source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/query/AdvancedChangesetQueryPanel.java @ 5241

Revision 4307, 46.6 KB checked in by stoecker, 10 months ago (diff)

fix #6684 - i18n issue

  • Property svn:eol-style set to native
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs.changeset.query;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.BorderLayout;
7import java.awt.Color;
8import java.awt.GridBagConstraints;
9import java.awt.GridBagLayout;
10import java.awt.Insets;
11import java.awt.event.ItemEvent;
12import java.awt.event.ItemListener;
13import java.text.DateFormat;
14import java.text.ParseException;
15import java.util.Date;
16import java.util.GregorianCalendar;
17import java.util.Locale;
18
19import javax.swing.BorderFactory;
20import javax.swing.ButtonGroup;
21import javax.swing.JCheckBox;
22import javax.swing.JLabel;
23import javax.swing.JOptionPane;
24import javax.swing.JPanel;
25import javax.swing.JRadioButton;
26import javax.swing.JScrollPane;
27import javax.swing.JTextField;
28import javax.swing.text.JTextComponent;
29
30import org.openstreetmap.josm.Main;
31import org.openstreetmap.josm.gui.HelpAwareOptionPane;
32import org.openstreetmap.josm.gui.JMultilineLabel;
33import org.openstreetmap.josm.gui.JosmUserIdentityManager;
34import org.openstreetmap.josm.gui.help.HelpUtil;
35import org.openstreetmap.josm.gui.widgets.AbstractTextComponentValidator;
36import org.openstreetmap.josm.gui.widgets.BoundingBoxSelectionPanel;
37import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
38import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
39import org.openstreetmap.josm.io.ChangesetQuery;
40import org.openstreetmap.josm.tools.CheckParameterUtil;
41
42/**
43 * This panel allows to specify a changeset query
44 *
45 */
46public class AdvancedChangesetQueryPanel extends JPanel {
47
48    private JCheckBox cbUserRestriction;
49    private JCheckBox cbOpenAndCloseRestrictions;
50    private JCheckBox cbTimeRestrictions;
51    private JCheckBox cbBoundingBoxRestriction;
52    private UserRestrictionPanel pnlUserRestriction;
53    private OpenAndCloseStateRestrictionPanel pnlOpenAndCloseRestriction;
54    private TimeRestrictionPanel pnlTimeRestriction;
55    private BBoxRestrictionPanel pnlBoundingBoxRestriction;
56
57    protected JPanel buildQueryPanel() {
58        ItemListener stateChangeHandler = new RestrictionGroupStateChangeHandler();
59        JPanel pnl  = new VerticallyScrollablePanel();
60        pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
61        pnl.setLayout(new GridBagLayout());
62        GridBagConstraints gc = new GridBagConstraints();
63
64        // -- select changesets by a specific user
65        //
66        gc.anchor = GridBagConstraints.NORTHWEST;
67        gc.weightx = 0.0;
68        gc.fill = GridBagConstraints.HORIZONTAL;
69        pnl.add(cbUserRestriction = new JCheckBox(), gc);
70        cbUserRestriction.addItemListener(stateChangeHandler);
71
72        gc.gridx = 1;
73        gc.weightx = 1.0;
74        pnl.add(new JMultilineLabel(tr("Select changesets owned by specific users")),gc);
75
76        gc.gridy = 1;
77        gc.gridx = 1;
78        gc.weightx = 1.0;
79        pnl.add(pnlUserRestriction = new UserRestrictionPanel(), gc);
80
81        // -- restricting the query to open and closed changesets
82        //
83        gc.gridy = 2;
84        gc.gridx = 0;
85        gc.anchor = GridBagConstraints.NORTHWEST;
86        gc.weightx = 0.0;
87        gc.fill = GridBagConstraints.HORIZONTAL;
88        pnl.add(cbOpenAndCloseRestrictions = new JCheckBox(), gc);
89        cbOpenAndCloseRestrictions.addItemListener(stateChangeHandler);
90
91        gc.gridx = 1;
92        gc.weightx = 1.0;
93        pnl.add(new JMultilineLabel(tr("Select changesets depending on whether they are open or closed")),gc);
94
95        gc.gridy = 3;
96        gc.gridx = 1;
97        gc.weightx = 1.0;
98        pnl.add(pnlOpenAndCloseRestriction = new OpenAndCloseStateRestrictionPanel(), gc);
99
100        // -- restricting the query to a specific time
101        //
102        gc.gridy = 4;
103        gc.gridx = 0;
104        gc.anchor = GridBagConstraints.NORTHWEST;
105        gc.weightx = 0.0;
106        gc.fill = GridBagConstraints.HORIZONTAL;
107        pnl.add(cbTimeRestrictions = new JCheckBox(), gc);
108        cbTimeRestrictions.addItemListener(stateChangeHandler);
109
110        gc.gridx = 1;
111        gc.weightx = 1.0;
112        pnl.add(new JMultilineLabel(tr("Select changesets based on the date/time they have been created or closed")),gc);
113
114        gc.gridy = 5;
115        gc.gridx = 1;
116        gc.weightx = 1.0;
117        pnl.add(pnlTimeRestriction = new TimeRestrictionPanel(), gc);
118
119
120        // -- restricting the query to a specific bounding box
121        //
122        gc.gridy = 6;
123        gc.gridx = 0;
124        gc.anchor = GridBagConstraints.NORTHWEST;
125        gc.weightx = 0.0;
126        gc.fill = GridBagConstraints.HORIZONTAL;
127        pnl.add(cbBoundingBoxRestriction = new JCheckBox(), gc);
128        cbBoundingBoxRestriction.addItemListener(stateChangeHandler);
129
130        gc.gridx = 1;
131        gc.weightx = 1.0;
132        pnl.add(new JMultilineLabel(tr("Select only changesets related to a specific bounding box")),gc);
133
134        gc.gridy = 7;
135        gc.gridx = 1;
136        gc.weightx = 1.0;
137        pnl.add(pnlBoundingBoxRestriction = new BBoxRestrictionPanel(), gc);
138
139
140        gc.gridy = 8;
141        gc.gridx = 0;
142        gc.gridwidth = 2;
143        gc.fill  =GridBagConstraints.BOTH;
144        gc.weightx = 1.0;
145        gc.weighty = 1.0;
146        pnl.add(new JPanel(), gc);
147
148        return pnl;
149    }
150
151    protected void build() {
152        setLayout(new BorderLayout());
153        JScrollPane spQueryPanel = new JScrollPane(buildQueryPanel());
154        add(spQueryPanel, BorderLayout.CENTER);
155        spQueryPanel.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
156        spQueryPanel.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
157
158    }
159
160    public AdvancedChangesetQueryPanel() {
161        build();
162    }
163
164    public void startUserInput() {
165        restoreFromSettings();
166        pnlBoundingBoxRestriction.setVisible(cbBoundingBoxRestriction.isSelected());
167        pnlOpenAndCloseRestriction.setVisible(cbOpenAndCloseRestrictions.isSelected());
168        pnlTimeRestriction.setVisible(cbTimeRestrictions.isSelected());
169        pnlUserRestriction.setVisible(cbUserRestriction.isSelected());
170        pnlOpenAndCloseRestriction.startUserInput();
171        pnlUserRestriction.startUserInput();
172        pnlTimeRestriction.startUserInput();
173    }
174
175    public void displayMessageIfInvalid() {
176        if (cbUserRestriction.isSelected()) {
177            if (! pnlUserRestriction.isValidChangesetQuery()) {
178                pnlUserRestriction.displayMessageIfInvalid();
179            }
180        } else if (cbTimeRestrictions.isSelected()) {
181            if (!pnlTimeRestriction.isValidChangesetQuery()) {
182                pnlTimeRestriction.displayMessageIfInvalid();
183            }
184        } else if (cbBoundingBoxRestriction.isSelected()) {
185            if (!pnlBoundingBoxRestriction.isValidChangesetQuery()) {
186                pnlBoundingBoxRestriction.displayMessageIfInvalid();
187            }
188        }
189    }
190
191    /**
192     * Builds the changeset query based on the data entered in the form.
193     *
194     * @return the changeset query. null, if the data entered doesn't represent
195     * a valid changeset query.
196     */
197    public ChangesetQuery buildChangesetQuery() {
198        ChangesetQuery query = new ChangesetQuery();
199        if (cbUserRestriction.isSelected()) {
200            if (! pnlUserRestriction.isValidChangesetQuery())
201                return null;
202            pnlUserRestriction.fillInQuery(query);
203        }
204        if (cbOpenAndCloseRestrictions.isSelected()) {
205            // don't have to check whether it's valid. It always is.
206            pnlOpenAndCloseRestriction.fillInQuery(query);
207        }
208        if (cbBoundingBoxRestriction.isSelected()) {
209            if (!pnlBoundingBoxRestriction.isValidChangesetQuery())
210                return null;
211            pnlBoundingBoxRestriction.fillInQuery(query);
212        }
213        if (cbTimeRestrictions.isSelected()) {
214            if (!pnlTimeRestriction.isValidChangesetQuery())
215                return null;
216            pnlTimeRestriction.fillInQuery(query);
217        }
218        return query;
219    }
220
221    public void rememberSettings() {
222        Main.pref.put("changeset-query.advanced.user-restrictions", cbUserRestriction.isSelected());
223        Main.pref.put("changeset-query.advanced.open-restrictions", cbOpenAndCloseRestrictions.isSelected());
224        Main.pref.put("changeset-query.advanced.time-restrictions", cbTimeRestrictions.isSelected());
225        Main.pref.put("changeset-query.advanced.bbox-restrictions", cbBoundingBoxRestriction.isSelected());
226
227        pnlUserRestriction.rememberSettings();
228        pnlOpenAndCloseRestriction.rememberSettings();
229        pnlTimeRestriction.rememberSettings();
230    }
231
232    public void restoreFromSettings() {
233        cbUserRestriction.setSelected(Main.pref.getBoolean("changeset-query.advanced.user-restrictions", false));
234        cbOpenAndCloseRestrictions.setSelected(Main.pref.getBoolean("changeset-query.advanced.open-restrictions", false));
235        cbTimeRestrictions.setSelected(Main.pref.getBoolean("changeset-query.advanced.time-restrictions", false));
236        cbBoundingBoxRestriction.setSelected(Main.pref.getBoolean("changeset-query.advanced.bbox-restrictions", false));
237    }
238
239    class RestrictionGroupStateChangeHandler implements ItemListener {
240        protected void userRestrictionStateChanged() {
241            if (pnlUserRestriction == null) return;
242            pnlUserRestriction.setVisible(cbUserRestriction.isSelected());
243        }
244
245        protected void openCloseRestrictionStateChanged() {
246            if (pnlOpenAndCloseRestriction == null) return;
247            pnlOpenAndCloseRestriction.setVisible(cbOpenAndCloseRestrictions.isSelected());
248        }
249
250        protected void timeRestrictionsStateChanged() {
251            if (pnlTimeRestriction == null) return;
252            pnlTimeRestriction.setVisible(cbTimeRestrictions.isSelected());
253        }
254
255        protected void boundingBoxRestrictionChanged() {
256            if (pnlBoundingBoxRestriction == null) return;
257            pnlBoundingBoxRestriction.setVisible(cbBoundingBoxRestriction.isSelected());
258        }
259
260        public void itemStateChanged(ItemEvent e) {
261            if (e.getSource() == cbUserRestriction) {
262                userRestrictionStateChanged();
263            } else if (e.getSource() == cbOpenAndCloseRestrictions) {
264                openCloseRestrictionStateChanged();
265            } else if (e.getSource() == cbTimeRestrictions) {
266                timeRestrictionsStateChanged();
267            } else if (e.getSource() == cbBoundingBoxRestriction) {
268                boundingBoxRestrictionChanged();
269            }
270            validate();
271            repaint();
272        }
273    }
274
275    /**
276     * This is the panel for selecting whether the changeset query should be restricted to
277     * open or closed changesets
278     */
279    static private class OpenAndCloseStateRestrictionPanel extends JPanel {
280
281        private JRadioButton rbOpenOnly;
282        private JRadioButton rbClosedOnly;
283        private JRadioButton rbBoth;
284
285        protected void build() {
286            setLayout(new GridBagLayout());
287            setBorder(BorderFactory.createCompoundBorder(
288                    BorderFactory.createEmptyBorder(3,3,3,3),
289                    BorderFactory.createCompoundBorder(
290                            BorderFactory.createLineBorder(Color.GRAY),
291                            BorderFactory.createEmptyBorder(5,5,5,5)
292                    )
293            ));
294            GridBagConstraints gc = new GridBagConstraints();
295            gc.anchor = GridBagConstraints.NORTHWEST;
296            gc.fill = GridBagConstraints.HORIZONTAL;
297            gc.weightx = 0.0;
298            add(rbOpenOnly = new JRadioButton(), gc);
299
300            gc.gridx = 1;
301            gc.weightx = 1.0;
302            add(new JMultilineLabel(tr("Query open changesets only")), gc);
303
304            gc.gridy = 1;
305            gc.gridx = 0;
306            gc.weightx = 0.0;
307            add(rbClosedOnly = new JRadioButton(), gc);
308
309            gc.gridx = 1;
310            gc.weightx = 1.0;
311            add(new JMultilineLabel(tr("Query closed changesets only")), gc);
312
313            gc.gridy = 2;
314            gc.gridx = 0;
315            gc.weightx = 0.0;
316            add(rbBoth = new JRadioButton(), gc);
317
318            gc.gridx = 1;
319            gc.weightx = 1.0;
320            add(new JMultilineLabel(tr("Query both open and closed changesets")), gc);
321
322            ButtonGroup bgRestrictions = new ButtonGroup();
323            bgRestrictions.add(rbBoth);
324            bgRestrictions.add(rbClosedOnly);
325            bgRestrictions.add(rbOpenOnly);
326        }
327
328        public OpenAndCloseStateRestrictionPanel() {
329            build();
330        }
331
332        public void startUserInput() {
333            restoreFromSettings();
334        }
335
336        public void fillInQuery(ChangesetQuery query) {
337            if (rbBoth.isSelected()) {
338                query.beingClosed(true);
339                query.beingOpen(true);
340            } else if (rbOpenOnly.isSelected()) {
341                query.beingOpen(true);
342            } else if (rbClosedOnly.isSelected()) {
343                query.beingClosed(true);
344            }
345        }
346
347        public void rememberSettings() {
348            String prefRoot = "changeset-query.advanced.open-restrictions";
349            if (rbBoth.isSelected()) {
350                Main.pref.put(prefRoot + ".query-type", "both");
351            } else if (rbOpenOnly.isSelected()) {
352                Main.pref.put(prefRoot + ".query-type", "open");
353            } else if (rbClosedOnly.isSelected()) {
354                Main.pref.put(prefRoot + ".query-type", "closed");
355            }
356        }
357
358        public void restoreFromSettings() {
359            String prefRoot = "changeset-query.advanced.open-restrictions";
360            String v = Main.pref.get(prefRoot + ".query-type", "open");
361            rbBoth.setSelected(v.equals("both"));
362            rbOpenOnly.setSelected(v.equals("open"));
363            rbClosedOnly.setSelected(v.equals("closed"));
364        }
365    }
366
367    /**
368     * This is the panel for selecting whether the query should be restricted to a specific
369     * user
370     *
371     */
372    static private class UserRestrictionPanel extends JPanel {
373        private ButtonGroup bgUserRestrictions;
374        private JRadioButton rbRestrictToMyself;
375        private JRadioButton rbRestrictToUid;
376        private JRadioButton rbRestrictToUserName;
377        private JTextField tfUid;
378        private UidInputFieldValidator valUid;
379        private JTextField tfUserName;
380        private UserNameInputValidator valUserName;
381        private JMultilineLabel lblRestrictedToMyself;
382
383        protected JPanel buildUidInputPanel() {
384            JPanel pnl = new JPanel(new GridBagLayout());
385            GridBagConstraints gc = new GridBagConstraints();
386            gc.fill = GridBagConstraints.HORIZONTAL;
387            gc.weightx = 0.0;
388            gc.insets = new Insets(0,0,0,3);
389            pnl.add(new JLabel(tr("User ID:")), gc);
390
391            gc.gridx = 1;
392            pnl.add(tfUid = new JTextField(10),gc);
393            SelectAllOnFocusGainedDecorator.decorate(tfUid);
394            valUid = UidInputFieldValidator.decorate(tfUid);
395
396            // grab remaining space
397            gc.gridx = 2;
398            gc.weightx = 1.0;
399            pnl.add(new JPanel(), gc);
400            return pnl;
401        }
402
403        protected JPanel buildUserNameInputPanel() {
404            JPanel pnl = new JPanel(new GridBagLayout());
405            GridBagConstraints gc = new GridBagConstraints();
406            gc.fill = GridBagConstraints.HORIZONTAL;
407            gc.weightx = 0.0;
408            gc.insets = new Insets(0,0,0,3);
409            pnl.add(new JLabel(tr("User name:")), gc);
410
411            gc.gridx = 1;
412            pnl.add(tfUserName = new JTextField(10),gc);
413            SelectAllOnFocusGainedDecorator.decorate(tfUserName);
414            valUserName = UserNameInputValidator.decorate(tfUserName);
415
416            // grab remaining space
417            gc.gridx = 2;
418            gc.weightx = 1.0;
419            pnl.add(new JPanel(), gc);
420            return pnl;
421        }
422
423        protected void build() {
424            setLayout(new GridBagLayout());
425            setBorder(BorderFactory.createCompoundBorder(
426                    BorderFactory.createEmptyBorder(3,3,3,3),
427                    BorderFactory.createCompoundBorder(
428                            BorderFactory.createLineBorder(Color.GRAY),
429                            BorderFactory.createEmptyBorder(5,5,5,5)
430                    )
431            ));
432
433            ItemListener userRestrictionChangeHandler = new UserRestrictionChangedHandler();
434            GridBagConstraints gc = new GridBagConstraints();
435            gc.anchor = GridBagConstraints.NORTHWEST;
436            gc.gridx = 0;
437            gc.fill= GridBagConstraints.HORIZONTAL;
438            gc.weightx = 0.0;
439            add(rbRestrictToMyself = new JRadioButton(), gc);
440            rbRestrictToMyself.addItemListener(userRestrictionChangeHandler);
441
442            gc.gridx = 1;
443            gc.fill =  GridBagConstraints.HORIZONTAL;
444            gc.weightx = 1.0;
445            add(lblRestrictedToMyself = new JMultilineLabel(tr("Only changesets owned by myself")), gc);
446
447            gc.gridx = 0;
448            gc.gridy = 1;
449            gc.fill= GridBagConstraints.HORIZONTAL;
450            gc.weightx = 0.0;
451            add(rbRestrictToUid = new JRadioButton(), gc);
452            rbRestrictToUid.addItemListener(userRestrictionChangeHandler);
453
454            gc.gridx = 1;
455            gc.fill =  GridBagConstraints.HORIZONTAL;
456            gc.weightx = 1.0;
457            add(new JMultilineLabel(tr("Only changesets owned by the user with the following user ID")),gc);
458
459            gc.gridx = 1;
460            gc.gridy = 2;
461            gc.fill =  GridBagConstraints.HORIZONTAL;
462            gc.weightx = 1.0;
463            add(buildUidInputPanel(),gc);
464
465            gc.gridx = 0;
466            gc.gridy = 3;
467            gc.fill= GridBagConstraints.HORIZONTAL;
468            gc.weightx = 0.0;
469            add(rbRestrictToUserName = new JRadioButton(), gc);
470            rbRestrictToUserName.addItemListener(userRestrictionChangeHandler);
471
472            gc.gridx = 1;
473            gc.fill =  GridBagConstraints.HORIZONTAL;
474            gc.weightx = 1.0;
475            add(new JMultilineLabel(tr("Only changesets owned by the user with the following user name")),gc);
476
477            gc.gridx = 1;
478            gc.gridy = 4;
479            gc.fill =  GridBagConstraints.HORIZONTAL;
480            gc.weightx = 1.0;
481            add(buildUserNameInputPanel(),gc);
482
483            bgUserRestrictions = new ButtonGroup();
484            bgUserRestrictions.add(rbRestrictToMyself);
485            bgUserRestrictions.add(rbRestrictToUid);
486            bgUserRestrictions.add(rbRestrictToUserName);
487        }
488
489        public UserRestrictionPanel() {
490            build();
491        }
492
493        public void startUserInput() {
494            if (JosmUserIdentityManager.getInstance().isAnonymous()) {
495                lblRestrictedToMyself.setText(tr("Only changesets owned by myself (disabled. JOSM is currently run by an anonymous user)"));
496                rbRestrictToMyself.setEnabled(false);
497                if (rbRestrictToMyself.isSelected()) {
498                    rbRestrictToUid.setSelected(true);
499                }
500            } else {
501                lblRestrictedToMyself.setText(tr("Only changesets owned by myself"));
502                rbRestrictToMyself.setEnabled(true);
503                rbRestrictToMyself.setSelected(true);
504            }
505            restoreFromSettings();
506        }
507
508        /**
509         * Sets the query restrictions on <code>query</code> for changeset owner based
510         * restrictions.
511         *
512         * @param query the query. Must not be null.
513         * @throws IllegalArgumentException thrown if query is null
514         * @throws IllegalStateException thrown if one of the available values for query parameters in
515         * this panel isn't valid
516         *
517         */
518        public void fillInQuery(ChangesetQuery query) throws IllegalStateException, IllegalArgumentException  {
519            CheckParameterUtil.ensureParameterNotNull(query, "query");
520            if (rbRestrictToMyself.isSelected()) {
521                JosmUserIdentityManager im = JosmUserIdentityManager.getInstance();
522                if (im.isPartiallyIdentified()) {
523                    query.forUser(im.getUserName());
524                } else if (im.isFullyIdentified()) {
525                    query.forUser(im.getUserId());
526                } else
527                    throw new IllegalStateException(tr("Cannot restrict changeset query to the current user because the current user is anonymous"));
528            } else if (rbRestrictToUid.isSelected()) {
529                int uid  = valUid.getUid();
530                if (uid > 0) {
531                    query.forUser(uid);
532                } else
533                    throw new IllegalStateException(tr("Current value ''{0}'' for user ID is not valid", tfUid.getText()));
534            } else if (rbRestrictToUserName.isSelected()) {
535                if (! valUserName.isValid())
536                    throw new IllegalStateException(tr("Cannot restrict the changeset query to the user name ''{0}''", tfUserName.getText()));
537                query.forUser(tfUserName.getText());
538            }
539        }
540
541
542        public boolean isValidChangesetQuery() {
543            if (rbRestrictToUid.isSelected())
544                return valUid.isValid();
545            else if (rbRestrictToUserName.isSelected())
546                return valUserName.isValid();
547            return true;
548        }
549
550        protected void alertInvalidUid() {
551            HelpAwareOptionPane.showOptionDialog(
552                    this,
553                    tr("Please enter a valid user ID"),
554                    tr("Invalid user ID"),
555                    JOptionPane.ERROR_MESSAGE,
556                    HelpUtil.ht("/Dialog/ChangesetQueryDialog#InvalidUserId")
557            );
558        }
559
560        protected void alertInvalidUserName() {
561            HelpAwareOptionPane.showOptionDialog(
562                    this,
563                    tr("Please enter a non-empty user name"),
564                    tr("Invalid user name"),
565                    JOptionPane.ERROR_MESSAGE,
566                    HelpUtil.ht("/Dialog/ChangesetQueryDialog#InvalidUserName")
567            );
568        }
569
570        public void displayMessageIfInvalid() {
571            if (rbRestrictToUid.isSelected()) {
572                if (!valUid.isValid()) {
573                    alertInvalidUid();
574                }
575            } else if (rbRestrictToUserName.isSelected()) {
576                if (!valUserName.isValid()) {
577                    alertInvalidUserName();
578                }
579            }
580        }
581
582        public void rememberSettings() {
583            String prefRoot = "changeset-query.advanced.user-restrictions";
584            if (rbRestrictToMyself.isSelected()) {
585                Main.pref.put(prefRoot + ".query-type", "mine");
586            } else if (rbRestrictToUid.isSelected()) {
587                Main.pref.put(prefRoot + ".query-type", "uid");
588            } else if (rbRestrictToUserName.isSelected()) {
589                Main.pref.put(prefRoot + ".query-type", "username");
590            }
591            Main.pref.put(prefRoot + ".uid", tfUid.getText());
592            Main.pref.put(prefRoot + ".username", tfUserName.getText());
593        }
594
595        public void restoreFromSettings() {
596            String prefRoot = "changeset-query.advanced.user-restrictions";
597            String v = Main.pref.get(prefRoot + ".query-type", "mine");
598            if (v.equals("mine")) {
599                JosmUserIdentityManager im = JosmUserIdentityManager.getInstance();
600                if (im.isAnonymous()) {
601                    rbRestrictToUid.setSelected(true);
602                } else {
603                    rbRestrictToMyself.setSelected(true);
604                }
605            } else if (v.equals("uid")) {
606                rbRestrictToUid.setSelected(true);
607            } else if (v.equals("username")) {
608                rbRestrictToUserName.setSelected(true);
609            }
610            tfUid.setText(Main.pref.get(prefRoot + ".uid", ""));
611            if (!valUid.isValid()) {
612                tfUid.setText("");
613            }
614            tfUserName.setText(Main.pref.get(prefRoot + ".username", ""));
615        }
616
617        class UserRestrictionChangedHandler implements ItemListener {
618            public void itemStateChanged(ItemEvent e) {
619                tfUid.setEnabled(rbRestrictToUid.isSelected());
620                tfUserName.setEnabled(rbRestrictToUserName.isSelected());
621                if (rbRestrictToUid.isSelected()) {
622                    tfUid.requestFocusInWindow();
623                } else if (rbRestrictToUserName.isSelected()) {
624                    tfUserName.requestFocusInWindow();
625                }
626            }
627        }
628    }
629
630    /**
631     * This is the panel to apply a time restriction to the changeset query
632     */
633    static private class TimeRestrictionPanel extends JPanel {
634
635        private JRadioButton rbClosedAfter;
636        private JRadioButton rbClosedAfterAndCreatedBefore;
637        private JTextField tfClosedAfterDate1;
638        private DateValidator valClosedAfterDate1;
639        private JTextField tfClosedAfterTime1;
640        private TimeValidator valClosedAfterTime1;
641        private JTextField tfClosedAfterDate2;
642        private DateValidator valClosedAfterDate2;
643        private JTextField tfClosedAfterTime2;
644        private TimeValidator valClosedAfterTime2;
645        private JTextField tfCreatedBeforeDate;
646        private DateValidator valCreatedBeforeDate;
647        private JTextField tfCreatedBeforeTime;
648        private TimeValidator valCreatedBeforeTime;
649
650        protected JPanel buildClosedAfterInputPanel() {
651            JPanel pnl = new JPanel(new GridBagLayout());
652            GridBagConstraints gc = new GridBagConstraints();
653            gc.fill = GridBagConstraints.HORIZONTAL;
654            gc.weightx = 0.0;
655            gc.insets = new Insets(0,0,0,3);
656            pnl.add(new JLabel(tr("Date: ")), gc);
657
658            gc.gridx = 1;
659            gc.weightx = 0.7;
660            pnl.add(tfClosedAfterDate1 = new JTextField(),gc);
661            SelectAllOnFocusGainedDecorator.decorate(tfClosedAfterDate1);
662            valClosedAfterDate1 = DateValidator.decorate(tfClosedAfterDate1);
663            tfClosedAfterDate1.setToolTipText(valClosedAfterDate1.getStandardTooltipTextAsHtml());
664
665            gc.gridx = 2;
666            gc.weightx = 0.0;
667            pnl.add(new JLabel(tr("Time:")),gc);
668
669            gc.gridx = 3;
670            gc.weightx = 0.3;
671            pnl.add(tfClosedAfterTime1 = new JTextField(),gc);
672            SelectAllOnFocusGainedDecorator.decorate(tfClosedAfterTime1);
673            valClosedAfterTime1 = TimeValidator.decorate(tfClosedAfterTime1);
674            tfClosedAfterTime1.setToolTipText(valClosedAfterTime1.getStandardTooltipTextAsHtml());
675            return pnl;
676        }
677
678        protected JPanel buildClosedAfterAndCreatedBeforeInputPanel() {
679            JPanel pnl = new JPanel(new GridBagLayout());
680            GridBagConstraints gc = new GridBagConstraints();
681            gc.fill = GridBagConstraints.HORIZONTAL;
682            gc.weightx = 0.0;
683            gc.insets = new Insets(0,0,0,3);
684            pnl.add(new JLabel(tr("Closed after - ")), gc);
685
686            gc.gridx = 1;
687            gc.fill = GridBagConstraints.HORIZONTAL;
688            gc.weightx = 0.0;
689            gc.insets = new Insets(0,0,0,3);
690            pnl.add(new JLabel(tr("Date:")), gc);
691
692            gc.gridx = 2;
693            gc.weightx = 0.7;
694            pnl.add(tfClosedAfterDate2 = new JTextField(),gc);
695            SelectAllOnFocusGainedDecorator.decorate(tfClosedAfterDate2);
696            valClosedAfterDate2 = DateValidator.decorate(tfClosedAfterDate2);
697            tfClosedAfterDate2.setToolTipText(valClosedAfterDate2.getStandardTooltipTextAsHtml());
698            gc.gridx = 3;
699            gc.weightx = 0.0;
700            pnl.add(new JLabel(tr("Time:")),gc);
701
702            gc.gridx = 4;
703            gc.weightx = 0.3;
704            pnl.add(tfClosedAfterTime2 = new JTextField(),gc);
705            SelectAllOnFocusGainedDecorator.decorate(tfClosedAfterTime2);
706            valClosedAfterTime2 = TimeValidator.decorate(tfClosedAfterTime2);
707            tfClosedAfterTime2.setToolTipText(valClosedAfterTime2.getStandardTooltipTextAsHtml());
708
709            gc.gridy = 1;
710            gc.gridx = 0;
711            gc.fill = GridBagConstraints.HORIZONTAL;
712            gc.weightx = 0.0;
713            gc.insets = new Insets(0,0,0,3);
714            pnl.add(new JLabel(tr("Created before - ")), gc);
715
716            gc.gridx = 1;
717            gc.fill = GridBagConstraints.HORIZONTAL;
718            gc.weightx = 0.0;
719            gc.insets = new Insets(0,0,0,3);
720            pnl.add(new JLabel(tr("Date:")), gc);
721
722            gc.gridx = 2;
723            gc.weightx = 0.7;
724            pnl.add(tfCreatedBeforeDate = new JTextField(),gc);
725            SelectAllOnFocusGainedDecorator.decorate(tfCreatedBeforeDate);
726            valCreatedBeforeDate = DateValidator.decorate(tfCreatedBeforeDate);
727            tfCreatedBeforeDate.setToolTipText(valCreatedBeforeDate.getStandardTooltipTextAsHtml());
728
729            gc.gridx = 3;
730            gc.weightx = 0.0;
731            pnl.add(new JLabel(tr("Time:")),gc);
732
733            gc.gridx = 4;
734            gc.weightx = 0.3;
735            pnl.add(tfCreatedBeforeTime = new JTextField(),gc);
736            SelectAllOnFocusGainedDecorator.decorate(tfCreatedBeforeTime);
737            valCreatedBeforeTime = TimeValidator.decorate(tfCreatedBeforeTime);
738            tfCreatedBeforeTime.setToolTipText(valCreatedBeforeDate.getStandardTooltipTextAsHtml());
739
740            return pnl;
741        }
742
743        protected void build() {
744            setLayout(new GridBagLayout());
745            setBorder(BorderFactory.createCompoundBorder(
746                    BorderFactory.createEmptyBorder(3,3,3,3),
747                    BorderFactory.createCompoundBorder(
748                            BorderFactory.createLineBorder(Color.GRAY),
749                            BorderFactory.createEmptyBorder(5,5,5,5)
750                    )
751            ));
752
753            // -- changesets closed after a specific date/time
754            //
755            GridBagConstraints gc = new GridBagConstraints();
756            gc.anchor = GridBagConstraints.NORTHWEST;
757            gc.gridx = 0;
758            gc.fill= GridBagConstraints.HORIZONTAL;
759            gc.weightx = 0.0;
760            add(rbClosedAfter = new JRadioButton(), gc);
761
762            gc.gridx = 1;
763            gc.fill =  GridBagConstraints.HORIZONTAL;
764            gc.weightx = 1.0;
765            add(new JMultilineLabel(tr("Only changesets closed after the following date/time")), gc);
766
767            gc.gridx = 1;
768            gc.gridy = 1;
769            gc.fill =  GridBagConstraints.HORIZONTAL;
770            gc.weightx = 1.0;
771            add(buildClosedAfterInputPanel(),gc);
772
773            // -- changesets closed after a specific date/time and created before a specific date time
774            //
775            gc = new GridBagConstraints();
776            gc.anchor = GridBagConstraints.NORTHWEST;
777            gc.gridy = 2;
778            gc.gridx = 0;
779            gc.fill= GridBagConstraints.HORIZONTAL;
780            gc.weightx = 0.0;
781            add(rbClosedAfterAndCreatedBefore = new JRadioButton(), gc);
782
783            gc.gridx = 1;
784            gc.fill =  GridBagConstraints.HORIZONTAL;
785            gc.weightx = 1.0;
786            add(new JMultilineLabel(tr("Only changesets closed after and created before a specific date/time")), gc);
787
788            gc.gridx = 1;
789            gc.gridy = 3;
790            gc.fill =  GridBagConstraints.HORIZONTAL;
791            gc.weightx = 1.0;
792            add(buildClosedAfterAndCreatedBeforeInputPanel(),gc);
793
794            ButtonGroup bg = new ButtonGroup();
795            bg.add(rbClosedAfter);
796            bg.add(rbClosedAfterAndCreatedBefore);
797
798            ItemListener restrictionChangeHandler = new TimeRestrictionChangedHandler();
799            rbClosedAfter.addItemListener(restrictionChangeHandler);
800            rbClosedAfterAndCreatedBefore.addItemListener(restrictionChangeHandler);
801
802            rbClosedAfter.setSelected(true);
803        }
804
805        public TimeRestrictionPanel() {
806            build();
807        }
808
809        public boolean isValidChangesetQuery() {
810            if (rbClosedAfter.isSelected())
811                return valClosedAfterDate1.isValid() && valClosedAfterTime1.isValid();
812            else if (rbClosedAfterAndCreatedBefore.isSelected())
813                return valClosedAfterDate2.isValid() && valClosedAfterTime2.isValid()
814                && valCreatedBeforeDate.isValid() && valCreatedBeforeTime.isValid();
815            // should not happen
816            return true;
817        }
818
819        class TimeRestrictionChangedHandler implements ItemListener {
820            public void itemStateChanged(ItemEvent e) {
821                tfClosedAfterDate1.setEnabled(rbClosedAfter.isSelected());
822                tfClosedAfterTime1.setEnabled(rbClosedAfter.isSelected());
823
824                tfClosedAfterDate2.setEnabled(rbClosedAfterAndCreatedBefore.isSelected());
825                tfClosedAfterTime2.setEnabled(rbClosedAfterAndCreatedBefore.isSelected());
826                tfCreatedBeforeDate.setEnabled(rbClosedAfterAndCreatedBefore.isSelected());
827                tfCreatedBeforeTime.setEnabled(rbClosedAfterAndCreatedBefore.isSelected());
828            }
829        }
830
831        public void startUserInput() {
832            restoreFromSettings();
833        }
834
835        public void fillInQuery(ChangesetQuery query) throws IllegalStateException{
836            if (!isValidChangesetQuery())
837                throw new IllegalStateException(tr("Cannot build changeset query with time based restrictions. Input is not valid."));
838            if (rbClosedAfter.isSelected()) {
839                GregorianCalendar cal = new GregorianCalendar();
840                Date d1 = valClosedAfterDate1.getDate();
841                Date d2 = valClosedAfterTime1.getDate();
842                cal.setTimeInMillis(d1.getTime() + (d2 == null ? 0 : d2.getTime()));
843                query.closedAfter(cal.getTime());
844            } else if (rbClosedAfterAndCreatedBefore.isSelected()) {
845                GregorianCalendar cal = new GregorianCalendar();
846                Date d1 = valClosedAfterDate2.getDate();
847                Date d2 = valClosedAfterTime2.getDate();
848                cal.setTimeInMillis(d1.getTime() + (d2 == null ? 0 : d2.getTime()));
849                Date d3 = cal.getTime();
850
851                d1 = valCreatedBeforeDate.getDate();
852                d2 = valCreatedBeforeTime.getDate();
853                cal.setTimeInMillis(d1.getTime() + (d2 == null ? 0 : d2.getTime()));
854                Date d4 = cal.getTime();
855
856                query.closedAfterAndCreatedBefore(d3, d4);
857            }
858        }
859
860        public void displayMessageIfInvalid() {
861            if (isValidChangesetQuery()) return;
862            HelpAwareOptionPane.showOptionDialog(
863                    this,
864                    tr(
865                            "<html>Please enter valid date/time values to restrict<br>"
866                            + "the query to a specific time range.</html>"
867                    ),
868                    tr("Invalid date/time values"),
869                    JOptionPane.ERROR_MESSAGE,
870                    HelpUtil.ht("/Dialog/ChangesetQueryDialog#InvalidDateTimeValues")
871            );
872        }
873
874
875        public void rememberSettings() {
876            String prefRoot = "changeset-query.advanced.time-restrictions";
877            if (rbClosedAfter.isSelected()) {
878                Main.pref.put(prefRoot + ".query-type", "closed-after");
879            } else if (rbClosedAfterAndCreatedBefore.isSelected()) {
880                Main.pref.put(prefRoot + ".query-type", "closed-after-created-before");
881            }
882            Main.pref.put(prefRoot + ".closed-after.date", tfClosedAfterDate1.getText());
883            Main.pref.put(prefRoot + ".closed-after.time", tfClosedAfterTime1.getText());
884            Main.pref.put(prefRoot + ".closed-created.closed.date", tfClosedAfterDate2.getText());
885            Main.pref.put(prefRoot + ".closed-created.closed.time", tfClosedAfterTime2.getText());
886            Main.pref.put(prefRoot + ".closed-created.created.date", tfCreatedBeforeDate.getText());
887            Main.pref.put(prefRoot + ".closed-created.created.time", tfCreatedBeforeTime.getText());
888        }
889
890        public void restoreFromSettings() {
891            String prefRoot = "changeset-query.advanced.open-restrictions";
892            String v = Main.pref.get(prefRoot + ".query-type", "closed-after");
893            rbClosedAfter.setSelected(v.equals("closed-after"));
894            rbClosedAfterAndCreatedBefore.setSelected(v.equals("closed-after-created-before"));
895            if (!rbClosedAfter.isSelected() && !rbClosedAfterAndCreatedBefore.isSelected()) {
896                rbClosedAfter.setSelected(true);
897            }
898            tfClosedAfterDate1.setText(Main.pref.get(prefRoot + ".closed-after.date", ""));
899            tfClosedAfterTime1.setText(Main.pref.get(prefRoot + ".closed-after.time", ""));
900            tfClosedAfterDate2.setText(Main.pref.get(prefRoot + ".closed-created.closed.date", ""));
901            tfClosedAfterTime2.setText(Main.pref.get(prefRoot + ".closed-created.closed.time", ""));
902            tfCreatedBeforeDate.setText(Main.pref.get(prefRoot + ".closed-created.created.date", ""));
903            tfCreatedBeforeTime.setText(Main.pref.get(prefRoot + ".closed-created.created.time", ""));
904            if (!valClosedAfterDate1.isValid()) {
905                tfClosedAfterDate1.setText("");
906            }
907            if (!valClosedAfterTime1.isValid()) {
908                tfClosedAfterTime1.setText("");
909            }
910            if (!valClosedAfterDate2.isValid()) {
911                tfClosedAfterDate2.setText("");
912            }
913            if (!valClosedAfterTime2.isValid()) {
914                tfClosedAfterTime2.setText("");
915            }
916            if (!valCreatedBeforeDate.isValid()) {
917                tfCreatedBeforeDate.setText("");
918            }
919            if (!valCreatedBeforeTime.isValid()) {
920                tfCreatedBeforeTime.setText("");
921            }
922        }
923    }
924
925    static private class BBoxRestrictionPanel extends BoundingBoxSelectionPanel {
926        public BBoxRestrictionPanel() {
927            setBorder(BorderFactory.createCompoundBorder(
928                    BorderFactory.createEmptyBorder(3,3,3,3),
929                    BorderFactory.createCompoundBorder(
930                            BorderFactory.createLineBorder(Color.GRAY),
931                            BorderFactory.createEmptyBorder(5,5,5,5)
932                    )
933            ));
934        }
935
936        public boolean isValidChangesetQuery() {
937            return getBoundingBox() != null;
938        }
939
940        public void fillInQuery(ChangesetQuery query) {
941            if (!isValidChangesetQuery())
942                throw new IllegalStateException(tr("Cannot restrict the changeset query to a specific bounding box. The input is invalid."));
943            query.inBbox(getBoundingBox());
944        }
945
946        public void displayMessageIfInvalid() {
947            if (isValidChangesetQuery()) return;
948            HelpAwareOptionPane.showOptionDialog(
949                    this,
950                    tr(
951                            "<html>Please enter valid longitude/latitude values to restrict<br>" +
952                            "the changeset query to a specific bounding box.</html>"
953                    ),
954                    tr("Invalid bounding box"),
955                    JOptionPane.ERROR_MESSAGE,
956                    HelpUtil.ht("/Dialog/ChangesetQueryDialog#InvalidBoundingBox")
957            );
958        }
959    }
960
961    /**
962     * Validator for user ids entered in in a {@see JTextComponent}.
963     *
964     */
965    static private class UidInputFieldValidator extends AbstractTextComponentValidator {
966        static public UidInputFieldValidator decorate(JTextComponent tc) {
967            return new UidInputFieldValidator(tc);
968        }
969
970        public UidInputFieldValidator(JTextComponent tc) {
971            super(tc);
972        }
973
974        @Override
975        public boolean isValid() {
976            return getUid() > 0;
977        }
978
979        @Override
980        public void validate() {
981            String value  = getComponent().getText();
982            if (value == null || value.trim().length() == 0) {
983                feedbackInvalid("");
984                return;
985            }
986            try {
987                int uid = Integer.parseInt(value);
988                if (uid <= 0) {
989                    feedbackInvalid(tr("The current value is not a valid user ID. Please enter an integer value > 0"));
990                    return;
991                }
992            } catch(NumberFormatException e) {
993                feedbackInvalid(tr("The current value is not a valid user ID. Please enter an integer value > 0"));
994                return;
995            }
996            feedbackValid(tr("Please enter an integer value > 0"));
997        }
998
999        public int getUid() {
1000            String value  = getComponent().getText();
1001            if (value == null || value.trim().length() == 0) return 0;
1002            try {
1003                int uid = Integer.parseInt(value.trim());
1004                if (uid > 0) return uid;
1005                return 0;
1006            } catch(NumberFormatException e) {
1007                return 0;
1008            }
1009        }
1010    }
1011
1012    static private class UserNameInputValidator extends AbstractTextComponentValidator {
1013        static public UserNameInputValidator decorate(JTextComponent tc) {
1014            return new UserNameInputValidator(tc);
1015        }
1016
1017        public UserNameInputValidator(JTextComponent tc) {
1018            super(tc);
1019        }
1020
1021        @Override
1022        public boolean isValid() {
1023            return getComponent().getText().trim().length() > 0;
1024        }
1025
1026        @Override
1027        public void validate() {
1028            String value  = getComponent().getText();
1029            if (value.trim().length() == 0) {
1030                feedbackInvalid(tr("<html>The  current value is not a valid user name.<br>Please enter an non-empty user name.</html>"));
1031                return;
1032            }
1033            feedbackValid(tr("Please enter an non-empty user name"));
1034        }
1035    }
1036
1037    /**
1038     * Validates dates entered as text in in a {@see JTextComponent}. Validates the input
1039     * on the fly and gives feedback about whether the date is valid or not.
1040     *
1041     * Dates can be entered in one of four standard formats defined for the current locale.
1042     */
1043    static private class DateValidator extends AbstractTextComponentValidator {
1044        static public DateValidator decorate(JTextComponent tc) {
1045            return new DateValidator(tc);
1046        }
1047
1048        public DateValidator(JTextComponent tc) {
1049            super(tc);
1050        }
1051
1052        @Override
1053        public boolean isValid() {
1054            return getDate() != null;
1055        }
1056
1057        public String getStandardTooltipTextAsHtml() {
1058            return "<html>" + getStandardTooltipText() + "</html>";
1059        }
1060
1061        public String getStandardTooltipText() {
1062            return  tr(
1063                    "Please enter a date in the usual format for your locale.<br>"
1064                    + "Example: {0}<br>"
1065                    + "Example: {1}<br>"
1066                    + "Example: {2}<br>"
1067                    + "Example: {3}<br>",
1068                    DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault()).format(new Date()),
1069                    DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.getDefault()).format(new Date()),
1070                    DateFormat.getDateInstance(DateFormat.LONG, Locale.getDefault()).format(new Date()),
1071                    DateFormat.getDateInstance(DateFormat.FULL, Locale.getDefault()).format(new Date())
1072            );
1073        }
1074
1075        @Override
1076        public void validate() {
1077            if (!isValid()) {
1078                String msg = "<html>The current value isn't a valid date.<br>" + getStandardTooltipText()+ "</html>";
1079                feedbackInvalid(msg);
1080                return;
1081            } else {
1082                String msg = "<html>" + getStandardTooltipText() + "</html>";
1083                feedbackValid(msg);
1084            }
1085        }
1086
1087        public Date getDate() {
1088            for (int format: new int[] {DateFormat.SHORT, DateFormat.MEDIUM, DateFormat.LONG, DateFormat.FULL}) {
1089                DateFormat df = DateFormat.getDateInstance(format);
1090                try {
1091                    return df.parse(getComponent().getText());
1092                } catch (ParseException e) {
1093                    // Try next format
1094                }
1095            }
1096            return null;
1097        }
1098    }
1099
1100    /**
1101     * Validates time values entered as text in in a {@see JTextComponent}. Validates the input
1102     * on the fly and gives feedback about whether the time value is valid or not.
1103     *
1104     * Time values can be entered in one of four standard formats defined for the current locale.
1105     */
1106    static private class TimeValidator extends AbstractTextComponentValidator {
1107        static public TimeValidator decorate(JTextComponent tc) {
1108            return new TimeValidator(tc);
1109        }
1110
1111        public TimeValidator(JTextComponent tc) {
1112            super(tc);
1113        }
1114
1115        @Override
1116        public boolean isValid() {
1117            if (getComponent().getText().trim().length() == 0) return true;
1118            return getDate() != null;
1119        }
1120
1121        public String getStandardTooltipTextAsHtml() {
1122            return "<html>" + getStandardTooltipText() + "</html>";
1123        }
1124
1125        public String getStandardTooltipText() {
1126            return tr(
1127                    "Please enter a valid time in the usual format for your locale.<br>"
1128                    + "Example: {0}<br>"
1129                    + "Example: {1}<br>"
1130                    + "Example: {2}<br>"
1131                    + "Example: {3}<br>",
1132                    DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()).format(new Date()),
1133                    DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.getDefault()).format(new Date()),
1134                    DateFormat.getTimeInstance(DateFormat.LONG, Locale.getDefault()).format(new Date()),
1135                    DateFormat.getTimeInstance(DateFormat.FULL, Locale.getDefault()).format(new Date())
1136            );
1137        }
1138
1139        @Override
1140        public void validate() {
1141
1142            if (!isValid()) {
1143                String msg = "<html>The current value isn't a valid time.<br>" + getStandardTooltipText() + "</html>";
1144                feedbackInvalid(msg);
1145                return;
1146            } else {
1147                String msg = "<html>" + getStandardTooltipText() + "</html>";
1148                feedbackValid(msg);
1149            }
1150        }
1151
1152        public Date getDate() {
1153            if (getComponent().getText().trim().length() == 0)
1154                return null;
1155
1156            for (int i = 0; i< 4; i++) {
1157                try {
1158                    DateFormat df = null;
1159                    switch(i) {
1160                    case 0: df = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()); break;
1161                    case 1: df = DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.getDefault()); break;
1162                    case 2: df = DateFormat.getTimeInstance(DateFormat.LONG, Locale.getDefault()); break;
1163                    case 3: df = DateFormat.getTimeInstance(DateFormat.FULL,Locale.getDefault()); break;
1164                    }
1165                    Date d = df.parse(getComponent().getText());
1166                    return d;
1167                } catch(ParseException e) {
1168                    continue;
1169                }
1170            }
1171            return null;
1172        }
1173    }
1174}
Note: See TracBrowser for help on using the repository browser.