Statistics
| Revision:

gvsig-tools / 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 @ 2491

History | View | Annotate | Download (8.25 KB)

1
package org.gvsig.tools.swing.impl.pickercontroller;
2

    
3
import java.awt.Color;
4
import static java.awt.Component.RIGHT_ALIGNMENT;
5
import java.awt.Cursor;
6
import java.awt.event.ActionEvent;
7
import java.awt.event.ActionListener;
8
import java.net.URL;
9
import java.text.DateFormat;
10
import java.text.ParseException;
11
import java.text.SimpleDateFormat;
12
import java.util.Date;
13
import java.util.Locale;
14
import javax.swing.ImageIcon;
15
import javax.swing.JButton;
16
import javax.swing.JFormattedTextField;
17
import javax.swing.JPopupMenu;
18
import javax.swing.event.DocumentEvent;
19
import javax.swing.event.DocumentListener;
20
import javax.swing.text.Document;
21
import javax.swing.text.JTextComponent;
22
import javax.swing.text.MaskFormatter;
23
import org.apache.commons.lang3.StringUtils;
24
import org.freixas.jcalendar.DateEvent;
25
import org.freixas.jcalendar.JCalendar;
26
import org.gvsig.tools.dataTypes.DataTypes;
27
import org.gvsig.tools.swing.api.ToolsSwingLocator;
28
import org.gvsig.tools.swing.api.ToolsSwingManager;
29
import org.gvsig.tools.swing.api.pickercontroller.AbstractPickerController;
30
import org.gvsig.tools.swing.api.pickercontroller.DatePickerController;
31
import org.gvsig.tools.swing.icontheme.IconTheme;
32
import org.gvsig.tools.swing.icontheme.IconThemeManager;
33
import org.gvsig.tools.swing.impl.ClearButtonUtils;
34
import org.gvsig.tools.swing.impl.ContextMenuUtils;
35

    
36
/**
37
 *
38
 * @author jjdelcerro
39
 */
40
@SuppressWarnings("UseSpecificCatch")
41
public class DatePickerControllerImpl
42
        extends AbstractPickerController<Date>
