--- openide.dialogs/apichanges.xml +++ openide.dialogs/apichanges.xml @@ -51,6 +51,25 @@ + + + Added ExtendedAsynchronousValidatingPanel + + + + + +

+ Added a new wizard panel type which introduces finishValidation() + method. It is complementary to prepareValidation() + method in AsynchronousValidatingPanel and should be + used to unlock user interface when the validation is finished. +

+
+ + +
+ Added BackgroundInstantiatingIterator --- openide.dialogs/manifest.mf +++ openide.dialogs/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.openide.dialogs -OpenIDE-Module-Specification-Version: 7.30 +OpenIDE-Module-Specification-Version: 7.31 OpenIDE-Module-Localizing-Bundle: org/openide/Bundle.properties AutoUpdate-Essential-Module: true --- openide.dialogs/src/org/openide/WizardDescriptor.java +++ openide.dialogs/src/org/openide/WizardDescriptor.java @@ -1469,6 +1469,9 @@ public void run () { if( initialized.get() ) { //#220286 err.log (Level.FINE, "Runs onValidPerformer from invokeLater."); // NOI18N + if( panel instanceof ExtendedAsynchronousValidatingPanel ) { + ((ExtendedAsynchronousValidatingPanel)panel).finishValidation(); + } onValidPerformer.run(); } } @@ -1484,6 +1487,9 @@ SwingUtilities.invokeLater( new Runnable() { @Override public void run() { + if( panel instanceof ExtendedAsynchronousValidatingPanel ) { + ((ExtendedAsynchronousValidatingPanel)panel).finishValidation(); + } onValidationFailed( wve ); } }); @@ -1859,6 +1865,10 @@ *

During background validation Cancel button is hooked * to signal the validation thread using interrupt(). * + *

Note: It is recommended to use ExtendedAsynchronousValidatingPanel instead + * as it adds a method to conveniently unlock wizard's user interface when + * the validation is finished. + * * @since 6.2 (16 May 2005) */ public interface AsynchronousValidatingPanel extends ValidatingPanel { @@ -1881,7 +1891,50 @@ public void validate() throws WizardValidationException; } + /** + * A special interface for panels that need to do additional + * asynchronous validation when Next or Finish button is clicked. + * + *

During background validation is Next or Finish button + * disabled. On validation success wizard automatically + * progress to next panel or finishes. + * + *

During background validation Cancel button is hooked + * to signal the validation thread using interrupt(). + * + * @param + * + * @since 7.31 + */ + public interface ExtendedAsynchronousValidatingPanel extends AsynchronousValidatingPanel { + /** + * Called synchronously from UI thread when Next + * of Finish buttons clicked. It allows to lock user + * input to assure official data for background validation. + */ + @Override + public void prepareValidation(); + + /** + * Is called in separate thread when Next of Finish buttons + * are clicked and allows deeper check to find out that panel + * is in valid state and it is ok to leave it. + * + * @throws WizardValidationException when validation fails + */ + @Override + public void validate() throws WizardValidationException; + + /** + * Called synchronously from UI thread when the background validation + * is finished (even when throwing validation exception). + * It allows to enable user input locked in prepareValidation() method. + */ + public void finishValidation(); + } + + /** A special interface for panel that needs to dynamically enabled * Finish button. * @since 4.28 --- openide.dialogs/test/unit/src/org/openide/AsynchronousValidatingPanelTest.java +++ openide.dialogs/test/unit/src/org/openide/AsynchronousValidatingPanelTest.java @@ -49,6 +49,7 @@ import javax.swing.*; import javax.swing.JLabel; import javax.swing.event.ChangeListener; +import static junit.framework.Assert.assertTrue; import org.netbeans.junit.RandomlyFails; import org.openide.util.*; import org.openide.util.HelpCtx; @@ -85,11 +86,12 @@ public void testAsynchronousLazyValidation () throws Exception { Panel panels[] = new Panel[3]; - class MyPanel extends Panel implements WizardDescriptor.AsynchronousValidatingPanel { + class MyPanel extends Panel implements WizardDescriptor.ExtendedAsynchronousValidatingPanel { public String validateMsg; public String failedMsg; public boolean running; public boolean wasEnabled; + public boolean validationFinished; public MyPanel () { super ("enhanced panel"); @@ -97,13 +99,13 @@ public void prepareValidation () { running = true; + validationFinished = false; } public synchronized void validate () throws WizardValidationException { err.log ("validate() entry."); wasEnabled = wd.isNextEnabled () || wd.isFinishEnabled (); running = false; - notifyAll (); if (validateMsg != null) { failedMsg = validateMsg; err.log ("Throw WizardValidationException."); @@ -112,7 +114,13 @@ err.log ("validate() exit."); return; } + + public synchronized void finishValidation() { + assert SwingUtilities.isEventDispatchThread(); + validationFinished = true; + notifyAll (); } + } class MyFinishPanel extends MyPanel implements WizardDescriptor.FinishablePanel { @Override @@ -149,6 +157,7 @@ } assertFalse ("Finish is disabled during validation.", mp.wasEnabled); assertTrue ("Wizard is ready to next validation however previous failed.", wd.isForwardEnabled ()); + assertTrue ("finishValidation() was called even when validation failed.", mp.validationFinished); assertEquals ("The lazy validation failed on Next.", mp.validateMsg, mp.failedMsg); assertNull ("The lazy validation failed, still no initialiaation", panels[1].component); assertNull ("The lazy validation failed, still no initialiaation", panels[2].component); @@ -174,6 +183,7 @@ assertNull ("Validation on Next passes", mp.failedMsg); assertNotNull ("Now we switched to another panel", panels[1].component); assertNull ("The lazy validation failed, still no initialiaation", panels[2].component); + assertTrue ("finishValidation() was called when validation finished.", mp.validationFinished); // remember previous state Object state = wd.getValue();