001 // License: GPL. For details, see LICENSE file. 002 package org.openstreetmap.josm.gui.dialogs.changeset.query; 003 004 import static org.openstreetmap.josm.tools.I18n.tr; 005 006 import java.awt.BorderLayout; 007 import java.awt.Color; 008 import java.awt.GridBagConstraints; 009 import java.awt.GridBagLayout; 010 import java.awt.Insets; 011 import java.awt.event.ItemEvent; 012 import java.awt.event.ItemListener; 013 import java.text.DateFormat; 014 import java.text.ParseException; 015 import java.util.Date; 016 import java.util.GregorianCalendar; 017 import java.util.Locale; 018 019 import javax.swing.BorderFactory; 020 import javax.swing.ButtonGroup; 021 import javax.swing.JCheckBox; 022 import javax.swing.JLabel; 023 import javax.swing.JOptionPane; 024 import javax.swing.JPanel; 025 import javax.swing.JRadioButton; 026 import javax.swing.JScrollPane; 027 import javax.swing.JTextField; 028 import javax.swing.text.JTextComponent; 029 030 import org.openstreetmap.josm.Main; 031 import org.openstreetmap.josm.gui.HelpAwareOptionPane; 032 import org.openstreetmap.josm.gui.JMultilineLabel; 033 import org.openstreetmap.josm.gui.JosmUserIdentityManager; 034 import org.openstreetmap.josm.gui.help.HelpUtil; 035 import org.openstreetmap.josm.gui.widgets.AbstractTextComponentValidator; 036 import org.openstreetmap.josm.gui.widgets.BoundingBoxSelectionPanel; 037 import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator; 038 import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel; 039 import org.openstreetmap.josm.io.ChangesetQuery; 040 import org.openstreetmap.josm.tools.CheckParameterUtil; 041 042 /** 043 * This panel allows to specify a changeset query 044 * 045 */ 046 public class AdvancedChangesetQueryPanel extends JPanel { 047 048 private JCheckBox cbUserRestriction; 049 private JCheckBox cbOpenAndCloseRestrictions; 050 private JCheckBox cbTimeRestrictions; 051 private JCheckBox cbBoundingBoxRestriction; 052 private UserRestrictionPanel pnlUserRestriction; 053 private OpenAndCloseStateRestrictionPanel pnlOpenAndCloseRestriction; 054 private TimeRestrictionPanel pnlTimeRestriction; 055 private BBoxRestrictionPanel pnlBoundingBoxRestriction; 056 057 protected JPanel buildQueryPanel() { 058 ItemListener stateChangeHandler = new RestrictionGroupStateChangeHandler(); 059 JPanel pnl = new VerticallyScrollablePanel(); 060 pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 061 pnl.setLayout(new GridBagLayout()); 062 GridBagConstraints gc = new GridBagConstraints(); 063 064 // -- select changesets by a specific user 065 // 066 gc.anchor = GridBagConstraints.NORTHWEST; 067 gc.weightx = 0.0; 068 gc.fill = GridBagConstraints.HORIZONTAL; 069 pnl.add(cbUserRestriction = new JCheckBox(), gc); 070 cbUserRestriction.addItemListener(stateChangeHandler); 071 072 gc.gridx = 1; 073 gc.weightx = 1.0; 074 pnl.add(new JMultilineLabel(tr("Select changesets owned by specific users")),gc); 075 076 gc.gridy = 1; 077 gc.gridx = 1; 078 gc.weightx = 1.0; 079 pnl.add(pnlUserRestriction = new UserRestrictionPanel(), gc); 080 081 // -- restricting the query to open and closed changesets 082 // 083 gc.gridy = 2; 084 gc.gridx = 0; 085 gc.anchor = GridBagConstraints.NORTHWEST; 086 gc.weightx = 0.0; 087 gc.fill = GridBagConstraints.HORIZONTAL; 088 pnl.add(cbOpenAndCloseRestrictions = new JCheckBox(), gc); 089 cbOpenAndCloseRestrictions.addItemListener(stateChangeHandler); 090 091 gc.gridx = 1; 092 gc.weightx = 1.0; 093 pnl.add(new JMultilineLabel(tr("Select changesets depending on whether they are open or closed")),gc); 094 095 gc.gridy = 3; 096 gc.gridx = 1; 097 gc.weightx = 1.0; 098 pnl.add(pnlOpenAndCloseRestriction = new OpenAndCloseStateRestrictionPanel(), gc); 099 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 {@link 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 {@link 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 {@link 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 }