43
        implements DatePickerController {
44

    
45
  private final JButton btnDate;
46
  private final JTextComponent txtDate;
47
  private JCalendar jcalendar;
48
  private DateFormat df;
49

    
50
  public static void selfRegister() {
51
    URL imageResource = DatePickerControllerImpl.class.getClassLoader().getResource("org/gvsig/tools/swing/picker/picker-date.png");
52
    if (imageResource != null) {
53
      IconThemeManager iconThemeManager = ToolsSwingLocator.getIconThemeManager();
54
      IconTheme theme = iconThemeManager.getCurrent();
55
      ImageIcon icon = new ImageIcon(imageResource);
56
      theme.registerDefault("tools", "picker", "picker-date", icon, imageResource);
57
    }
58
  }
59
  private final Document document;
60
  private final DocumentListener documentListener;
61
  private final Color colorOk;
62
  private final Color colorErr;
63
  private String emptyText;
64
  private MaskFormatter mask;
65
  private final ActionListener buttonListener;
66
  private boolean isMyClearButton;
67

    
68
  public DatePickerControllerImpl(JTextComponent txtDate, JButton btnDate) {
69
    this.txtDate = txtDate;
70
    this.txtDate.setOpaque(true);
71
    if (btnDate == null) {
72
      btnDate = new JButton();
73
    }    
74
    this.isMyClearButton = false;
75
    if( !ClearButtonUtils.hasClearButton(txtDate) ) {
76
        ClearButtonUtils.addClearButton(txtDate, (ActionEvent e) -> { set(null); });
77
        this.isMyClearButton = true;
78
    }
79
    ContextMenuUtils.setDefaultContextMenu(this.txtDate);
80
    this.df = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
81
    this.df.setLenient(false);
82
    if (this.txtDate instanceof JFormattedTextField) {
83
      JFormattedTextField ftf = (JFormattedTextField) this.txtDate;
84
      if (df instanceof SimpleDateFormat) {
85
        try {
86
          SimpleDateFormat sdf = (SimpleDateFormat) this.df;
87
          String s = sdf.toPattern(); 
88
          if( !s.contains("yyyy") ) {
89
            if( s.contains("yy") ) {
90
              s = s.replace("yy", "yyyy");
91
            } else if( s.contains("y") ) {
92
              s = s.replace("y", "yyyy");
93
            }
94
          }
95
          if( !s.contains("dd") ) {
96
            if( s.contains("d") ) {
97
              s = s.replace("d", "dd");
98
            }
99
          }
100
          if( !s.contains("MM") ) {
101
            if( s.contains("M") ) {
102
              s = s.replace("M", "MM");
103
            }
104
          }
105
          sdf.applyPattern(s);
106
          s = s.replace("y", "#");
107
          s = s.replace("d", "#");
108
          s = s.replace("M", "#");
109
          this.mask = new MaskFormatter(s);
110
          mask.setPlaceholderCharacter('_');
111
          this.emptyText = s.replace("#","_");
112
          mask.setAllowsInvalid(false);
113
          mask.install(ftf);
114
        } catch (Exception ex) {
115
          LOG.warn("Not been able to create mask", ex);
116
        }
117
      }
118
    }
119
    this.colorOk = this.txtDate.getBackground();
120
    this.colorErr = new Color(255,225,232);    
121
    this.btnDate = btnDate;
122
    this.btnDate.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
123
    this.txtDate.setAlignmentX(RIGHT_ALIGNMENT);
124
    this.txtDate.setEditable(true);
125
    this.document = this.txtDate.getDocument();
126
    this.documentListener = new DocumentListener() {
127
      @Override
128
      public void insertUpdate(DocumentEvent e) {
129
        checkContents();
130
      }
131

    
132
      @Override
133
      public void removeUpdate(DocumentEvent e) {
134
        checkContents();
135
      }
136

    
137
      @Override
138
      public void changedUpdate(DocumentEvent e) {
139
        checkContents();
140
      }
141
    };
142
    document.addDocumentListener(this.documentListener);
143

    
144
    this.btnDate.setIcon(this.getIcon("picker-date"));
145
    if (this.btnDate.getText().equals("...")) {
146
      this.btnDate.setText("");
147
    }
148

    
149
    this.buttonListener = (ActionEvent e) -> {
150
      doShowCalendar();
151
    };
152
    this.btnDate.addActionListener(this.buttonListener);
153
  }
154

    
155
  @Override
156
  public void uninstall() {
157
    this.document.removeDocumentListener(documentListener);
158
    if( this.mask!=null ) {
159
      this.mask.uninstall();
160
    }
161
    this.txtDate.setOpaque(false);
162
    this.txtDate.setBackground(colorOk);
163
    this.btnDate.removeActionListener(buttonListener);    
164
    if( this.isMyClearButton ) {
165
        ToolsSwingLocator.getToolsSwingManager().removeClearButton(txtDate);
166
        this.isMyClearButton = false;
167
    }
168
  }
169
  
170
  protected String getText() {
171
    String s = this.txtDate.getText();
172
    if( this.emptyText!=null && this.emptyText.equals(s) ) {
173
      return "";
174
    }
175
    s = s.replace("_", "");
176
    return s;
177
  }
178

    
179
  protected void checkContents() {
180
    if( this.isValid() ) {
181
      this.txtDate.setBackground(colorOk);
182
    } else {
183
      this.txtDate.setBackground(colorErr);
184
    }
185
  }
186

    
187
  @Override
188
  public boolean isValid() {
189
    if (StringUtils.isBlank(this.getText())) {
190
      return true;
191
    }
192
    try {
193
      Date date = this.df.parse(this.getText());
194
      return true;
195
    } catch (ParseException ex) {
196
      return false;
197
    }
198
  }
199

    
200
  @Override
201
  public boolean isEmpty() {
202
    if (StringUtils.isBlank(this.getText())) {
203
      return true;
204
    }
205
    try {
206
      Date date = this.df.parse(this.getText());
207
      return false;
208
    } catch (ParseException ex) {
209
      return true;
210
    }
211
  }
212

    
213
    @Override
214
  public Date get() {
215
    if (StringUtils.isBlank(this.getText())) {
216
      return null;
217
    }
218
    try {
219
      Date date = this.df.parse(this.getText());
220
      return date;
221
    } catch (Exception ex) {
222
      throw new NumberFormatException("Unable to parse string into date: "+this.getText());
223
    }
224
  }
225

    
226
  @Override
227
  public void set(Date date) {
228
    if( date == null ) {
229
      this.txtDate.setText("");
230
      return;
231
    }
232
    this.txtDate.setText(this.df.format(date));
233
  }
234

    
235
  @Override
236
  public void setEnabled(boolean enabled) {
237
    this.btnDate.setEnabled(enabled);
238
    this.txtDate.setEnabled(enabled);
239
  }
240

    
241
  @Override
242
  public boolean isEnabled() {
243
    return this.btnDate.isEnabled();
244
  }
245

    
246
  private void doShowCalendar() {
247
    if (!this.isEditable()) {
248
      return;
249
    }
250
    JPopupMenu menu = new JPopupMenu();
251
    menu.add(getJCalendar());
252
    Date v = new Date();
253
    if( !isEmpty() ) {
254
      v = this.get();
255
    }
256
    if (v != null) {
257
      getJCalendar().setDate(v);
258
    }
259
    menu.show(this.txtDate, 0, this.txtDate.getY() + this.txtDate.getPreferredSize().height);
260
  }
261

    
262
  protected JCalendar getJCalendar() {
263
    if (this.jcalendar == null) {
264
      this.jcalendar = new JCalendar();
265
      this.jcalendar.addDateListener((DateEvent arg0) -> {
266
        set(getJCalendar().getDate());
267
        fireChangeEvent();
268
      });
269
    }
270
    return (JCalendar) this.jcalendar;
271
  }
272

    
273
  @Override
274
  public void coerceAndSet(Object value) {
275
    this.set((Date) this.coerce(DataTypes.DATE, value, new Date()));
276
  }
277

    
278
  @Override
279
  public DateFormat getDateFormat() {
280
    return this.df;
281
  }
282

    
283
  @Override
284
  public MaskFormatter  getMask() {
285
      return this.mask;
286
  }
287

    
288
  @Override
289
  public void setEmptyText(String emptyText) {
290
    this.emptyText = emptyText;
291
  }
292

    
293
}