Revision 2165 org.gvsig.tools/library/trunk/org.gvsig.tools/org.gvsig.tools.swing/org.gvsig.tools.swing.impl/src/main/java/org/gvsig/tools/swing/impl/pickercontroller/DatePickerControllerImpl.java
DatePickerControllerImpl.java | ||
---|---|---|
1 | 1 |
package org.gvsig.tools.swing.impl.pickercontroller; |
2 | 2 |
|
3 |
import java.awt.Color; |
|
3 | 4 |
import static java.awt.Component.RIGHT_ALIGNMENT; |
4 | 5 |
import java.awt.event.ActionEvent; |
5 | 6 |
import java.net.URL; |
... | ... | |
12 | 13 |
import javax.swing.JButton; |
13 | 14 |
import javax.swing.JFormattedTextField; |
14 | 15 |
import javax.swing.JPopupMenu; |
16 |
import javax.swing.event.DocumentEvent; |
|
17 |
import javax.swing.event.DocumentListener; |
|
18 |
import javax.swing.text.Document; |
|
15 | 19 |
import javax.swing.text.JTextComponent; |
16 |
import javax.swing.text.DateFormatter; |
|
17 |
import javax.swing.text.DefaultFormatterFactory; |
|
18 | 20 |
import javax.swing.text.MaskFormatter; |
19 | 21 |
import org.apache.commons.lang3.StringUtils; |
20 | 22 |
import org.freixas.jcalendar.DateEvent; |
... | ... | |
33 | 35 |
* @author jjdelcerro |
34 | 36 |
*/ |
35 | 37 |
@SuppressWarnings("UseSpecificCatch") |
36 |
public class DatePickerControllerImpl |
|
37 |
extends AbstractPickerController<Date> |
|
38 |
implements DatePickerController |
|
39 |
{ |
|
40 |
|
|
41 |
private final JButton btnDate; |
|
42 |
private final JTextComponent txtDate; |
|
43 |
private JCalendar jcalendar; |
|
44 |
private DateFormat df; |
|
45 |
private static final Logger LOG = LoggerFactory.getLogger(DatePickerControllerImpl.class); |
|
46 |
|
|
47 |
public static void selfRegister() { |
|
48 |
URL imageResource = DatePickerControllerImpl.class.getClassLoader().getResource("org/gvsig/tools/swing/picker/picker-date.png"); |
|
49 |
if (imageResource != null) { |
|
50 |
IconThemeManager iconThemeManager = ToolsSwingLocator.getIconThemeManager(); |
|
51 |
IconTheme theme = iconThemeManager.getCurrent(); |
|
52 |
ImageIcon icon = new ImageIcon(imageResource); |
|
53 |
theme.registerDefault("tools", "picker", "picker-date", icon, imageResource); |
|
54 |
} |
|
38 |
public class DatePickerControllerImpl |
|
39 |
extends AbstractPickerController<Date> |
|
40 |
implements DatePickerController { |
|
41 |
|
|
42 |
private final JButton btnDate; |
|
43 |
private final JTextComponent txtDate; |
|
44 |
private JCalendar jcalendar; |
|
45 |
private DateFormat df; |
|
46 |
private static final Logger LOG = LoggerFactory.getLogger(DatePickerControllerImpl.class); |
|
47 |
|
|
48 |
public static void selfRegister() { |
|
49 |
URL imageResource = DatePickerControllerImpl.class.getClassLoader().getResource("org/gvsig/tools/swing/picker/picker-date.png"); |
|
50 |
if (imageResource != null) { |
|
51 |
IconThemeManager iconThemeManager = ToolsSwingLocator.getIconThemeManager(); |
|
52 |
IconTheme theme = iconThemeManager.getCurrent(); |
|
53 |
ImageIcon icon = new ImageIcon(imageResource); |
|
54 |
theme.registerDefault("tools", "picker", "picker-date", icon, imageResource); |
|
55 | 55 |
} |
56 |
|
|
57 |
public DatePickerControllerImpl(JTextComponent txtDate, JButton btnDate) { |
|
58 |
this.txtDate = txtDate; |
|
59 |
ToolsSwingLocator.getToolsSwingManager().addClearButton(txtDate, (ActionEvent e) -> { |
|
60 |
set(null); |
|
61 |
txtDate.setText(""); |
|
62 |
}); |
|
63 |
this.df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); |
|
64 |
if( this.txtDate instanceof JFormattedTextField ) { |
|
65 |
JFormattedTextField ftf = (JFormattedTextField) this.txtDate; |
|
66 |
DefaultFormatterFactory formatterFactory = new DefaultFormatterFactory(new DateFormatter(df)); |
|
67 |
ftf.setFormatterFactory(formatterFactory); |
|
68 |
ftf.setFocusLostBehavior(JFormattedTextField.COMMIT_OR_REVERT); |
|
69 |
if( df instanceof SimpleDateFormat ) { |
|
70 |
try { |
|
71 |
SimpleDateFormat sdf = (SimpleDateFormat) this.df; |
|
72 |
String s = sdf.toPattern(); // d/M/yy H:mm:ss |
|
73 |
s = s.replace("d", "##"); |
|
74 |
s = s.replace("MM", "##"); |
|
75 |
s = s.replace("M", "##"); |
|
76 |
s = s.replace("y", "#"); |
|
77 |
s = s.replace("HH", "##"); |
|
78 |
s = s.replace("H", "##"); |
|
79 |
s = s.replace("m", "#"); |
|
80 |
|
|
81 |
s = s.replace("s", "#"); |
|
82 |
MaskFormatter mask = new MaskFormatter(s); |
|
83 |
mask.setPlaceholderCharacter('_'); |
|
84 |
//mask.setPlaceholder(sdf.format(new Date())); |
|
85 |
mask.setAllowsInvalid(false); |
|
86 |
mask.install(ftf); |
|
87 |
} catch (Exception ex) { |
|
88 |
LOG.warn("Not been able to create mask", ex); |
|
89 |
} |
|
56 |
} |
|
57 |
private final Document document; |
|
58 |
private final DocumentListener documentListener; |
|
59 |
private final Color colorOk; |
|
60 |
private final Color colorErr; |
|
61 |
private String emptyValue; |
|
62 |
|
|
63 |
public DatePickerControllerImpl(JTextComponent txtDate, JButton btnDate) { |
|
64 |
this.txtDate = txtDate; |
|
65 |
if (btnDate == null) { |
|
66 |
btnDate = new JButton(); |
|
67 |
} |
|
68 |
ToolsSwingLocator.getToolsSwingManager().addClearButton(txtDate, (ActionEvent e) -> { |
|
69 |
set(null); |
|
70 |
}); |
|
71 |
this.df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()); |
|
72 |
this.df.setLenient(false); |
|
73 |
if (this.txtDate instanceof JFormattedTextField) { |
|
74 |
JFormattedTextField ftf = (JFormattedTextField) this.txtDate; |
|
75 |
if (df instanceof SimpleDateFormat) { |
|
76 |
try { |
|
77 |
SimpleDateFormat sdf = (SimpleDateFormat) this.df; |
|
78 |
String s = sdf.toPattern(); |
|
79 |
if( !s.contains("yyyy") ) { |
|
80 |
if( s.contains("yy") ) { |
|
81 |
s = s.replace("yy", "yyyy"); |
|
82 |
} else if( s.contains("y") ) { |
|
83 |
s = s.replace("y", "yyyy"); |
|
90 | 84 |
} |
85 |
} |
|
86 |
if( !s.contains("dd") ) { |
|
87 |
if( s.contains("d") ) { |
|
88 |
s = s.replace("d", "dd"); |
|
89 |
} |
|
90 |
} |
|
91 |
if( !s.contains("MM") ) { |
|
92 |
if( s.contains("M") ) { |
|
93 |
s = s.replace("M", "MM"); |
|
94 |
} |
|
95 |
} |
|
96 |
sdf.applyPattern(s); |
|
97 |
s = s.replace("y", "#"); |
|
98 |
s = s.replace("d", "#"); |
|
99 |
s = s.replace("M", "#"); |
|
100 |
MaskFormatter mask = new MaskFormatter(s); |
|
101 |
mask.setPlaceholderCharacter('_'); |
|
102 |
this.emptyValue = s.replace("#","_"); |
|
103 |
mask.setAllowsInvalid(false); |
|
104 |
mask.install(ftf); |
|
105 |
} catch (Exception ex) { |
|
106 |
LOG.warn("Not been able to create mask", ex); |
|
91 | 107 |
} |
92 |
this.btnDate = btnDate; |
|
93 |
this.txtDate.setAlignmentX(RIGHT_ALIGNMENT); |
|
94 |
this.txtDate.setEditable(true); |
|
95 |
|
|
96 |
this.btnDate.setIcon(this.getIcon("picker-date")); |
|
97 |
this.btnDate.setText(""); |
|
98 |
|
|
99 |
this.btnDate.addActionListener((ActionEvent e) -> { |
|
100 |
doShowCalendar(); |
|
101 |
}); |
|
108 |
} |
|
102 | 109 |
} |
110 |
this.colorOk = this.txtDate.getBackground(); |
|
111 |
this.colorErr = new Color(255,225,232); |
|
112 |
this.btnDate = btnDate; |
|
113 |
this.txtDate.setAlignmentX(RIGHT_ALIGNMENT); |
|
114 |
this.txtDate.setEditable(true); |
|
115 |
this.document = this.txtDate.getDocument(); |
|
116 |
this.documentListener = new DocumentListener() { |
|
117 |
@Override |
|
118 |
public void insertUpdate(DocumentEvent e) { |
|
119 |
checkContents(); |
|
120 |
} |
|
103 | 121 |
|
104 |
@Override |
|
105 |
public boolean isValid() { |
|
106 |
if( StringUtils.isBlank(this.txtDate.getText()) ) { |
|
107 |
return true; |
|
122 |
@Override |
|
123 |
public void removeUpdate(DocumentEvent e) { |
|
124 |
checkContents(); |
|
108 | 125 |
} |
109 |
try { |
|
110 |
Date date = this.df.parse(this.txtDate.getText()); |
|
111 |
return true; |
|
112 |
} catch (ParseException ex) { |
|
113 |
return false; |
|
126 |
|
|
127 |
@Override |
|
128 |
public void changedUpdate(DocumentEvent e) { |
|
129 |
checkContents(); |
|
114 | 130 |
} |
131 |
}; |
|
132 |
document.addDocumentListener(this.documentListener); |
|
133 |
|
|
134 |
this.btnDate.setIcon(this.getIcon("picker-date")); |
|
135 |
if (this.btnDate.getText().equals("...")) { |
|
136 |
this.btnDate.setText(""); |
|
115 | 137 |
} |
116 | 138 |
|
117 |
@Override |
|
118 |
public boolean isEmpty() { |
|
119 |
if( StringUtils.isBlank(this.txtDate.getText()) ) { |
|
120 |
return true; |
|
121 |
} |
|
122 |
try { |
|
123 |
Date date = this.df.parse(this.txtDate.getText()); |
|
124 |
return false; |
|
125 |
} catch (ParseException ex) { |
|
126 |
return true; |
|
127 |
} |
|
139 |
this.btnDate.addActionListener((ActionEvent e) -> { |
|
140 |
doShowCalendar(); |
|
141 |
}); |
|
142 |
} |
|
143 |
|
|
144 |
@Override |
|
145 |
public void uninstall() { |
|
146 |
|
|
147 |
} |
|
148 |
|
|
149 |
private String getText() { |
|
150 |
String s = this.txtDate.getText(); |
|
151 |
if( this.emptyValue!=null && this.emptyValue.equals(s) ) { |
|
152 |
return ""; |
|
128 | 153 |
} |
154 |
s = s.replace("_", ""); |
|
155 |
return s; |
|
156 |
} |
|
129 | 157 |
|
130 |
@Override |
|
131 |
public Date get() { |
|
132 |
if( StringUtils.isBlank(this.txtDate.getText()) ) { |
|
133 |
return null; |
|
134 |
} |
|
135 |
try { |
|
136 |
Date date = this.df.parse(this.txtDate.getText()); |
|
137 |
return date; |
|
138 |
} catch (ParseException ex) { |
|
139 |
return null; |
|
140 |
} |
|
158 |
private void checkContents() { |
|
159 |
if( this.isValid() ) { |
|
160 |
this.txtDate.setBackground(colorOk); |
|
161 |
} else { |
|
162 |
this.txtDate.setBackground(colorErr); |
|
141 | 163 |
} |
164 |
} |
|
142 | 165 |
|
143 |
@Override |
|
144 |
public void set(Date date) { |
|
145 |
if (txtDate instanceof JFormattedTextField) { |
|
146 |
((JFormattedTextField) txtDate).setValue(date); |
|
147 |
} else { |
|
148 |
this.txtDate.setText(this.df.format(date)); |
|
149 |
} |
|
166 |
@Override |
|
167 |
public boolean isValid() { |
|
168 |
if (StringUtils.isBlank(this.getText())) { |
|
169 |
return true; |
|
150 | 170 |
} |
171 |
try { |
|
172 |
Date date = this.df.parse(this.getText()); |
|
173 |
return true; |
|
174 |
} catch (ParseException ex) { |
|
175 |
return false; |
|
176 |
} |
|
177 |
} |
|
151 | 178 |
|
152 |
@Override
|
|
153 |
public void setEnabled(boolean enabled) {
|
|
154 |
this.btnDate.setEnabled(enabled);
|
|
155 |
this.txtDate.setEnabled(enabled);
|
|
179 |
@Override |
|
180 |
public boolean isEmpty() {
|
|
181 |
if (StringUtils.isBlank(this.getText())) {
|
|
182 |
return true;
|
|
156 | 183 |
} |
184 |
try { |
|
185 |
Date date = this.df.parse(this.getText()); |
|
186 |
return false; |
|
187 |
} catch (ParseException ex) { |
|
188 |
return true; |
|
189 |
} |
|
190 |
} |
|
157 | 191 |
|
158 |
@Override |
|
159 |
public boolean isEnabled() { |
|
160 |
return this.btnDate.isEnabled(); |
|
192 |
@Override |
|
193 |
public Date get() { |
|
194 |
if (StringUtils.isBlank(this.getText())) { |
|
195 |
return null; |
|
161 | 196 |
} |
197 |
try { |
|
198 |
Date date = this.df.parse(this.getText()); |
|
199 |
return date; |
|
200 |
} catch (ParseException ex) { |
|
201 |
return null; |
|
202 |
} |
|
203 |
} |
|
162 | 204 |
|
163 |
private void doShowCalendar() { |
|
164 |
if( !this.isEditable() ) { |
|
165 |
return; |
|
166 |
} |
|
167 |
JPopupMenu menu = new JPopupMenu(); |
|
168 |
menu.add(getJCalendar()); |
|
169 |
Date v = this.get(); |
|
170 |
if (v != null) { |
|
171 |
getJCalendar().setDate(v); |
|
172 |
} |
|
173 |
menu.show(this.txtDate, 0, this.txtDate.getY() + this.txtDate.getPreferredSize().height); |
|
174 |
this.set(getJCalendar().getDate()); |
|
175 |
this.fireChangeEvent(); |
|
205 |
@Override |
|
206 |
public void set(Date date) { |
|
207 |
if( date == null ) { |
|
208 |
this.txtDate.setText(""); |
|
209 |
return; |
|
176 | 210 |
} |
211 |
this.txtDate.setText(this.df.format(date)); |
|
212 |
} |
|
177 | 213 |
|
178 |
protected JCalendar getJCalendar() { |
|
179 |
if (this.jcalendar == null) { |
|
180 |
this.jcalendar = new JCalendar(); |
|
181 |
this.jcalendar.addDateListener((DateEvent arg0) -> { |
|
182 |
set(getJCalendar().getDate()); |
|
183 |
fireChangeEvent(); |
|
184 |
}); |
|
185 |
} |
|
186 |
return (JCalendar) this.jcalendar; |
|
214 |
@Override |
|
215 |
public void setEnabled(boolean enabled) { |
|
216 |
this.btnDate.setEnabled(enabled); |
|
217 |
this.txtDate.setEnabled(enabled); |
|
218 |
} |
|
219 |
|
|
220 |
@Override |
|
221 |
public boolean isEnabled() { |
|
222 |
return this.btnDate.isEnabled(); |
|
223 |
} |
|
224 |
|
|
225 |
private void doShowCalendar() { |
|
226 |
if (!this.isEditable()) { |
|
227 |
return; |
|
187 | 228 |
} |
229 |
JPopupMenu menu = new JPopupMenu(); |
|
230 |
menu.add(getJCalendar()); |
|
231 |
Date v = this.get(); |
|
232 |
if (v != null) { |
|
233 |
getJCalendar().setDate(v); |
|
234 |
} |
|
235 |
menu.show(this.txtDate, 0, this.txtDate.getY() + this.txtDate.getPreferredSize().height); |
|
236 |
} |
|
188 | 237 |
|
189 |
@Override |
|
190 |
public void coerceAndSet(Object value) { |
|
191 |
this.set((Date) this.coerce(DataTypes.DATE, value, new Date())); |
|
238 |
protected JCalendar getJCalendar() { |
|
239 |
if (this.jcalendar == null) { |
|
240 |
this.jcalendar = new JCalendar(); |
|
241 |
this.jcalendar.addDateListener((DateEvent arg0) -> { |
|
242 |
set(getJCalendar().getDate()); |
|
243 |
fireChangeEvent(); |
|
244 |
}); |
|
192 | 245 |
} |
193 |
|
|
246 |
return (JCalendar) this.jcalendar; |
|
247 |
} |
|
248 |
|
|
249 |
@Override |
|
250 |
public void coerceAndSet(Object value) { |
|
251 |
this.set((Date) this.coerce(DataTypes.DATE, value, new Date())); |
|
252 |
} |
|
253 |
|
|
194 | 254 |
} |
Also available in: Unified diff