OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 150 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 150 Rev 153
1
package org.jopencalendar.ui;
1
package org.jopencalendar.ui;
2
 
2
 
3
import java.awt.Color;
3
import java.awt.Color;
4
import java.awt.Component;
4
import java.awt.Component;
5
import java.awt.Dimension;
5
import java.awt.Dimension;
6
import java.awt.FlowLayout;
6
import java.awt.FlowLayout;
7
import java.awt.GraphicsConfiguration;
7
import java.awt.GraphicsConfiguration;
8
import java.awt.GraphicsDevice;
8
import java.awt.GraphicsDevice;
9
import java.awt.GraphicsEnvironment;
9
import java.awt.GraphicsEnvironment;
10
import java.awt.Insets;
10
import java.awt.Insets;
11
import java.awt.Point;
11
import java.awt.Point;
12
import java.awt.Rectangle;
12
import java.awt.Rectangle;
13
import java.awt.Toolkit;
13
import java.awt.Toolkit;
14
import java.awt.Window;
14
import java.awt.Window;
15
import java.awt.event.ActionEvent;
15
import java.awt.event.ActionEvent;
16
import java.awt.event.ActionListener;
16
import java.awt.event.ActionListener;
17
import java.awt.event.WindowEvent;
17
import java.awt.event.WindowEvent;
18
import java.awt.event.WindowFocusListener;
18
import java.awt.event.WindowFocusListener;
19
import java.beans.PropertyChangeEvent;
19
import java.beans.PropertyChangeEvent;
20
import java.beans.PropertyChangeListener;
20
import java.beans.PropertyChangeListener;
21
import java.text.DateFormat;
21
import java.text.DateFormat;
22
import java.text.Format;
22
import java.text.Format;
23
import java.text.ParseException;
23
import java.text.ParseException;
24
import java.util.ArrayList;
24
import java.util.ArrayList;
25
import java.util.Calendar;
25
import java.util.Calendar;
26
import java.util.Date;
26
import java.util.Date;
27
import java.util.List;
27
import java.util.List;
28
 
28
 
29
import javax.swing.AbstractAction;
29
import javax.swing.AbstractAction;
30
import javax.swing.Action;
30
import javax.swing.Action;
31
import javax.swing.BorderFactory;
31
import javax.swing.BorderFactory;
32
import javax.swing.ImageIcon;
32
import javax.swing.ImageIcon;
33
import javax.swing.JButton;
33
import javax.swing.JButton;
34
import javax.swing.JComponent;
34
import javax.swing.JComponent;
35
import javax.swing.JDialog;
35
import javax.swing.JDialog;
36
import javax.swing.JFormattedTextField;
36
import javax.swing.JFormattedTextField;
37
import javax.swing.JPanel;
37
import javax.swing.JPanel;
38
import javax.swing.JTextField;
38
import javax.swing.JTextField;
39
import javax.swing.SwingUtilities;
39
import javax.swing.SwingUtilities;
40
 
40
 
