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

Last change on this file since 5886 was 5886, checked in by Don-vip, 11 years ago

see #4429 - Right click menu "undo, cut, copy, paste, delete, select all" for each text component (originally based on patch by NooN)

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