41
public class DatePicker extends JPanel {
41
public class DatePicker extends JPanel {
42
 
42
 
43
    private JFormattedTextField text;
43
    private JFormattedTextField text;
44
    private JDialog dialog;
44
    private JDialog dialog;
45
    private long dialogLostFocusTime;
45
    private long dialogLostFocusTime;
46
    private DatePickerPanel pickerPanel;
46
    private DatePickerPanel pickerPanel;
47
    private Date date;
47
    private Date date;
48
    private List<ActionListener> actionListeners = new ArrayList<ActionListener>();
48
    private List<ActionListener> actionListeners = new ArrayList<ActionListener>();
49
    private static final long RELEASE_TIME_MS = 500;
49
    private static final long RELEASE_TIME_MS = 500;
50
    private JButton button;
50
    private JButton button;
51
 
51
 
52
    public DatePicker() {
52
    public DatePicker() {
53
        this(true);
53
        this(true);
54
    }
54
    }
55
 
55
 
56
    public DatePicker(boolean useEditor) {
56
    public DatePicker(boolean useEditor) {
57
        this(useEditor, false);
57
        this(useEditor, false);
58
    }
58
    }
59
 
59
 
60
    public DatePicker(boolean useEditor, boolean fillWithCurrentDate) {
60
    public DatePicker(boolean useEditor, boolean fillWithCurrentDate) {
61
        this(DateFormat.getDateInstance(), useEditor, fillWithCurrentDate);
61
        this(DateFormat.getDateInstance(), useEditor, fillWithCurrentDate);
62
    }
62
    }
63
 
63
 
64
    public DatePicker(Format dateFormat, boolean useEditor, boolean fillWithCurrentDate) {
64
    public DatePicker(Format dateFormat, boolean useEditor, boolean fillWithCurrentDate) {
65
        this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
65
        this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
66
        this.setOpaque(false);
66
        this.setOpaque(false);
67
        if (useEditor) {
67
        if (useEditor) {
68
            text = new JFormattedTextField(dateFormat);
68
            text = new JFormattedTextField(dateFormat);
69
            text.setColumns(12);
69
            text.setColumns(12);
70
            text.addPropertyChangeListener("value", new PropertyChangeListener() {
70
            text.addPropertyChangeListener("value", new PropertyChangeListener() {
71
                @Override
71
                @Override
72
                public void propertyChange(PropertyChangeEvent evt) {
72
                public void propertyChange(PropertyChangeEvent evt) {
73
                    setDate((Date) evt.getNewValue());
73
                    setDate((Date) evt.getNewValue());
74
                }
74
                }
75
            });
75
            });
76
            this.add(text);
76
            this.add(text);
77
            JPanel spacer = new JPanel();
77
            JPanel spacer = new JPanel();
78
            spacer.setOpaque(false);
78
            spacer.setOpaque(false);
79
            spacer.setMinimumSize(new Dimension(3, 5));
79
            spacer.setMinimumSize(new Dimension(3, 5));
80
            spacer.setPreferredSize(new Dimension(3, 5));
80
            spacer.setPreferredSize(new Dimension(3, 5));
81
            this.add(spacer);
81
            this.add(spacer);
82
        }
82
        }
83
 
83
 
-
 
84
        String iconFileName = "calendar.png";
-
 
85
        if (getFont().getSize() > 16) {
-
 
86
            iconFileName = "calendar_2x.png";
-
 
87
        }
84
        final ImageIcon icon = new ImageIcon(this.getClass().getResource("calendar.png"));
88
        final ImageIcon icon = new ImageIcon(this.getClass().getResource(iconFileName));
85
        button = new JButton(new AbstractAction(null, icon) {
89
        button = new JButton(new AbstractAction(null, icon) {
86
 
90
 
87
            @Override
91
            @Override
88
            public void actionPerformed(ActionEvent e) {
92
            public void actionPerformed(ActionEvent e) {
89
                final JComponent source = (JComponent) e.getSource();
-
 
90
 
-
 
91
                if (text != null) {
-
 
92
                    // if the button isn't focusable, no FOCUS_LOST will occur and the text won't
-
 
93
                    // get
-
 
94
                    // committed (or reverted). So act as if the user requested a commit, so that
-
 
95
                    // invalidEdit() can be called (usually causing a beep).
-
 
96
                    if (!source.isFocusable()) {
-
 
97
                        for (final Action a : text.getActions()) {
-
 
98
                            final String name = (String) a.getValue(Action.NAME);
-
 
99
                            if (JTextField.notifyAction.equals(name))
-
 
100
                                a.actionPerformed(new ActionEvent(text, e.getID(), null));
-
 
101
                        }
-
 
102
                    }
-
 
103
 
-
 
104
                    // if after trying to commit, the value is invalid then don't show the popup
-
 
105
                    if (!text.isEditValid())
-
 
106
                        return;
-
 
107
                }
-
 
108
                if (dialog == null) {
-
 
109
                    final JDialog d = new JDialog(SwingUtilities.getWindowAncestor(DatePicker.this));
-
 
110
                    pickerPanel = new DatePickerPanel();
-
 
111
 
-
 
112
                    d.setContentPane(pickerPanel);
-
 
113
                    d.setUndecorated(true);
-
 
114
                    pickerPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
-
 
115
                    d.setSize(330, 270);
-
 
116
 
-
 
117
                    pickerPanel.addPropertyChangeListener(DatePickerPanel.TIME_IN_MILLIS, new PropertyChangeListener() {
-
 
118
 
-
 
119
                        @Override
-
 
120
                        public void propertyChange(PropertyChangeEvent evt) {
-
 
121
                            if (!DatePicker.this.isEditable())
-
 
122
                                return;
-
 
123
                            final Long millis = (Long) evt.getNewValue();
-
 
124
                            final Calendar c = Calendar.getInstance();
-
 
125
                            c.setTimeInMillis(millis);
-
 
126
                            setDate(c.getTime());
-
 
127
                            if (dialog != null) {
-
 
128
                                dialog.dispose();
-
 
129
                                dialog = null;
-
 
130
                            }
-
 
131
                            fireActionPerformed();
-
 
132
                        }
-
 
133
 
-
 
134
                    });
-
 
135
                    d.addWindowFocusListener(new WindowFocusListener() {
-
 
136
 
-
 
137
                        public void windowGainedFocus(WindowEvent e) {
-
 
138
                            // do nothing
-
 
139
                        }
-
 
140
 
-
 
141
                        public void windowLostFocus(WindowEvent e) {
-
 
142
                            if (dialog != null) {
-
 
143
                                final Window oppositeWindow = e.getOppositeWindow();
-
 
144
                                if (oppositeWindow != null && SwingUtilities.isDescendingFrom(oppositeWindow, dialog)) {
-
 
145
                                    return;
-
 
146
                                }
-
 
147
                                dialog.dispose();
-
 
148
                                dialog = null;
-
 
149
                            }
-
 
150
                            dialogLostFocusTime = System.currentTimeMillis();
-
 
151
                        }
-
 
152
 
-
 
153
                    });
-
 
154
                    dialog = d;
-
 
155
                }
-
 
156
                // Set picker panel date
-
 
157
                final Calendar calendar = Calendar.getInstance();
-
 
158
                if (date != null) {
-
 
159
                    calendar.setTime(date);
93
                calendarButtonPressed(e);
160
                    pickerPanel.setSelectedDate(calendar);
-
 
161
                } else {
-
 
162
                    pickerPanel.setSelectedDate(null);
-
 
163
                }
-
 
164
                // Show dialog
-
 
165
                final int x = source.getLocation().x;
-
 
166
                final int y = source.getLocation().y + source.getHeight();
-
 
167
                Point p = new Point(x, y);
-
 
168
                SwingUtilities.convertPointToScreen(p, DatePicker.this);
-
 
169
                p = adjustPopupLocationToFitScreen(p.x, p.y, dialog.getSize(), source.getSize());
-
 
170
                dialog.setLocation(p.x, p.y);
-
 
171
                final long time = System.currentTimeMillis() - dialogLostFocusTime;
-
 
172
                if (time > RELEASE_TIME_MS) {
-
 
173
                    dialog.setVisible(true);
-
 
174
                } else {
-
 
175
                    dialogLostFocusTime = System.currentTimeMillis() - RELEASE_TIME_MS;
-
 
176
                }
-
 
177
            }
94
            }
178
 
95
 
179
        });
96
        });
180
        button.setContentAreaFilled(false);
97
        button.setContentAreaFilled(false);
181
        button.setOpaque(false);
98
        button.setOpaque(false);
182
        button.setFocusable(false);
99
        button.setFocusable(false);
183
        button.setBorder(BorderFactory.createEmptyBorder());
100
        button.setBorder(BorderFactory.createEmptyBorder());
184
        this.add(button);
101
        this.add(button);
185
 
102
 
186
        // init & synchronize text field
103
        // init & synchronize text field
187
        setDate(fillWithCurrentDate ? new Date() : null, true);
104
        setDate(fillWithCurrentDate ? new Date() : null, true);
188
    }
105
    }
189
 
106
 
190
    public void setDate(Date date) {
107
    public void setDate(Date date) {
191
        this.setDate(date, false);
108
        this.setDate(date, false);
192
    }
109
    }
193
 
110
 
194
    public void setButtonVisible(boolean b) {
111
    public void setButtonVisible(boolean b) {
195
        this.button.setVisible(b);
112
        this.button.setVisible(b);
196
    }
113
    }
197
 
114
 
198
    private void setDate(Date date, boolean force) {
115
    private void setDate(Date date, boolean force) {
199
        Date oldDate = this.date;
116
        Date oldDate = this.date;
200
        if (force || !equals(oldDate, date)) {
117
        if (force || !equals(oldDate, date)) {
201
            this.date = date;
118
            this.date = date;
202
            if (text != null) {
119
            if (text != null) {
203
                text.setValue(date);
120
                text.setValue(date);
204
            }
121
            }
205
            firePropertyChange("value", oldDate, date);
122
            firePropertyChange("value", oldDate, date);
206
        }
123
        }
207
    }
124
    }
208
 
125
 
209
    public Date getDate() {
126
    public Date getDate() {
210
        return date;
127
        return date;
211
    }
128
    }
212
 
129
 
213
    public JFormattedTextField getEditor() {
130
    public JFormattedTextField getEditor() {
214
        return text;
131
        return text;
215
    }
132
    }
216
 
133
 
217
    public void setEditable(boolean b) {
134
    public void setEditable(boolean b) {
218
        if (this.text != null) {
135
        if (this.text != null) {
219
            this.text.setEditable(b);
136
            this.text.setEditable(b);
220
        }
137
        }
221
    }
138
    }
222
 
139
 
223
    public boolean isEditable() {
140
    public boolean isEditable() {
224
        if (this.text != null) {
141
        if (this.text != null) {
225
            return this.text.isEditable();
142
            return this.text.isEditable();
226
        }
143
        }
227
        return true;
144
        return true;
228
    }
145
    }
229
 
146
 
230
    @Override
147
    @Override
231
    public void setEnabled(boolean enabled) {
148
    public void setEnabled(boolean enabled) {
232
        super.setEnabled(enabled);
149
        super.setEnabled(enabled);
233
        for (final Component c : this.getComponents())
150
        for (final Component c : this.getComponents())
234
            c.setEnabled(enabled);
151
            c.setEnabled(enabled);
235
    }
152
    }
236
 
153
 
237
    public void addActionListener(ActionListener listener) {
154
    public void addActionListener(ActionListener listener) {
238
        this.actionListeners.add(listener);
155
        this.actionListeners.add(listener);
239
 
156
 
240
    }
157
    }
241
 
158
 
242
    public void removeActionListener(ActionListener listener) {
159
    public void removeActionListener(ActionListener listener) {
243
        this.actionListeners.remove(listener);
160
        this.actionListeners.remove(listener);
244
 
161
 
245
    }
162
    }
246
 
163
 
247
    public void fireActionPerformed() {
164
    public void fireActionPerformed() {
248
        for (ActionListener l : actionListeners) {
165
        for (ActionListener l : actionListeners) {
249
            l.actionPerformed(new ActionEvent(this, 0, "dateChanged"));
166
            l.actionPerformed(new ActionEvent(this, 0, "dateChanged"));
250
        }
167
        }
251
    }
168
    }
252
 
169
 
253
    /**
170
    /**
254
     * Tries to find GraphicsConfiguration that contains the mouse cursor position. Can return null.
171
     * Tries to find GraphicsConfiguration that contains the mouse cursor position. Can return null.
255
     */
172
     */
256
    private GraphicsConfiguration getCurrentGraphicsConfiguration(Point popupLocation) {
173
    private GraphicsConfiguration getCurrentGraphicsConfiguration(Point popupLocation) {
257
        GraphicsConfiguration gc = null;
174
        GraphicsConfiguration gc = null;
258
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
175
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
259
        GraphicsDevice[] gd = ge.getScreenDevices();
176
        GraphicsDevice[] gd = ge.getScreenDevices();
260
        for (int i = 0; i < gd.length; i++) {
177
        for (int i = 0; i < gd.length; i++) {
261
            if (gd[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
178
            if (gd[i].getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
262
                GraphicsConfiguration dgc = gd[i].getDefaultConfiguration();
179
                GraphicsConfiguration dgc = gd[i].getDefaultConfiguration();
263
                if (dgc.getBounds().contains(popupLocation)) {
180
                if (dgc.getBounds().contains(popupLocation)) {
264
                    gc = dgc;
181
                    gc = dgc;
265
                    break;
182
                    break;
266
                }
183
                }
267
            }
184
            }
268
        }
185
        }
269
 
186
 
270
        return gc;
187
        return gc;
271
    }
188
    }
272
 
189
 
273
    /**
190
    /**
274
     * Returns an point which has been adjusted to take into account of the desktop bounds, taskbar
191
     * Returns an point which has been adjusted to take into account of the desktop bounds, taskbar
275
     * and multi-monitor configuration.
192
     * and multi-monitor configuration.
276
     * <p>
193
     * <p>
277
     * This adustment may be cancelled by invoking the application with
194
     * This adustment may be cancelled by invoking the application with
278
     * -Djavax.swing.adjustPopupLocationToFit=false
195
     * -Djavax.swing.adjustPopupLocationToFit=false
279
     * 
196
     * 
280
     * @param popupSize
197
     * @param popupSize
281
     */
198
     */
282
    Point adjustPopupLocationToFitScreen(int xPosition, int yPosition, Dimension popupSize, Dimension buttonSize) {
199
    Point adjustPopupLocationToFitScreen(int xPosition, int yPosition, Dimension popupSize, Dimension buttonSize) {
283
        Point popupLocation = new Point(xPosition, yPosition);
200
        Point popupLocation = new Point(xPosition, yPosition);
284
 
201
 
285
        if (GraphicsEnvironment.isHeadless()) {
202
        if (GraphicsEnvironment.isHeadless()) {
286
            return popupLocation;
203
            return popupLocation;
287
        }
204
        }
288
 
205
 
289
        // Get screen bounds
206
        // Get screen bounds
290
        Rectangle scrBounds;
207
        Rectangle scrBounds;
291
        GraphicsConfiguration gc = getCurrentGraphicsConfiguration(popupLocation);
208
        GraphicsConfiguration gc = getCurrentGraphicsConfiguration(popupLocation);
292
        Toolkit toolkit = Toolkit.getDefaultToolkit();
209
        Toolkit toolkit = Toolkit.getDefaultToolkit();
293
        if (gc != null) {
210
        if (gc != null) {
294
            // If we have GraphicsConfiguration use it to get screen bounds
211
            // If we have GraphicsConfiguration use it to get screen bounds
295
            scrBounds = gc.getBounds();
212
            scrBounds = gc.getBounds();
296
        } else {
213
        } else {
297
            // If we don't have GraphicsConfiguration use primary screen
214
            // If we don't have GraphicsConfiguration use primary screen
298
            scrBounds = new Rectangle(toolkit.getScreenSize());
215
            scrBounds = new Rectangle(toolkit.getScreenSize());
299
        }
216
        }
300
 
217
 
301
        // Calculate the screen size that popup should fit
218
        // Calculate the screen size that popup should fit
302
 
219
 
303
        long popupRightX = (long) popupLocation.x + (long) popupSize.width;
220
        long popupRightX = (long) popupLocation.x + (long) popupSize.width;
304
        long popupBottomY = (long) popupLocation.y + (long) popupSize.height;
221
        long popupBottomY = (long) popupLocation.y + (long) popupSize.height;
305
        int scrWidth = scrBounds.width;
222
        int scrWidth = scrBounds.width;
306
        int scrHeight = scrBounds.height;
223
        int scrHeight = scrBounds.height;
307
 
224
 
308
        // Insets include the task bar. Take them into account.
225
        // Insets include the task bar. Take them into account.
309
        Insets scrInsets = toolkit.getScreenInsets(gc);
226
        Insets scrInsets = toolkit.getScreenInsets(gc);
310
        scrBounds.x += scrInsets.left;
227
        scrBounds.x += scrInsets.left;
311
        scrBounds.y += scrInsets.top;
228
        scrBounds.y += scrInsets.top;
312
        scrWidth -= scrInsets.left + scrInsets.right;
229
        scrWidth -= scrInsets.left + scrInsets.right;
313
        scrHeight -= scrInsets.top + scrInsets.bottom;
230
        scrHeight -= scrInsets.top + scrInsets.bottom;
314
 
231
 
315
        int scrRightX = scrBounds.x + scrWidth;
232
        int scrRightX = scrBounds.x + scrWidth;
316
        int scrBottomY = scrBounds.y + scrHeight;
233
        int scrBottomY = scrBounds.y + scrHeight;
317
 
234
 
318
        // Ensure that popup menu fits the screen
235
        // Ensure that popup menu fits the screen
319
        if (popupRightX > (long) scrRightX) {
236
        if (popupRightX > (long) scrRightX) {
320
            popupLocation.x = scrRightX - popupSize.width;
237
            popupLocation.x = scrRightX - popupSize.width;
321
            popupLocation.y = popupLocation.y - buttonSize.height - popupSize.height - 2;
238
            popupLocation.y = popupLocation.y - buttonSize.height - popupSize.height - 2;
322
        }
239
        }
323
 
240
 
324
        if (popupBottomY > (long) scrBottomY) {
241
        if (popupBottomY > (long) scrBottomY) {
325
            popupLocation.y = scrBottomY - popupSize.height;
242
            popupLocation.y = scrBottomY - popupSize.height;
326
            if (popupRightX + buttonSize.width < (long) scrRightX) {
243
            if (popupRightX + buttonSize.width < (long) scrRightX) {
327
                popupLocation.x += buttonSize.width;
244
                popupLocation.x += buttonSize.width;
328
            }
245
            }
329
        }
246
        }
330
 
247
 
331
        if (popupLocation.x < scrBounds.x) {
248
        if (popupLocation.x < scrBounds.x) {
332
            popupLocation.x = scrBounds.x;
249
            popupLocation.x = scrBounds.x;
333
        }
250
        }
334
 
251
 
335
        if (popupLocation.y < scrBounds.y) {
252
        if (popupLocation.y < scrBounds.y) {
336
            popupLocation.y = scrBounds.y;
253
            popupLocation.y = scrBounds.y;
337
        }
254
        }
338
 
255
 
339
        return popupLocation;
256
        return popupLocation;
340
    }
257
    }
341
 
258
 
342
    public void commitEdit() throws ParseException {
259
    public void commitEdit() throws ParseException {
343
        if (text != null) {
260
        if (text != null) {
344
            this.text.commitEdit();
261
            this.text.commitEdit();
345
        }
262
        }
346
    }
263
    }
347
 
264
 
-
 
265
    private void calendarButtonPressed(ActionEvent e) {
-
 
266
        final JComponent source = (JComponent) e.getSource();
-
 
267
 
-
 
268
        if (text != null) {
-
 
269
            // if the button isn't focusable, no FOCUS_LOST will occur and the text won't
-
 
270
            // get
-
 
271
            // committed (or reverted). So act as if the user requested a commit, so that
-
 
272
            // invalidEdit() can be called (usually causing a beep).
-
 
273
            if (!source.isFocusable()) {
-
 
274
                for (final Action a : text.getActions()) {
-
 
275
                    final String name = (String) a.getValue(Action.NAME);
-
 
276
                    if (JTextField.notifyAction.equals(name))
-
 
277
                        a.actionPerformed(new ActionEvent(text, e.getID(), null));
-
 
278
                }
-
 
279
            }
-
 
280
 
-
 
281
            // if after trying to commit, the value is invalid then don't show the popup
-
 
282
            if (!text.isEditValid())
-
 
283
                return;
-
 
284
        }
-
 
285
        if (dialog == null) {
-
 
286
            final JDialog d = new JDialog(SwingUtilities.getWindowAncestor(DatePicker.this));
-
 
287
            pickerPanel = new DatePickerPanel();
-
 
288
 
-
 
289
            d.setContentPane(pickerPanel);
-
 
290
            d.setUndecorated(true);
-
 
291
            pickerPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
-
 
292
            d.pack();
-
 
293
 
-
 
294
            pickerPanel.addPropertyChangeListener(DatePickerPanel.TIME_IN_MILLIS, new PropertyChangeListener() {
-
 
295
 
-
 
296
                @Override
-
 
297
                public void propertyChange(PropertyChangeEvent evt) {
-
 
298
                    if (!DatePicker.this.isEditable())
-
 
299
                        return;
-
 
300
                    final Long millis = (Long) evt.getNewValue();
-
 
301
                    final Calendar c = Calendar.getInstance();
-
 
302
                    c.setTimeInMillis(millis);
-
 
303
                    setDate(c.getTime());
-
 
304
                    if (dialog != null) {
-
 
305
                        dialog.dispose();
-
 
306
                        dialog = null;
-
 
307
                    }
-
 
308
                    fireActionPerformed();
-
 
309
                }
-
 
310
 
-
 
311
            });
-
 
312
            d.addWindowFocusListener(new WindowFocusListener() {
-
 
313
 
-
 
314
                public void windowGainedFocus(WindowEvent e) {
-
 
315
                    // do nothing
-
 
316
                }
-
 
317
 
-
 
318
                public void windowLostFocus(WindowEvent e) {
-
 
319
                    if (dialog != null) {
-
 
320
                        final Window oppositeWindow = e.getOppositeWindow();
-
 
321
                        if (oppositeWindow != null && SwingUtilities.isDescendingFrom(oppositeWindow, dialog)) {
-
 
322
                            return;
-
 
323
                        }
-
 
324
                        dialog.dispose();
-
 
325
                        dialog = null;
-
 
326
                    }
-
 
327
                    dialogLostFocusTime = System.currentTimeMillis();
-
 
328
                }
-
 
329
 
-
 
330
            });
-
 
331
            dialog = d;
-
 
332
        }
-
 
333
        // Set picker panel date
-
 
334
        final Calendar calendar = Calendar.getInstance();
-
 
335
        if (date != null) {
-
 
336
            calendar.setTime(date);
-
 
337
            pickerPanel.setSelectedDate(calendar);
-
 
338
        } else {
-
 
339
            pickerPanel.setSelectedDate(null);
-
 
340
        }
-
 
341
        // Show dialog
-
 
342
        final int x = source.getLocation().x;
-
 
343
        final int y = source.getLocation().y + source.getHeight();
-
 
344
        Point p = new Point(x, y);
-
 
345
        SwingUtilities.convertPointToScreen(p, DatePicker.this);
-
 
346
        p = adjustPopupLocationToFitScreen(p.x, p.y, dialog.getSize(), source.getSize());
-
 
347
        dialog.setLocation(p.x, p.y);
-
 
348
        final long time = System.currentTimeMillis() - dialogLostFocusTime;
-
 
349
        if (time > RELEASE_TIME_MS) {
-
 
350
            dialog.setVisible(true);
-
 
351
        } else {
-
 
352
            dialogLostFocusTime = System.currentTimeMillis() - RELEASE_TIME_MS;
-
 
353
        }
-
 
354
    }
-
 
355
 
348
    static public final boolean equals(Object o1, Object o2) {
356
    public static final boolean equals(Object o1, Object o2) {
349
        if (o1 == null && o2 == null)
357
        if (o1 == null && o2 == null)
350
            return true;
358
            return true;
351
        if (o1 == null || o2 == null)
359
        if (o1 == null || o2 == null)
352
            return false;
360
            return false;
353
        return o1.equals(o2);
361
        return o1.equals(o2);
354
    }
362
    }
355
 
363
 
356
}
364
}