KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > WizardDescriptor


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.openide;
21
22 import java.awt.BorderLayout JavaDoc;
23 import java.awt.Color JavaDoc;
24 import java.awt.Component JavaDoc;
25 import java.awt.Container JavaDoc;
26 import java.awt.Cursor JavaDoc;
27 import java.awt.Dimension JavaDoc;
28 import java.awt.FocusTraversalPolicy JavaDoc;
29 import java.awt.Font JavaDoc;
30 import java.awt.Graphics JavaDoc;
31 import java.awt.Image JavaDoc;
32 import java.awt.Insets JavaDoc;
33 import java.awt.KeyboardFocusManager JavaDoc;
34 import java.awt.MediaTracker JavaDoc;
35 import java.awt.Rectangle JavaDoc;
36 import java.awt.Window JavaDoc;
37 import java.awt.event.ActionEvent JavaDoc;
38 import java.awt.event.ActionListener JavaDoc;
39 import java.awt.event.KeyEvent JavaDoc;
40 import java.awt.event.WindowEvent JavaDoc;
41 import java.awt.event.WindowListener JavaDoc;
42 import java.beans.PropertyChangeEvent JavaDoc;
43 import java.beans.PropertyChangeListener JavaDoc;
44 import java.io.IOException JavaDoc;
45 import java.net.URL JavaDoc;
46 import java.text.MessageFormat JavaDoc;
47 import java.util.Arrays JavaDoc;
48 import java.util.Collections JavaDoc;
49 import java.util.HashMap JavaDoc;
50 import java.util.Map JavaDoc;
51 import java.util.ResourceBundle JavaDoc;
52 import java.util.Set JavaDoc;
53 import java.util.logging.Level JavaDoc;
54 import java.util.logging.Logger JavaDoc;
55 import javax.accessibility.Accessible JavaDoc;
56 import javax.swing.BorderFactory JavaDoc;
57 import javax.swing.ImageIcon JavaDoc;
58 import javax.swing.JButton JavaDoc;
59 import javax.swing.JComponent JavaDoc;
60 import javax.swing.JLabel JavaDoc;
61 import javax.swing.JList JavaDoc;
62 import javax.swing.JPanel JavaDoc;
63 import javax.swing.JProgressBar JavaDoc;
64 import javax.swing.JScrollPane JavaDoc;
65 import javax.swing.JSeparator JavaDoc;
66 import javax.swing.JTabbedPane JavaDoc;
67 import javax.swing.JTextArea JavaDoc;
68 import javax.swing.KeyStroke JavaDoc;
69 import javax.swing.ListCellRenderer JavaDoc;
70 import javax.swing.SwingConstants JavaDoc;
71 import javax.swing.SwingUtilities JavaDoc;
72 import javax.swing.UIManager JavaDoc;
73 import javax.swing.event.ChangeEvent JavaDoc;
74 import javax.swing.event.ChangeListener JavaDoc;
75 import org.openide.awt.HtmlBrowser;
76 import org.openide.awt.Mnemonics;
77 import org.openide.util.Exceptions;
78 import org.openide.util.HelpCtx;
79 import org.openide.util.Mutex;
80 import org.openide.util.NbBundle;
81 import org.openide.util.RequestProcessor;
82 import org.openide.util.Utilities;
83 import org.openide.util.WeakListeners;
84 import org.netbeans.api.progress.ProgressHandle;
85 import org.netbeans.api.progress.ProgressHandleFactory;
86
87 /**
88  * Implements a basic "wizard" GUI system.
89  * A list of <em>wizard panels</em> may be specified and these
90  * may be traversed at the proper times using the "Previous"
91  * and "Next" buttons (or "Finish" on the last one).
92  * @see DialogDisplayer#createDialog
93  * @see <a HREF="doc-files/wizard-guidebook.html">Wizard Guidebook
94  * (describes the set of properties controlling the display of wizard panels)</a>
95  */

96 public class WizardDescriptor extends DialogDescriptor {
97     /** "Next" button option.
98     * @see #setOptions */

99     public static final Object JavaDoc NEXT_OPTION = new String JavaDoc("NEXT_OPTION"); // NOI18N
100

101     /** "Finish" button option.
102     * @see #setOptions */

103     public static final Object JavaDoc FINISH_OPTION = OK_OPTION;
104
105     /** "Previous" button option.
106     * @see #setOptions */

107     public static final Object JavaDoc PREVIOUS_OPTION = new String JavaDoc("PREVIOUS_OPTION"); // NOI18N
108
private static final ActionListener JavaDoc CLOSE_PREVENTER = new ActionListener JavaDoc() {
109             public void actionPerformed(ActionEvent JavaDoc evt) {
110             }
111
112             public String JavaDoc toString() {
113                 return "CLOSE_PREVENTER"; // NOI18N
114
}
115         };
116
117     /** <CODE>Boolean</CODE> property. The value is taken from <CODE>WizardDescriptor.getProperty()</CODE> or
118      * <CODE>((JComponent)Panel.getComponent()).getClientProperty()</CODE> in this order.
119      * Set to <CODE>true</CODE> for enabling other properties. It is relevant only on
120      * initialization (client property in first panel).
121      * When false or not present in JComponent.getClientProperty(), then supplied panel is
122      * used directly without content, help or panel name auto layout.
123      */

124     private static final String JavaDoc PROP_AUTO_WIZARD_STYLE = "WizardPanel_autoWizardStyle"; // NOI18N
125

126     /** <CODE>Boolean</CODE> property. The value is taken from <CODE>WizardDescriptor.getProperty()</CODE> or
127      * <CODE>((JComponent)Panel.getComponent()).getClientProperty()</CODE> in this order.
128      * Set to <CODE>true</CODE> for showing help pane in the left pane. It is relevant only on
129      * initialization (client property in first panel).
130      */

131     private static final String JavaDoc PROP_HELP_DISPLAYED = "WizardPanel_helpDisplayed"; // NOI18N
132

133     /** <CODE>Boolean</CODE> property. The value is taken from <CODE>WizardDescriptor.getProperty()</CODE> or
134      * <CODE>((JComponent)Panel.getComponent()).getClientProperty()</CODE> in this order.
135      * Set to <CODE>true</CODE> for showing content pane in the left pane. It is relevant only on
136      * initialization (client property in first panel).
137      */

138     private static final String JavaDoc PROP_CONTENT_DISPLAYED = "WizardPanel_contentDisplayed"; // NOI18N
139

140     /** <CODE>Boolean</CODE> property. The value is taken from <CODE>WizardDescriptor.getProperty()</CODE> or
141      * <CODE>((JComponent)Panel.getComponent()).getClientProperty()</CODE> in this order.
142      * Set to <CODE>true</CODE> for displaying numbers in the content. It is relevant only on
143      * initialization (client property in first panel).
144      */

145     private static final String JavaDoc PROP_CONTENT_NUMBERED = "WizardPanel_contentNumbered"; // NOI18N
146

147     /** <CODE>Integer</CODE> property. The value is taken from <CODE>WizardDescriptor.getProperty()</CODE> or
148      * <CODE>((JComponent)Panel.getComponent()).getClientProperty()</CODE> in this order.
149      * Represents index of content item which will be highlited.
150      */

151     private static final String JavaDoc PROP_CONTENT_SELECTED_INDEX = "WizardPanel_contentSelectedIndex"; // NOI18N
152

153     /** <CODE>String[]</CODE> property. The value is taken from <CODE>WizardDescriptor.getProperty()</CODE> or
154      * <CODE>((JComponent)Panel.getComponent()).getClientProperty()</CODE> in this order.
155      * Represents array of content items.
156      */

157     private static final String JavaDoc PROP_CONTENT_DATA = "WizardPanel_contentData"; // NOI18N
158

159     /** <CODE>Color</CODE> property. The value is taken from <CODE>WizardDescriptor.getProperty()</CODE> or
160      * <CODE>((JComponent)Panel.getComponent()).getClientProperty()</CODE> in this order.
161      * Set to background color of content pane.
162      */

163     private static final String JavaDoc PROP_CONTENT_BACK_COLOR = "WizardPanel_contentBackColor"; // NOI18N
164

165     /** <CODE>Color</CODE> property. The value is taken from <CODE>WizardDescriptor.getProperty()</CODE> or
166      * <CODE>((JComponent)Panel.getComponent()).getClientProperty()</CODE> in this order.
167      * Set to foreground color of content pane.
168      */

169     private static final String JavaDoc PROP_CONTENT_FOREGROUND_COLOR = "WizardPanel_contentForegroundColor"; // NOI18N
170

171     /** <CODE>Image</CODE> property. The value is taken from <CODE>WizardDescriptor.getProperty()</CODE> or
172      * <CODE>((JComponent)Panel.getComponent()).getClientProperty()</CODE> in this order.
173      * Set to image which should be displayed in the left pane (behind the content).
174      */

175     private static final String JavaDoc PROP_IMAGE = "WizardPanel_image"; // NOI18N
176

177     /** <CODE>String</CODE> property. The value is taken from <CODE>WizardDescriptor.getProperty()</CODE> or
178      * <CODE>((JComponent)Panel.getComponent()).getClientProperty()</CODE> in this order.
179      * Set to side where the image should be drawn.
180      */

181     private static final String JavaDoc PROP_IMAGE_ALIGNMENT = "WizardPanel_imageAlignment"; // NOI18N
182

183     /** <CODE>Dimension</CODE> property. The value is taken from <CODE>WizardDescriptor.getProperty()</CODE> or
184      * <CODE>((JComponent)Panel.getComponent()).getClientProperty()</CODE> in this order.
185      * Dimension of left pane, should be same as dimension of <CODE>PROP_IMAGE</CODE>.
186      * It is relevant only on initialization (client property in first panel).
187      */

188     private static final String JavaDoc PROP_LEFT_DIMENSION = "WizardPanel_leftDimension"; // NOI18N
189

190     /** <CODE>URL</CODE> property. The value is taken from <CODE>WizardDescriptor.getProperty()</CODE> or
191      * <CODE>((JComponent)Panel.getComponent()).getClientProperty()</CODE> in this order.
192      * Represents URL of help displayed in left pane.
193      */

194     private static final String JavaDoc PROP_HELP_URL = "WizardPanel_helpURL"; // NOI18N
195

196     /** <CODE>String</CODE> property. The value is taken from <CODE>WizardDescriptor.getProperty()</CODE>.
197      * If it contains non-null value the String is displayed the bottom of the wizard
198      * and should inform user why the panel is invalid and why the Next/Finish
199      * buttons were disabled.
200      * @since 3.39
201      */

202     private static final String JavaDoc PROP_ERROR_MESSAGE = "WizardPanel_errorMessage"; // NOI18N
203

204     private static Logger JavaDoc err = Logger.getLogger(WizardDescriptor.class.getName ());
205
206     /** real buttons to be placed instead of the options */
207     private final JButton JavaDoc nextButton = new JButton JavaDoc();
208     private final JButton JavaDoc finishButton = new JButton JavaDoc();
209     private final JButton JavaDoc cancelButton = new JButton JavaDoc();
210     private final JButton JavaDoc previousButton = new JButton JavaDoc();
211     private FinishAction finishOption;
212     private Set JavaDoc /*<Object>*/ newObjects = Collections.EMPTY_SET;
213
214     /** a component with wait cursor */
215     private Component JavaDoc waitingComponent;
216     private boolean changeStateInProgress = false;
217
218     /** Whether wizard panel will be constructed from <CODE>WizardDescriptor.getProperty()</CODE>/
219      * <CODE>(JComponent)Panel.getComponent()</CODE> client properties or returned
220      * <CODE>Component</CODE> will be inserted to wizard dialog directly.
221      */

222     private boolean autoWizardStyle = false;
223
224     /** Whether properties from first <CODE>(JComponent)Panel.getComponent()</CODE>
225      * have been initialized.
226      */

227     private boolean init = false;
228
229     /** Panel which is used when in <CODE>AUTO_WIZARD_STYLE</CODE> mode.*/
230     private WizardPanel wizardPanel;
231
232     /** Image */
233     private Image JavaDoc image;
234
235     /** Content data */
236     private String JavaDoc[] contentData = new String JavaDoc[] { };
237
238     /** Selected content index */
239     private int contentSelectedIndex = -1;
240
241     /** Background color*/
242     private Color JavaDoc contentBackColor;
243
244     /** Foreground color*/
245     private Color JavaDoc contentForegroundColor;
246
247     /** Help URL displayed in the left pane */
248     private URL JavaDoc helpURL;
249
250     /** Listener on a user component client property changes*/
251     private PropL propListener;
252
253     /** 'North' or 'South' */
254     private String JavaDoc imageAlignment = "North"; // NOI18N
255

256     /** Iterator between panels in the wizard and its settings */
257     private SettingsAndIterator<?> data;
258
259     /** Change listener that invokes method update state */
260     private ChangeListener JavaDoc weakChangeListener;
261     private PropertyChangeListener JavaDoc weakPropertyChangeListener;
262     private ActionListener JavaDoc weakNextButtonListener;
263     private ActionListener JavaDoc weakPreviousButtonListener;
264     private ActionListener JavaDoc weakFinishButtonListener;
265     private ActionListener JavaDoc weakCancelButtonListener;
266
267     // base listener which won't be directly attached, will only wrapped by WeakListener
268
private Listener JavaDoc baseListener;
269
270     /** message format to create title of the document */
271     private MessageFormat JavaDoc titleFormat;
272
273     /** hashtable with additional settings that is usually used
274     * by Panels to store their data
275     */

276     private Map JavaDoc<String JavaDoc,Object JavaDoc> properties;
277     ResourceBundle JavaDoc bundle = NbBundle.getBundle(WizardDescriptor.class);
278
279     /** Request processor that is used for asynchronous jobs (background validation,
280      * asynchronous instantiation i.e.) and supports Thread.interrupted().
281      * It's package-private to accessible for unit tests.
282      */

283     static final RequestProcessor ASYNCHRONOUS_JOBS_RP =
284         new RequestProcessor("wizard-descriptor-asynchronous-jobs", 1, true); // NOI18N
285

286     private RequestProcessor.Task backgroundValidationTask;
287
288     private boolean validationRuns;
289
290     private ProgressHandle handle;
291
292     private static final String JavaDoc PROGRESS_BAR_DISPLAY_NAME = NbBundle.getMessage (WizardDescriptor.class, "CTL_InstantiateProgress_Title"); // NOI18N
293

294     private ActionListener JavaDoc escapeActionListener;
295
296     {
297         // button init
298
ResourceBundle JavaDoc b = NbBundle.getBundle("org.openide.Bundle"); // NOI18N
299
nextButton.setText(b.getString("CTL_NEXT"));
300         Mnemonics.setLocalizedText(previousButton, b.getString("CTL_PREVIOUS"));
301         Mnemonics.setLocalizedText(finishButton, b.getString("CTL_FINISH"));
302         finishButton.getAccessibleContext().setAccessibleDescription(b.getString("ACSD_FINISH"));
303         cancelButton.setText(b.getString("CTL_CANCEL"));
304         cancelButton.getAccessibleContext().setAccessibleDescription(b.getString("ACSD_CANCEL"));
305
306         finishButton.setDefaultCapable(true);
307         nextButton.setDefaultCapable(true);
308         previousButton.setDefaultCapable(false);
309         cancelButton.setDefaultCapable(false);
310     }
311
312     /** Create a new wizard from a fixed list of panels, passing some settings to the panels.
313     * @param wizardPanels the panels to use
314     * @param settings the settings to pass to panels, or <code>null</code>
315     * @see #WizardDescriptor(WizardDescriptor.Iterator, Object)
316     */

317     public <Data> WizardDescriptor(Panel JavaDoc<Data>[] wizardPanels, Data settings) {
318         this(new SettingsAndIterator<Data>(new ArrayIterator<Data>(wizardPanels), settings));
319     }
320     
321     /** Create a new wizard from a fixed list of panels with settings
322     * defaulted to <CODE>this</CODE>.
323     *
324     * @param wizardPanels the panels to use
325     * @see #WizardDescriptor(WizardDescriptor.Iterator, Object)
326     */

327     public WizardDescriptor(Panel JavaDoc<WizardDescriptor>[] wizardPanels) {
328         this(SettingsAndIterator.create(new ArrayIterator<WizardDescriptor>(wizardPanels)));
329     }
330
331     /** Create wizard for a sequence of panels, passing some settings to the panels.
332     * @param panels iterator over all {@link WizardDescriptor.Panel}s that can appear in the wizard
333     * @param settings the settings to provide to the panels (may be any data understood by them)
334     * @see WizardDescriptor.Panel#readSettings
335     * @see WizardDescriptor.Panel#storeSettings
336     */

337     public <Data>WizardDescriptor(Iterator<Data> panels, Data settings) {
338         this(new SettingsAndIterator<Data>(panels, settings));
339     }
340     
341     private <Data> WizardDescriptor(SettingsAndIterator<Data> data) {
342         super("", "", true, DEFAULT_OPTION, null, CLOSE_PREVENTER); // NOI18N
343

344         this.data = data;
345
346         baseListener = new Listener JavaDoc();
347
348         weakNextButtonListener = WeakListeners.create(
349                 ActionListener JavaDoc.class, baseListener, nextButton
350             ); // NOI18N
351
weakPreviousButtonListener = WeakListeners.create(
352                 ActionListener JavaDoc.class, baseListener, previousButton
353             ); // NOI18N
354
weakFinishButtonListener = WeakListeners.create(
355                 ActionListener JavaDoc.class, baseListener, finishButton
356             ); // NOI18N
357
weakCancelButtonListener = WeakListeners.create(
358                 ActionListener JavaDoc.class, baseListener, cancelButton
359             ); // NOI18N
360

361         nextButton.addActionListener(weakNextButtonListener);
362         previousButton.addActionListener(weakPreviousButtonListener);
363         finishButton.addActionListener(weakFinishButtonListener);
364         cancelButton.addActionListener(weakCancelButtonListener);
365
366         finishOption = new WizardDescriptor.FinishAction();
367
368         super.setOptions(new Object JavaDoc[] { previousButton, nextButton, finishButton, cancelButton });
369         super.setClosingOptions(new Object JavaDoc[] { finishOption, cancelButton });
370
371         // attach the change listener to iterator
372
weakChangeListener = WeakListeners.change(baseListener, data.getIterator(this));
373         data.getIterator(this).addChangeListener(weakChangeListener);
374
375         callInitialize();
376     }
377
378     /** Create wizard for a sequence of panels, with settings
379     * defaulted to <CODE>this</CODE>.
380     *
381     * @param panels iterator over all {@link WizardDescriptor.Panel}s that can appear in the wizard
382     */

383     public WizardDescriptor(Iterator<WizardDescriptor> panels) {
384         this(SettingsAndIterator.create(panels));
385     }
386
387     /** Initializes settings.
388      */

389     protected void initialize() {
390         super.initialize();
391
392         updateState();
393         
394         // #81938: special handling WizardDescriptor to avoid close wizard during instantiate
395
SwingUtilities.invokeLater (new Runnable JavaDoc () {
396             public void run () {
397                 final Window JavaDoc w = SwingUtilities.getWindowAncestor((Component JavaDoc) getMessage());
398                 if (w != null) {
399                     w.addWindowListener (new WindowListener JavaDoc () {
400                         public void windowActivated (WindowEvent JavaDoc e) {
401                         }
402                         public void windowClosed (WindowEvent JavaDoc e) {
403                         }
404                         public void windowClosing (WindowEvent JavaDoc e) {
405                             if (!changeStateInProgress) {
406                                 w.setVisible (false);
407                                 w.dispose ();
408                             }
409                         }
410                         public void windowDeactivated (WindowEvent JavaDoc e) {
411                         }
412                         public void windowDeiconified (WindowEvent JavaDoc e) {
413                         }
414                         public void windowIconified (WindowEvent JavaDoc e) {
415                         }
416                         public void windowOpened (WindowEvent JavaDoc e) {
417                         }
418                     });
419                 }
420             }
421         });
422     }
423
424     /** Set a different list of panels.
425     * Correctly updates the buttons.
426     * @param panels the new list of {@link WizardDescriptor.Panel}s
427     * @deprecated use setPanelsAndSettings if needed.
428     */

429     @Deprecated JavaDoc
430     @SuppressWarnings JavaDoc("unchecked")
431     public final synchronized void setPanels(Iterator panels) {
432         if (data.getIterator(this) != null) {
433             data.getIterator(this).removeChangeListener(weakChangeListener);
434         }
435
436         data = data.clone(panels);
437         weakChangeListener = WeakListeners.change(baseListener, data.getIterator(this));
438         data.getIterator(this).addChangeListener(weakChangeListener);
439         init = false;
440
441         updateState();
442     }
443
444     /** Set a different list of panels.
445     * Correctly updates the buttons.
446     * @param panels the new list of {@link WizardDescriptor.Panel}s
447     * @param settings the new settings that will be passed to the panels
448     * @since 7.2
449     */

450     public final synchronized <Data> void setPanelsAndSettings(Iterator<Data> panels, Data settings) {
451         if (data.getIterator(this) != null) {
452             data.getIterator(this).removeChangeListener(weakChangeListener);
453         }
454
455         data = new SettingsAndIterator<Data>(panels, settings);
456         weakChangeListener = WeakListeners.change(baseListener, data.getIterator(this));
457         data.getIterator(this).addChangeListener(weakChangeListener);
458         init = false;
459
460         updateState();
461     }
462
463     /** Set options permitted by the wizard considered as a <code>DialogDescriptor</code>.
464     * Substitutes tokens such as {@link #NEXT_OPTION} with the actual button.
465     *
466     * @param options the options to set
467     */

468     public void setOptions(Object JavaDoc[] options) {
469         super.setOptions(convertOptions(options));
470     }
471
472     /**
473     * @param options the options to set
474     */

475     public void setAdditionalOptions(Object JavaDoc[] options) {
476         super.setAdditionalOptions(convertOptions(options));
477     }
478
479     /**
480     * @param options the options to set
481     */

482     public void setClosingOptions(Object JavaDoc[] options) {
483         super.setClosingOptions(convertOptions(options));
484     }
485
486     /** Converts some options.
487     */

488     private Object JavaDoc[] convertOptions(Object JavaDoc[] options) {
489         Object JavaDoc[] clonedOptions = options.clone();
490
491         for (int i = clonedOptions.length - 1; i >= 0; i--) {
492             if (clonedOptions[i] == NEXT_OPTION) {
493                 clonedOptions[i] = nextButton;
494             }
495
496             if (clonedOptions[i] == PREVIOUS_OPTION) {
497                 clonedOptions[i] = previousButton;
498             }
499
500             if (clonedOptions[i] == FINISH_OPTION) {
501                 clonedOptions[i] = finishButton;
502             }
503
504             if (clonedOptions[i] == CANCEL_OPTION) {
505                 clonedOptions[i] = cancelButton;
506             }
507         }
508
509         return clonedOptions;
510     }
511
512     /** Overriden to ensure that returned value is one of
513      * the XXX_OPTION constants.
514      */

515     public Object JavaDoc getValue() {
516         return backConvertOption(super.getValue());
517     }
518
519     /** Converts the option back to one of the constants.
520      * It is called from getValue().
521      */

522     private Object JavaDoc backConvertOption(Object JavaDoc op) {
523         if (op == nextButton) {
524             return NEXT_OPTION;
525         }
526
527         if (op == previousButton) {
528             return PREVIOUS_OPTION;
529         }
530
531         if (op == finishButton) {
532             return FINISH_OPTION;
533         }
534
535         if (op == cancelButton) {
536             return CANCEL_OPTION;
537         }
538
539         // if we don't know just return the original value
540
return op;
541     }
542
543     /** Sets the message format to create title of the wizard.
544     * The format can take two parameters. The name of the
545     * current component and the name returned by the iterator that
546     * defines the order of panels. The default value is something
547     * like
548     * <PRE>
549     * {0} wizard {1}
550     * </PRE>
551     * That can be expanded to something like this
552     * <PRE>
553     * EJB wizard (1 of 8)
554     * </PRE>
555     * This method allows anybody to provide own title format.
556     *
557     * @param format message format to the title
558     */

559     public void setTitleFormat(MessageFormat JavaDoc format) {
560         titleFormat = format;
561
562         if (init) {
563             updateState();
564         }
565     }
566
567     /** Getter for current format to be used to format title.
568     * @return the format
569     * @see #setTitleFormat
570     */

571     public synchronized MessageFormat JavaDoc getTitleFormat() {
572         if (titleFormat == null) {
573             // ok, initialize the default one
574
titleFormat = new MessageFormat JavaDoc(NbBundle.getMessage(WizardDescriptor.class, "CTL_WizardName"));
575         }
576
577         return titleFormat;
578     }
579
580     /** Allows Panels that use WizardDescriptor as settings object to
581     * store additional settings into it.
582     *
583     * @param name name of the property
584     * @param value value of property
585     */

586     public void putProperty(final String JavaDoc name, final Object JavaDoc value) {
587         Object JavaDoc oldValue;
588
589         synchronized (this) {
590             if (properties == null) {
591                 properties = new HashMap JavaDoc<String JavaDoc,Object JavaDoc>(7);
592             }
593
594             oldValue = properties.get(name);
595             properties.put(name, value);
596         }
597
598         // bugfix #27738, firing changes in a value of the property
599
firePropertyChange(name, oldValue, value);
600
601         if (propListener != null) {
602             Mutex.EVENT.readAccess(
603                 new Runnable JavaDoc() {
604                     public void run() {
605                         propListener.propertyChange(new PropertyChangeEvent JavaDoc(this, name, null, null));
606                     }
607                 }
608             );
609         }
610
611         if (PROP_ERROR_MESSAGE.equals(name)) {
612             // #76318: New Entity wizard shows unreadable red error
613
if (init && OK_OPTION.equals (getValue ())) return ; // call getValue() only on initialized WD
614
if (wizardPanel != null) {
615                 SwingUtilities.invokeLater (new Runnable JavaDoc () {
616                     public void run () {
617                         wizardPanel.setErrorMessage((String JavaDoc) ((value == null) ? " " : value), (nextButton.isEnabled () || finishButton.isEnabled ()) ? Boolean.TRUE : Boolean.FALSE); //NOI18N
618
}
619                 });
620             }
621         }
622     }
623
624     /** Getter for stored property.
625     * @param name name of the property
626     * @return the value
627     */

628     public synchronized Object JavaDoc getProperty(String JavaDoc name) {
629         return (properties == null) ? null : properties.get(name);
630     }
631     
632     /** Read only map with stored properties.
633      * @return read only map of properties stored using {@link #putProperty} method
634      * @since 7.2
635      */

636     public synchronized Map JavaDoc<String JavaDoc,Object JavaDoc> getProperties() {
637         return properties == null ? Collections.<String JavaDoc,Object JavaDoc>emptyMap() : new HashMap JavaDoc<String JavaDoc,Object JavaDoc>(properties);
638     }
639
640     public void setHelpCtx(final HelpCtx helpCtx) {
641         if ((wizardPanel != null) && (helpCtx != null)) {
642             HelpCtx.setHelpIDString(wizardPanel, helpCtx.getHelpID());
643         }
644
645         // we call the inherited method after setting the ID
646
// on the panel becuase super.setHelpCtx fires the change
647
super.setHelpCtx(helpCtx);
648     }
649
650     /** Returns set of newly instantiated objects if the wizard has been correctly finished.
651      * Returns the empty set as default. If the wizard uses the InstantiatingIterator
652      * then WizardDescriptor returns a set of Object as same as InstantiatingIterator.instantiate().
653      *
654      * @exception IllegalStateException if this method is called on the unfinished wizard
655      * @return a set of Objects created
656      * @since 4.41
657      */

658     public Set JavaDoc /*<Object>*/ getInstantiatedObjects() {
659         //
660
if (!(FINISH_OPTION.equals(getValue()))) {
661             throw new IllegalStateException JavaDoc();
662         }
663
664         return newObjects;
665     }
666
667     /** Updates buttons to reflect the current state of the panels.
668     * Can be overridden by subclasses
669     * to change the options to special values. In such a case use:
670     * <p><code><PRE>
671     * super.updateState ();
672     * setOptions (...);
673     * </PRE></code>
674     */

675     protected synchronized void updateState() {
676         updateStateOpen(data);
677     }
678     private <A> void updateStateOpen(SettingsAndIterator<A> data) {
679         Panel JavaDoc<A> p = data.getIterator(this).current();
680
681         // listeners on the panel
682
if (data.current != p) {
683             if (data.current != null) {
684                 // remove
685
data.current.removeChangeListener(weakChangeListener);
686                 data.current.storeSettings(data.getSettings(this));
687             }
688
689             // Hack - obtain current panel again
690
// It's here to allow dynamic change of panels in wizard
691
// (which can be done in storeSettings method)
692
p = data.getIterator(this).current();
693
694             // add to new, detach old change listener and attach new one
695
data.getIterator(this).removeChangeListener(weakChangeListener);
696             weakChangeListener = WeakListeners.change(baseListener, p);
697             data.getIterator(this).addChangeListener(weakChangeListener);
698             p.addChangeListener(weakChangeListener);
699
700             data.current = p;
701             p.readSettings(data.getSettings(this));
702         }
703
704         boolean next = data.getIterator(this).hasNext();
705         boolean prev = data.getIterator(this).hasPrevious();
706         boolean valid = p.isValid();
707
708         // AWT sensitive code
709
if (SwingUtilities.isEventDispatchThread ()) {
710             updateStateInAWT ();
711         } else {
712             SwingUtilities.invokeLater (new Runnable JavaDoc () {
713                 public void run () {
714                    updateStateInAWT ();
715                 }
716             });
717         }
718         // end of AWT sensitive code
719

720         // nextButton.setVisible (next);
721
// finishButton.setVisible (!next || (current instanceof FinishPanel));
722
// XXX Why setValue on Next ?
723
// if (next) {
724
// setValue (nextButton);
725
// } else {
726
//// setValue (finishButton);
727
// }
728
setHelpCtx(p.getHelp());
729
730         java.awt.Component JavaDoc c = p.getComponent();
731
732         if ((c == null) || c instanceof java.awt.Window JavaDoc) {
733             throw new IllegalStateException JavaDoc("Wizard panel " + p + " gave a strange component " + c); // NOI18N
734
}
735
736         if (!init) {
737             if (c instanceof JComponent JavaDoc) {
738                 autoWizardStyle = getBooleanProperty((JComponent JavaDoc) c, PROP_AUTO_WIZARD_STYLE);
739
740                 if (autoWizardStyle) {
741                     wizardPanel = new WizardPanel(
742                             getBooleanProperty((JComponent JavaDoc) c, PROP_CONTENT_DISPLAYED),
743                             getBooleanProperty((JComponent JavaDoc) c, PROP_HELP_DISPLAYED),
744                             getBooleanProperty((JComponent JavaDoc) c, PROP_CONTENT_NUMBERED), getLeftDimension((JComponent JavaDoc) c)
745                         );
746                     initBundleProperties();
747                 }
748             }
749
750             if (propListener == null) {
751                 propListener = new PropL();
752             }
753
754             init = true;
755         }
756
757         //update wizardPanel
758
if (wizardPanel != null) {
759             Component JavaDoc oldComp = wizardPanel.getRightComponent();
760
761             if (oldComp != null) {
762                 oldComp.removePropertyChangeListener(weakPropertyChangeListener);
763             }
764
765             if (c instanceof JComponent JavaDoc) {
766                 setPanelProperties((JComponent JavaDoc) c);
767                 wizardPanel.setContent(contentData);
768                 wizardPanel.setSelectedIndex(contentSelectedIndex);
769                 wizardPanel.setContentBackColor(contentBackColor);
770                 wizardPanel.setContentForegroundColor(contentForegroundColor);
771                 wizardPanel.setImage(image);
772                 wizardPanel.setImageAlignment(imageAlignment);
773                 wizardPanel.setHelpURL(helpURL);
774                 updateButtonAccessibleDescription();
775                 weakPropertyChangeListener = WeakListeners.propertyChange(propListener, c);
776                 c.addPropertyChangeListener(weakPropertyChangeListener);
777             }
778
779             if (wizardPanel.getRightComponent() != c) {
780                 wizardPanel.setRightComponent(c);
781
782                 if (wizardPanel != getMessage()) {
783                     setMessage(wizardPanel);
784                 } else {
785                     // force revalidate and repaint because the contents of
786
// wizardPanel has changed. See NbPresenter code
787
firePropertyChange(DialogDescriptor.PROP_MESSAGE, null, wizardPanel);
788                 }
789             }
790         } else if (c != getMessage()) {
791             setMessage(c);
792         }
793
794         String JavaDoc panelName = c.getName();
795
796         if (panelName == null) {
797             panelName = ""; // NOI18N
798
}
799
800         Object JavaDoc[] args = { panelName, data.getIterator(this).name() };
801         MessageFormat JavaDoc mf = getTitleFormat();
802
803         if (autoWizardStyle) {
804             wizardPanel.setPanelName(mf.format(args));
805         } else {
806             setTitle(mf.format(args));
807         }
808
809         Component JavaDoc fo = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
810
811         if ((fo != null) && (!fo.isEnabled()) && (wizardPanel != null)) {
812             wizardPanel.requestFocus();
813         }
814     }
815     
816     // for xtesting usage only
817
boolean isForwardEnabled () {
818         return data.getIterator(this).current ().isValid () && !validationRuns;
819     }
820
821     private void updateStateInAWT () {
822         Panel JavaDoc<?> p = data.getIterator(this).current ();
823         boolean next = data.getIterator(this).hasNext ();
824         boolean prev = data.getIterator(this).hasPrevious ();
825         boolean valid = p.isValid () && !validationRuns;
826
827         nextButton.setEnabled (next && valid);
828         previousButton.setEnabled (prev);
829         cancelButton.setEnabled (true);
830         
831         if (data.current instanceof FinishablePanel) {
832             // check if isFinishPanel
833
if (((FinishablePanel)data.current).isFinishPanel ()) {
834                 finishButton.setEnabled (valid);
835             } else {
836                 // XXX What if the last panel is not FinishPanel ??? enable ?
837
finishButton.setEnabled (valid && !next);
838             }
839         } else {
840             // original way
841
finishButton.setEnabled (
842                 valid &&
843                 (!next || (data.current instanceof FinishPanel))
844             );
845         }
846     }
847
848     
849     /** Shows blocking wait cursor during updateState run */
850     private void updateStateWithFeedback() {
851         try {
852             showWaitCursor();
853             updateState();
854         } finally {
855             showNormalCursor();
856         }
857     }
858
859     /** Shows next step in UI of wizards, displays wait cursot during the change.
860      */

861     private void goToNextStep(Dimension JavaDoc previousSize) {
862         try {
863             showWaitCursor();
864
865             boolean alreadyUpdated = false;
866             Font JavaDoc controlFont = (Font JavaDoc) UIManager.getDefaults().get("controlFont"); //NOI18N
867
Integer JavaDoc defaultSize = (Integer JavaDoc) UIManager.get("nbDefaultFontSize");
868
869             if (defaultSize == null) {
870                 //Plastic look and feel...
871
defaultSize = new Integer JavaDoc(11);
872             }
873
874             // enable auto-resizing policy only for fonts bigger thne default
875
if ((controlFont != null) && (controlFont.getSize() > defaultSize.intValue())) { //NOI18N
876

877                 Window JavaDoc parentWindow = SwingUtilities.getWindowAncestor((Component JavaDoc) getMessage());
878
879                 if (parentWindow != null) {
880                     updateState();
881                     alreadyUpdated = true;
882                     resizeWizard(parentWindow, previousSize);
883                 }
884             }
885
886             if (!alreadyUpdated) {
887                 updateState();
888             }
889
890             if (wizardPanel != null) {
891                 wizardPanel.requestFocus();
892             }
893         } finally {
894             showNormalCursor();
895         }
896     }
897
898     /** Tries to resize wizard wisely if needed. Keeps "display inertia" so that
899      * wizard is only enlarged, not shrinked, and location is changed only when
900      * wizard window exceeds screen bounds after resize.
901      */

902     private void resizeWizard(Window JavaDoc parentWindow, Dimension JavaDoc prevSize) {
903         Dimension JavaDoc curSize = data.getIterator(this).current().getComponent().getPreferredSize();
904
905         // only enlarge if needed, don't shrink
906
if ((curSize.width > prevSize.width) || (curSize.height > prevSize.height)) {
907             Rectangle JavaDoc origBounds = parentWindow.getBounds();
908             int newWidth = Math.max(origBounds.width + (curSize.width - prevSize.width), origBounds.width);
909             int newHeight = Math.max(origBounds.height + (curSize.height - prevSize.height), origBounds.height);
910             Rectangle JavaDoc screenBounds = Utilities.getUsableScreenBounds();
911             Rectangle JavaDoc newBounds;
912
913             // don't allow to exceed screen size, center if needed
914
if (((origBounds.x + newWidth) > screenBounds.width) || ((origBounds.y + newHeight) > screenBounds.height)) {
915                 newWidth = Math.min(screenBounds.width, newWidth);
916                 newHeight = Math.min(screenBounds.height, newHeight);
917                 newBounds = Utilities.findCenterBounds(new Dimension JavaDoc(newWidth, newHeight));
918             } else {
919                 newBounds = new Rectangle JavaDoc(origBounds.x, origBounds.y, newWidth, newHeight);
920             }
921
922             parentWindow.setBounds(newBounds);
923             parentWindow.invalidate();
924             parentWindow.validate();
925             parentWindow.repaint();
926         }
927     }
928
929     private void showWaitCursor() {
930         if ((wizardPanel == null) || (wizardPanel.getRootPane() == null)) {
931             // if none root pane --> don't set wait cursor
932
return;
933         }
934         
935         // bugfix #92539: JR: I don't see the reason this code, I have tried comment out
936
// Window parentWindow = SwingUtilities.getWindowAncestor((Component) getMessage());
937
// if (parentWindow != null) {
938
// parentWindow.setEnabled (false);
939
// }
940
//
941
if (wizardPanel != null) {
942             // save escapeActionListener for normal state
943
KeyStroke JavaDoc ks = KeyStroke.getKeyStroke (KeyEvent.VK_ESCAPE, 0);
944             escapeActionListener = wizardPanel.getRootPane ().getActionForKeyStroke (ks);
945             wizardPanel.getRootPane ().unregisterKeyboardAction (ks);
946         }
947
948         waitingComponent = wizardPanel.getRootPane().getContentPane();
949         waitingComponent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
950         changeStateInProgress = true;
951     }
952
953     private void showNormalCursor() {
954         if (waitingComponent == null) {
955             // none waitingComponent --> don't change cursor to normal
956
return;
957         }
958         
959         Window JavaDoc parentWindow = SwingUtilities.getWindowAncestor((Component JavaDoc) getMessage());
960         if (parentWindow != null) {
961             parentWindow.setEnabled (true);
962         }
963         
964         if (wizardPanel != null) {
965             // set back escapeActionListener as same as NbPresenter does
966
if (escapeActionListener != null) {
967                 wizardPanel.getRootPane ().registerKeyboardAction (escapeActionListener, "Escape",
968                     KeyStroke.getKeyStroke (KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
969             }
970         }
971         
972         waitingComponent.setCursor(null);
973         waitingComponent = null;
974         changeStateInProgress = false;
975     }
976
977     /* commented out - issue #32927. Replaced by javadoc info in WizardDescriptor.Panel
978     private static final Set warnedPanelIsComponent = new WeakSet(); // Set<Class>
979     private static synchronized void warnPanelIsComponent(Class c) {
980         if (warnedPanelIsComponent.add(c)) {
981             StringBuffer buffer = new StringBuffer(150);
982             buffer.append("WARNING - the WizardDescriptor.Panel implementation "); // NOI18N
983             buffer.append(c.getName());
984             buffer.append(" provides itself as the result of getComponent().\n"); // NOI18N
985             buffer.append("This hurts performance and can cause a clash when Component.isValid() is overridden.\n"); // NOI18N
986             buffer.append("Please use a separate component class, see details at http://performance.netbeans.org/howto/dialogs/wizard-panels.html."); // NOI18N
987             err.log(ErrorManager.WARNING, buffer.toString());
988         }
989     }
990     */

991
992     /** Tryes to get property from getProperty() if doesn't succeed then tryes at
993      * supplied <CODE>JComponent</CODE>s client property.
994      * @param c origin of property
995      * @param s name of property
996      * @return boolean property
997      */

998     private boolean getBooleanProperty(JComponent JavaDoc c, String JavaDoc s) {
999         Object JavaDoc property = getProperty(s);
1000
1001        if (property instanceof Boolean JavaDoc) {
1002            return ((Boolean JavaDoc) property).booleanValue();
1003        }
1004
1005        property = c.getClientProperty(s);
1006
1007        if (property instanceof Boolean JavaDoc) {
1008            return ((Boolean JavaDoc) property).booleanValue();
1009        }
1010
1011        return false;
1012    }
1013
1014    /** Tryes to get dimension of wizard panel's left pane from getProperty()
1015     * if doesn't succeed then tryes at
1016     * supplied <CODE>JComponent</CODE>s client property.
1017     * @return <CODE>Dimension</CODE> dimension of wizard panel's left pane
1018     */

1019    private Dimension JavaDoc getLeftDimension(JComponent JavaDoc c) {
1020        Dimension JavaDoc leftDimension;
1021        Object JavaDoc property = c.getClientProperty(PROP_LEFT_DIMENSION);
1022
1023        if (property instanceof Dimension JavaDoc) {
1024            leftDimension = (Dimension JavaDoc) property;
1025        } else {
1026            leftDimension = new Dimension JavaDoc(198, 233);
1027        }
1028
1029        return leftDimension;
1030    }
1031
1032    /** Tryes to get properties from getProperty() if doesn't succeed then tryes at
1033     * supplied <CODE>JComponent</CODE>s client properties and store them
1034     * to appropriate fields.
1035     * @param c origin of property
1036     * @param s name of property
1037     * @return boolean property
1038     */

1039    private void setPanelProperties(JComponent JavaDoc c) {
1040        // TODO: Method should be devided into individual setter/getter methods !?
1041
Object JavaDoc property = getProperty(PROP_CONTENT_SELECTED_INDEX);
1042
1043        if (property instanceof Integer JavaDoc) {
1044            contentSelectedIndex = ((Integer JavaDoc) property).intValue();
1045        } else {
1046            property = c.getClientProperty(PROP_CONTENT_SELECTED_INDEX);
1047
1048            if (property instanceof Integer JavaDoc) {
1049                contentSelectedIndex = ((Integer JavaDoc) property).intValue();
1050            }
1051        }
1052
1053        property = getProperty(PROP_CONTENT_DATA);
1054
1055        if (property instanceof String JavaDoc[]) {
1056            contentData = (String JavaDoc[]) property;
1057        } else {
1058            property = c.getClientProperty(PROP_CONTENT_DATA);
1059
1060            if (property instanceof String JavaDoc[]) {
1061                contentData = (String JavaDoc[]) property;
1062            }
1063        }
1064
1065        property = getProperty(PROP_IMAGE);
1066
1067        if (property instanceof Image JavaDoc) {
1068            image = (Image JavaDoc) property;
1069        } else if ((properties == null) || (!properties.containsKey(PROP_IMAGE))) {
1070            property = c.getClientProperty(PROP_IMAGE);
1071
1072            if (property instanceof Image JavaDoc) {
1073                image = (Image JavaDoc) property;
1074            }
1075        }
1076
1077        property = getProperty(PROP_IMAGE_ALIGNMENT);
1078
1079        if (property instanceof String JavaDoc) {
1080            imageAlignment = (String JavaDoc) property;
1081        } else {
1082            property = c.getClientProperty(PROP_IMAGE_ALIGNMENT);
1083
1084            if (property instanceof String JavaDoc) {
1085                imageAlignment = (String JavaDoc) property;
1086            }
1087        }
1088
1089        property = getProperty(PROP_CONTENT_BACK_COLOR);
1090
1091        if (property instanceof Color JavaDoc) {
1092            contentBackColor = (Color JavaDoc) property;
1093        } else {
1094            property = c.getClientProperty(PROP_CONTENT_BACK_COLOR);
1095
1096            if (property instanceof Color JavaDoc) {
1097                contentBackColor = (Color JavaDoc) property;
1098            }
1099        }
1100
1101        property = getProperty(PROP_CONTENT_FOREGROUND_COLOR);
1102
1103        if (property instanceof Color JavaDoc) {
1104            contentForegroundColor = (Color JavaDoc) property;
1105        } else {
1106            property = c.getClientProperty(PROP_CONTENT_FOREGROUND_COLOR);
1107
1108            if (property instanceof Color JavaDoc) {
1109                contentForegroundColor = (Color JavaDoc) property;
1110            }
1111        }
1112
1113        property = c.getClientProperty(PROP_HELP_URL);
1114
1115        if (property instanceof URL JavaDoc) {
1116            helpURL = (URL JavaDoc) property;
1117        } else if (property == null) {
1118            helpURL = null;
1119        }
1120    }
1121
1122    private void initBundleProperties() {
1123        contentBackColor = new Color JavaDoc(
1124                getIntFromBundle("INT_WizardBackRed"), // NOI18N
1125
getIntFromBundle("INT_WizardBackGreen"), // NOI18N
1126
getIntFromBundle("INT_WizardBackBlue") // NOI18N
1127
); // NOI18N
1128

1129        contentForegroundColor = new Color JavaDoc(
1130                getIntFromBundle("INT_WizardForegroundRed"), // NOI18N
1131
getIntFromBundle("INT_WizardForegroundGreen"), // NOI18N
1132
getIntFromBundle("INT_WizardForegroundBlue") // NOI18N
1133
); // NOI18N
1134
imageAlignment = bundle.getString("STRING_WizardImageAlignment"); //NOI18N
1135
}
1136
1137    /** Overrides superclass method. Adds reseting of wizard
1138     * for <code>CLOSED_OPTION</code>. */

1139    public void setValue(Object JavaDoc value) {
1140        setValueOpen(value, data);
1141    }
1142    
1143    private <A> void setValueOpen(Object JavaDoc value, SettingsAndIterator<A> data) {
1144        Object JavaDoc convertedValue = backConvertOption(value);
1145        // set new value w/o fire PROP_VALUE change
1146
Object JavaDoc oldValue = getValue();
1147        setValueWithoutPCH(convertedValue);
1148
1149        // #17360: Reset wizard on CLOSED_OPTION too.
1150
if (CLOSED_OPTION.equals(convertedValue)) {
1151            try {
1152                resetWizard();
1153            } catch (RuntimeException JavaDoc x) {
1154                // notify to log
1155
err.log(Level.FINE, null, x);
1156            }
1157        } else if (FINISH_OPTION.equals(convertedValue) || NEXT_OPTION.equals(convertedValue)) {
1158            //Bugfix #25820: make sure that storeSettings
1159
//is called before propertyChange.
1160
if (data.current != null) {
1161                data.current.storeSettings(data.getSettings(this));
1162            }
1163        }
1164
1165        // notify listeners about PROP_VALUE change
1166
firePropertyChange(PROP_VALUE, oldValue, convertedValue);
1167    }
1168
1169    /** Resets wizard when after closed/cancelled/finished the wizard dialog. */
1170    private void resetWizard() {
1171        resetWizardOpen(data);
1172    }
1173    
1174    private <A> void resetWizardOpen(SettingsAndIterator<A> data) {
1175        if (data.current != null) {
1176            data.current.storeSettings(data.getSettings(this));
1177            data.current.removeChangeListener(weakChangeListener);
1178            data.current = null;
1179
1180            if (wizardPanel != null) {
1181                wizardPanel.resetPreferredSize();
1182            }
1183        }
1184
1185        callUninitialize();
1186
1187        // detach the change listener at the end of wizard
1188
data.getIterator(this).removeChangeListener(weakChangeListener);
1189    }
1190
1191    private int getIntFromBundle(String JavaDoc key) {
1192        return Integer.parseInt(bundle.getString(key));
1193    }
1194
1195    private static Image JavaDoc getDefaultImage() {
1196        return Utilities.loadImage("org/netbeans/modules/dialogs/defaultWizard.gif", true);
1197    }
1198
1199    private void updateButtonAccessibleDescription() {
1200        String JavaDoc stepName = ((contentData != null) && (contentSelectedIndex > 0) &&
1201            ((contentSelectedIndex - 1) < contentData.length)) ? contentData[contentSelectedIndex - 1] : ""; // NOI18N
1202
previousButton.getAccessibleContext().setAccessibleDescription(
1203            NbBundle.getMessage(WizardDescriptor.class, "ACSD_PREVIOUS", new Integer JavaDoc(contentSelectedIndex), stepName)
1204        );
1205
1206        stepName = ((contentData != null) && (contentSelectedIndex < (contentData.length - 1)) &&
1207            ((contentSelectedIndex + 1) >= 0)) ? contentData[contentSelectedIndex + 1] : ""; // NOI18N
1208
nextButton.getAccessibleContext().setAccessibleDescription(
1209            NbBundle.getMessage(WizardDescriptor.class, "ACSD_NEXT", new Integer JavaDoc(contentSelectedIndex + 2), stepName)
1210        );
1211    }
1212
1213    private void lazyValidate(final WizardDescriptor.Panel panel, final Runnable JavaDoc onValidPerformer) {
1214
1215        Runnable JavaDoc validationPeformer = new Runnable JavaDoc() {
1216            public void run() {
1217                
1218                err.log (Level.FINE, "validationPeformer entry."); // NOI18N
1219
ValidatingPanel v = (ValidatingPanel) panel;
1220
1221                try {
1222                    // try validation current panel
1223
v.validate();
1224                    validationRuns = false;
1225
1226                    // validation succesfull
1227
if (SwingUtilities.isEventDispatchThread ()) {
1228                        err.log (Level.FINE, "Runs onValidPerformer directly in EDT."); // NOI18N
1229
onValidPerformer.run();
1230                    } else {
1231                        err.log (Level.FINE, "invokeLater onValidPerformer."); // NOI18N
1232
SwingUtilities.invokeLater (new Runnable JavaDoc () {
1233                            public void run () {
1234                                err.log (Level.FINE, "Runs onValidPerformer from invokeLater."); // NOI18N
1235
onValidPerformer.run();
1236                            }
1237                        });
1238                    }
1239                } catch (WizardValidationException wve) {
1240                    validationRuns = false;
1241                    updateState ();
1242                    
1243                    // cannot continue, notify user
1244
if (wizardPanel != null) {
1245                        wizardPanel.setErrorMessage(wve.getLocalizedMessage(), Boolean.FALSE);
1246                    }
1247
1248                    // focus source of this problem
1249
final JComponent JavaDoc comp = wve.getSource();
1250                    if (comp != null && comp.isFocusable()) {
1251                        comp.requestFocus();
1252                    }
1253                }
1254
1255            }
1256        };
1257
1258        if (panel instanceof AsynchronousValidatingPanel) {
1259            AsynchronousValidatingPanel p = (AsynchronousValidatingPanel) panel;
1260            validationRuns = true; // disable Next> Finish buttons
1261
p.prepareValidation();
1262            err.log (Level.FINE, "Do ASYNCHRONOUS_JOBS_RP.post(validationPeformer)."); // NOI18N
1263
updateStateWithFeedback ();
1264            backgroundValidationTask = ASYNCHRONOUS_JOBS_RP.post(validationPeformer);
1265        } else if (panel instanceof ValidatingPanel) {
1266            validationRuns = true;
1267            err.log (Level.FINE, "Runs validationPeformer."); // NOI18N
1268
validationPeformer.run();
1269        } else {
1270            err.log (Level.FINE, "Runs onValidPerformer."); // NOI18N
1271
onValidPerformer.run();
1272        }
1273
1274    }
1275
1276    // helper methods which call to InstantiatingIterator
1277
private void callInitialize() {
1278        assert data.getIterator(this) != null;
1279
1280        if (data.getIterator(this) instanceof InstantiatingIterator) {
1281            ((InstantiatingIterator) data.getIterator(this)).initialize(this);
1282        }
1283
1284        newObjects = Collections.EMPTY_SET;
1285    }
1286
1287    private void callUninitialize() {
1288        assert data.getIterator(this) != null;
1289
1290        if (data.getIterator(this) instanceof InstantiatingIterator) {
1291            ((InstantiatingIterator) data.getIterator(this)).uninitialize(this);
1292        }
1293    }
1294
1295    private void callInstantiate() throws IOException JavaDoc {
1296        callInstantiateOpen(data);
1297    }
1298    
1299    private <A> void callInstantiateOpen(SettingsAndIterator<A> data) throws IOException JavaDoc {
1300        Iterator<A> panels = data.getIterator(this);
1301        
1302        assert panels != null;
1303        
1304        err.log (Level.FINE, "Is AsynchronousInstantiatingIterator? " + (panels instanceof AsynchronousInstantiatingIterator));
1305        err.log (Level.FINE, "Is ProgressInstantiatingIterator? " + (panels instanceof ProgressInstantiatingIterator));
1306        if (panels instanceof ProgressInstantiatingIterator) {
1307            handle = ProgressHandleFactory.createHandle (PROGRESS_BAR_DISPLAY_NAME);
1308            
1309            JComponent JavaDoc progressComp = ProgressHandleFactory.createProgressComponent (handle);
1310            if (wizardPanel != null) {
1311                wizardPanel.setProgressComponent (progressComp, ProgressHandleFactory.createDetailLabelComponent (handle));
1312            }
1313            
1314            err.log (Level.FINE, "Show progressPanel controlled by iterator later.");
1315        } else if (panels instanceof AsynchronousInstantiatingIterator) {
1316            handle = ProgressHandleFactory.createHandle (PROGRESS_BAR_DISPLAY_NAME);
1317            
1318            JComponent JavaDoc progressComp = ProgressHandleFactory.createProgressComponent (handle);
1319            if (wizardPanel != null) {
1320                wizardPanel.setProgressComponent (progressComp, ProgressHandleFactory.createMainLabelComponent (handle));
1321            }
1322            
1323            handle.start ();
1324            err.log (Level.FINE, "Show progressPanel later.");
1325        }
1326         
1327        // bugfix #44444, force store settings before do instantiate new objects
1328
panels.current().storeSettings(data.getSettings(this));
1329
1330        if (panels instanceof InstantiatingIterator) {
1331            showWaitCursor();
1332
1333            try {
1334                assert ! (panels instanceof AsynchronousInstantiatingIterator) || ! SwingUtilities.isEventDispatchThread () : "Cannot invoked within EDT if AsynchronousInstantiatingIterator!";
1335                
1336                if (panels instanceof ProgressInstantiatingIterator) {
1337                    assert handle != null : "ProgressHandle must be not null.";
1338                    err.log (Level.FINE, "Calls instantiate(ProgressHandle) on iterator: " + panels.getClass ().getName ());
1339                    newObjects = ((ProgressInstantiatingIterator) panels).instantiate (handle);
1340                } else {
1341                    err.log (Level.FINE, "Calls instantiate() on iterator: " + panels.getClass ().getName ());
1342                    newObjects = ((InstantiatingIterator) panels).instantiate ();
1343                }
1344            } finally {
1345
1346                // set cursor back to normal
1347
showNormalCursor();
1348                
1349            }
1350        }
1351    }
1352
1353    private static Font JavaDoc doDeriveFont(Font JavaDoc original, int style) {
1354        if (Utilities.isMac()) {
1355            // don't use deriveFont() - see #49973 for details
1356
return new Font JavaDoc(original.getName(), style, original.getSize());
1357        }
1358
1359        return original.deriveFont(style);
1360    }
1361
1362    // support methods for xtesting
1363
final void doNextClick() {
1364        if (nextButton.isEnabled()) {
1365            nextButton.doClick();
1366        }
1367    }
1368
1369    final void doPreviousClick() {
1370        if (previousButton.isEnabled()) {
1371            previousButton.doClick();
1372        }
1373    }
1374
1375    final void doFinishClick() {
1376        if (finishButton.isEnabled()) {
1377            finishButton.doClick();
1378        }
1379    }
1380
1381    final void doCancelClick() {
1382        if (cancelButton.isEnabled()) {
1383            cancelButton.doClick();
1384        }
1385    }
1386
1387    // helper method, might be removed from code
1388
// returns false if Next button is disabled
1389
final boolean isNextEnabled() {
1390        return nextButton.isEnabled();
1391    }
1392
1393    // helper method, might be removed from code
1394
// returns false if Finish button is disabled
1395
final boolean isFinishEnabled() {
1396        return finishButton.isEnabled();
1397    }
1398
1399    /** Iterator on the sequence of panels.
1400    * @see WizardDescriptor.Panel
1401    */

1402    public interface Iterator<Data> {
1403        /** Get the current panel.
1404        * @return the panel
1405        */

1406        public Panel JavaDoc<Data> current();
1407
1408        /** Get the name of the current panel.
1409        * @return the name
1410        */

1411        public String JavaDoc name();
1412
1413        /** Test whether there is a next panel.
1414        * @return <code>true</code> if so
1415        */

1416        public boolean hasNext();
1417
1418        /** Test whether there is a previous panel.
1419        * @return <code>true</code> if so
1420        */

1421        public boolean hasPrevious();
1422
1423        /** Move to the next panel.
1424        * I.e. increment its index, need not actually change any GUI itself.
1425        * @exception NoSuchElementException if the panel does not exist
1426        */

1427        public void nextPanel();
1428
1429        /** Move to the previous panel.
1430        * I.e. decrement its index, need not actually change any GUI itself.
1431        * @exception NoSuchElementException if the panel does not exist
1432        */

1433        public void previousPanel();
1434
1435        /** Add a listener to changes of the current panel.
1436        * The listener is notified when the possibility to move forward/backward changes.
1437        * @param l the listener to add
1438        */

1439        public void addChangeListener(ChangeListener JavaDoc l);
1440
1441        /** Remove a listener to changes of the current panel.
1442        * @param l the listener to remove
1443        */

1444        public void removeChangeListener(ChangeListener JavaDoc l);
1445    }
1446
1447    /** One wizard panel with a component on it.
1448     *
1449     * For good performance, implementation of this interface should be as
1450     * lightweight as possible. Defer creation and initialization of
1451     * UI component of wizard panel into {@link #getComponent} method.
1452     *
1453     * Please see complete guide at http://performance.netbeans.org/howto/dialogs/wizard-panels.html
1454     */

1455    public interface Panel<Data> {
1456        /** Get the component displayed in this panel.
1457         *
1458         * Note; method can be called from any thread, but not concurrently
1459         * with other methods of this interface. Please see complete guide at
1460         * http://performance.netbeans.org/howto/dialogs/wizard-panels.html for
1461         * correct implementation.
1462         *
1463         * @return the UI component of this wizard panel
1464         */

1465        public java.awt.Component JavaDoc getComponent();
1466
1467        /** Help for this panel.
1468        * When the panel is active, this is used as the help for the wizard dialog.
1469        * @return the help or <code>null</code> if no help is supplied
1470        */

1471        public HelpCtx getHelp();
1472
1473        /** Provides the wizard panel with the current data--either
1474        * the default data or already-modified settings, if the user used the previous and/or next buttons.
1475        * This method can be called multiple times on one instance of <code>WizardDescriptor.Panel</code>.
1476        * <p>The settings object is originally supplied to {@link WizardDescriptor#WizardDescriptor(WizardDescriptor.Iterator,Object)}.
1477        * In the case of a <code>TemplateWizard.Iterator</code> panel, the object is
1478        * in fact the <code>TemplateWizard</code>.
1479        * @param settings the object representing wizard panel state
1480        * @exception IllegalStateException if the the data provided
1481        * by the wizard are not valid.
1482        */

1483        public void readSettings(Data settings);
1484
1485        /** Provides the wizard panel with the opportunity to update the
1486        * settings with its current customized state.
1487        * Rather than updating its settings with every change in the GUI, it should collect them,
1488        * and then only save them when requested to by this method.
1489        * Also, the original settings passed to {@link #readSettings} should not be modified (mutated);
1490        * rather, the object passed in here should be mutated according to the collected changes,
1491        * in case it is a copy.
1492        * This method can be called multiple times on one instance of <code>WizardDescriptor.Panel</code>.
1493        * <p>The settings object is originally supplied to {@link WizardDescriptor#WizardDescriptor(WizardDescriptor.Iterator,Object)}.
1494        * In the case of a <code>TemplateWizard.Iterator</code> panel, the object is
1495        * in fact the <code>TemplateWizard</code>.
1496        * @param settings the object representing wizard panel state
1497        */

1498        public void storeSettings(Data settings);
1499
1500        /** Test whether the panel is finished and it is safe to proceed to the next one.
1501        * If the panel is valid, the "Next" (or "Finish") button will be enabled.
1502        * <p><strong>Tip:</strong> if your panel is actually the component itself
1503        * (so {@link #getComponent} returns <code>this</code>), be sure to specifically
1504        * override this method, as the unrelated implementation in {@link java.awt.Component#isValid}
1505        * if not overridden could cause your wizard to behave erratically.
1506        * @return <code>true</code> if the user has entered satisfactory information
1507        */

1508        public boolean isValid();
1509
1510        /** Add a listener to changes of the panel's validity.
1511        * @param l the listener to add
1512        * @see #isValid
1513        */

1514        public void addChangeListener(ChangeListener JavaDoc l);
1515
1516        /** Remove a listener to changes of the panel's validity.
1517        * @param l the listener to remove
1518        */

1519        public void removeChangeListener(ChangeListener JavaDoc l);
1520    }
1521
1522    /** A special interface for panels in middle of the
1523    * iterators path that would like to have the finish button
1524    * enabled. So both Next and Finish are enabled on panel
1525    * implementing this interface.
1526    * @deprecated 4.28 Use FinishablePanel instead.
1527    */

1528    @Deprecated JavaDoc
1529    public interface FinishPanel<Data> extends Panel JavaDoc<Data> {
1530    }
1531
1532    /** A special interface for panels that need to do additional
1533     * validation when Next or Finish button is clicked.
1534     * @since 4.28
1535     */

1536    public interface ValidatingPanel<Data> extends Panel JavaDoc<Data> {
1537        /**
1538         * Is called when Next of Finish buttons are clicked and
1539         * allows deeper check to find out that panel is in valid
1540         * state and it is ok to leave it.
1541         *
1542         * @throws WizardValidationException when validation fails
1543         * @since 4.28
1544         */

1545        public void validate() throws WizardValidationException;
1546    }
1547
1548
1549    /**
1550     * A special interface for panels that need to do additional
1551     * asynchronous validation when Next or Finish button is clicked.
1552     *
1553     * <p>During backround validation is Next or Finish button
1554     * disabled. On validation success wizard automatically
1555     * progress to next panel or finishes.
1556     *
1557     * <p>During backround validation Cancel button is hooked
1558     * to signal the validation thread using interrupt().
1559     *
1560     * @since 6.2 (16 May 2005)
1561     */

1562    public interface AsynchronousValidatingPanel<Data> extends ValidatingPanel<Data> {
1563
1564        /**
1565         * Called synchronously from UI thread when Next
1566         * of Finish buttons clicked. It allows to lock user
1567         * input to assure official data for background validation.
1568         */

1569        public void prepareValidation();
1570
1571        /**
1572         * Is called in separate thread when Next of Finish buttons
1573         * are clicked and allows deeper check to find out that panel
1574         * is in valid state and it is ok to leave it.
1575         *
1576         * @throws WizardValidationException when validation fails
1577         */

1578        public void validate() throws WizardValidationException;
1579    }
1580
1581
1582    /** A special interface for panel that needs to dynamically enabled
1583     * Finish button.
1584     * @since 4.28
1585     */

1586    public interface FinishablePanel<Data> extends Panel JavaDoc<Data> {
1587        /** Specify if this panel would enable Finish button. Finish button is
1588         * enabled if and only if isValid() returns true and isFinishPanel()
1589         * returns true.
1590         *
1591         * @return Finish button could be enabled
1592         * @since 4.28
1593         */

1594        boolean isFinishPanel();
1595    }
1596
1597    /**
1598     * Iterator for a wizard that needs to somehow instantiate new objects.
1599     * (This interface can replace
1600     * <a HREF="@OPENIDE/LOADERS@/org/openide/loaders/TemplateWizard.Iterator.html"><code>TemplateWizard.Iterator</code></a>
1601     * in a template's declaration.)
1602     * @since org.openide/1 4.33
1603     */

1604    public interface InstantiatingIterator<Data> extends Iterator<Data> {
1605        /** Returns set of instantiated objects. If instantiation fails then wizard remains open to enable correct values.
1606         *
1607         * @throws IOException
1608         * @return a set of objects created (the exact type is at the discretion of the caller)
1609         */

1610        public Set JavaDoc/*<?>*/ instantiate() throws IOException JavaDoc;
1611
1612        /** Initializes this iterator, called from WizardDescriptor's constructor.
1613         *
1614         * @param wizard wizard's descriptor
1615         */

1616        public void initialize(WizardDescriptor wizard);
1617
1618        /** Uninitializes this iterator, called when the wizard is being
1619         * closed, no matter what closing option invoked.
1620         *
1621         * @param wizard wizard's descriptor
1622         */

1623        public void uninitialize(WizardDescriptor wizard);
1624    }
1625    
1626    /**
1627     * Iterator for a wizard that needs to somehow instantiate new objects outside ATW queue.
1628     * (This interface can replace
1629     * <a HREF="@OPENIDE/LOADERS@/org/openide/loaders/TemplateWizard.Iterator.html"><code>TemplateWizard.Iterator</code></a>
1630     * in a template's declaration.)
1631     * @since org.openide/1 6.5
1632     */

1633    public interface AsynchronousInstantiatingIterator<Data> extends InstantiatingIterator<Data> {
1634
1635        /**
1636         * Is called in separate thread when the Finish button
1637         * are clicked and allows implement asynchronous
1638         * instantating of newly created objects.
1639         *
1640         * @throws IOException when instantiate fails
1641         * @return a set of objects created (the exact type is at the discretion of the caller)
1642         */

1643        public Set JavaDoc/*<?>*/ instantiate () throws IOException JavaDoc;
1644
1645    }
1646
1647    /**
1648     * Iterator for a wizard that wants to notify users while instantiate is running by a progress bar.
1649     * The method <code>instantiate</code> is called outside ATW queue.
1650     * (This interface can replace
1651     * <a HREF="@OPENIDE/LOADERS@/org/openide/loaders/TemplateWizard.Iterator.html"><code>TemplateWizard.Iterator</code></a>
1652     * in a template's declaration.)
1653     * @since org.openide.dialogs 7.1
1654     */

1655    public interface ProgressInstantiatingIterator<Data> extends AsynchronousInstantiatingIterator<Data> {
1656
1657        /**
1658         * Is called in separate thread when the Finish button
1659         * are clicked and allows implement asynchronous instantating of newly created objects.
1660         * While instantiating users are notified by progress bar in wizard's panel. Notfication will
1661         * be visualized by a progress bar.
1662         * Note: The <code>ProgressHandle</code> is not started, need to start it and report progress by
1663         * messages in the <code>progress()</code> method.
1664         *
1665         * @param handle progress bar handle
1666         * @throws IOException when instantiate fails
1667         * @return a set of objects created (the exact type is at the discretion of the caller)
1668         */

1669        public Set JavaDoc/*<?>*/ instantiate (ProgressHandle handle) throws IOException JavaDoc;
1670        
1671    }
1672
1673    /** Special iterator that works on an array of <code>Panel</code>s.
1674    */

1675    public static class ArrayIterator<Data> extends Object JavaDoc implements Iterator<Data> {
1676        /** Array of items.
1677        */

1678        private Panel JavaDoc<Data>[] panels;
1679
1680        /** Index into the array
1681        */

1682        private int index;
1683
1684        /* Default constructor. It's here to allow subclasses to
1685        * be serializable easily. Panel initialization is done
1686        * through initializePanels() protected method. */

1687        public ArrayIterator() {
1688            panels = initializePanels();
1689            index = 0;
1690        }
1691
1692        /** Construct an iterator.
1693        * @param array the list of panels to use
1694        */

1695        public ArrayIterator(Panel JavaDoc<Data>[] array) {
1696            panels = array;
1697            index = 0;
1698        }
1699
1700        /** Allows subclasses to initialize their arrays of panels when
1701        * constructed using default constructor.
1702        * (for example during deserialization.
1703        * Default implementation returns empty array. */

1704        @SuppressWarnings JavaDoc("unchecked")
1705        protected Panel JavaDoc<Data>[] initializePanels() {
1706            return new Panel JavaDoc[0];
1707        }
1708
1709        /* The current panel.
1710        */

1711        public Panel JavaDoc<Data> current() {
1712            return panels[index];
1713        }
1714
1715        /* Current name of the panel */
1716        public String JavaDoc name() {
1717            return NbBundle.getMessage(
1718                WizardDescriptor.class, "CTL_ArrayIteratorName", new Integer JavaDoc(index + 1), new Integer JavaDoc(panels.length)
1719            );
1720        }
1721
1722        /* Is there a next panel?
1723        * @return true if so
1724        */

1725        public boolean hasNext() {
1726            return index < (panels.length - 1);
1727        }
1728
1729        /* Is there a previous panel?
1730        * @return true if so
1731        */

1732        public boolean hasPrevious() {
1733            return index > 0;
1734        }
1735
1736        /* Moves to the next panel.
1737        * @exception NoSuchElementException if the panel does not exist
1738        */

1739        public synchronized void nextPanel() {
1740            if ((index + 1) == panels.length) {
1741                throw new java.util.NoSuchElementException JavaDoc();
1742            }
1743
1744            index++;
1745        }
1746
1747        /* Moves to previous panel.
1748        * @exception NoSuchElementException if the panel does not exist
1749        */

1750        public synchronized void previousPanel() {
1751            if (index == 0) {
1752                throw new java.util.NoSuchElementException JavaDoc();
1753            }
1754
1755            index--;
1756        }
1757
1758        /* Ignores the listener, there are no changes in order of panels.
1759        */

1760        public void addChangeListener(ChangeListener JavaDoc l) {
1761        }
1762
1763        /* Ignored.
1764        */

1765        public void removeChangeListener(ChangeListener JavaDoc l) {
1766        }
1767
1768        /** Resets this iterator to initial state.
1769        * Called by subclasses when they need re-initialization of the iterator.
1770        */

1771        protected void reset() {
1772            index = 0;
1773        }
1774    }
1775
1776    /** Listener to changes in the iterator and panels.
1777    */

1778    private final class Listener implements ChangeListener JavaDoc, ActionListener JavaDoc {
1779        Listener() {
1780        }
1781
1782        /** Change in the observed objects */
1783        public void stateChanged(ChangeEvent JavaDoc ev) {
1784            updateState();
1785        }
1786
1787        /** Action listener */
1788        public void actionPerformed(ActionEvent JavaDoc ev) {
1789            final Iterator<?> panels = data.getIterator(WizardDescriptor.this);
1790            if (wizardPanel != null) {
1791                wizardPanel.setErrorMessage(" ", null); //NOI18N
1792
}
1793
1794            Object JavaDoc src = ev.getSource();
1795            err.log (Level.FINE, "actionPerformed entry. Source: " + src); // NOI18N
1796
if (src == nextButton) {
1797                final Dimension JavaDoc previousSize = panels.current().getComponent().getSize();
1798                Runnable JavaDoc onValidPerformer = new Runnable JavaDoc() {
1799
1800                    public void run() {
1801                        err.log(Level.FINE,
1802                                "onValidPerformer on next button entry.");
1803                        panels.nextPanel();
1804                        try {
1805                            // change UI to show next step, show wait cursor during
1806
// the change
1807
goToNextStep(previousSize);
1808                        }
1809                        catch (IllegalStateException JavaDoc ise) {
1810                            panels.previousPanel();
1811                            String JavaDoc msg = ise.getMessage();
1812                            if (msg != null) {
1813                                // this is only for backward compatitility
1814
DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(msg));
1815                            } else {
1816                                // this should be used (it checks for exception
1817
// annotations and severity)
1818
Exceptions.printStackTrace(ise);
1819                            }
1820                            updateState();
1821                        }
1822                        err.log(Level.FINE,
1823                                "onValidPerformer on next button exit.");
1824                    }
1825                };
1826                lazyValidate(panels.current(), onValidPerformer);
1827            }
1828
1829            if (ev.getSource() == previousButton) {
1830                panels.previousPanel();
1831
1832                // show wait cursor when updating previous button
1833
updateStateWithFeedback();
1834            }
1835
1836            if (ev.getSource() == finishButton) {
1837                Runnable JavaDoc onValidPerformer = new Runnable JavaDoc() {
1838                    public void run() {
1839                        err.log (Level.FINE, "onValidPerformer on finish button entry."); // NOI18N
1840

1841                        // disable all buttons to indicate that instantiate runs
1842
previousButton.setEnabled (false);
1843                        nextButton.setEnabled (false);
1844                        finishButton.setEnabled (false);
1845                        cancelButton.setEnabled (false);
1846                        
1847                        Runnable JavaDoc performFinish = new Runnable JavaDoc () {
1848                            public void run () {
1849                                err.log (Level.FINE, "performFinish entry."); // NOI18N
1850
Object JavaDoc oldValue = getValue();
1851                                    
1852                                // do instantiate
1853
try {
1854                                    callInstantiate();
1855                                    setValueWithoutPCH(OK_OPTION);
1856                                    resetWizard();
1857                                } catch (IOException JavaDoc ioe) {
1858                                    // notify to log
1859
err.log(Level.FINE, null, ioe);
1860
1861                                    setValueWithoutPCH(NEXT_OPTION);
1862                                    updateStateWithFeedback();
1863
1864                                    // notify user by the wizard's status line
1865
putProperty(PROP_ERROR_MESSAGE, ioe.getLocalizedMessage());
1866
1867                                    // if validation failed => cannot move to next panel
1868
return;
1869                                } catch (RuntimeException JavaDoc x) {
1870                                    // notify to log
1871
err.log(Level.FINE, null, x);
1872
1873                                    setValueWithoutPCH(NEXT_OPTION);
1874                                    updateStateWithFeedback();
1875
1876                                    // notify user by the wizard's status line
1877
putProperty(PROP_ERROR_MESSAGE, x.getLocalizedMessage());
1878
1879                                    // if validation failed => cannot move to next panel
1880
return;
1881                                }
1882                                firePropertyChange(PROP_VALUE, oldValue, OK_OPTION);
1883                                
1884                                SwingUtilities.invokeLater (new Runnable JavaDoc () {
1885                                    public void run () {
1886                                        // all is OK
1887
// close wizrad
1888
err.log (Level.FINE, "WD.finishOption.fireActionPerformed()");
1889                                        finishOption.fireActionPerformed();
1890                                        err.log (Level.FINE, "Set value to OK_OPTION.");
1891                                        setValue (OK_OPTION);
1892                                    }
1893                                });
1894                                err.log (Level.FINE, "performFinish exit."); // NOI18N
1895
}
1896                        };
1897                        
1898                        if (panels instanceof AsynchronousInstantiatingIterator) {
1899                            err.log (Level.FINE, "Do ASYNCHRONOUS_JOBS_RP.post(performFinish)."); // NOI18N
1900
ASYNCHRONOUS_JOBS_RP.post (performFinish);
1901                        } else {
1902                            err.log (Level.FINE, "Run performFinish."); // NOI18N
1903
performFinish.run ();
1904                        }
1905                        
1906                        err.log (Level.FINE, "onValidPerformer on finish button exit."); // NOI18N
1907

1908                    }
1909                };
1910                lazyValidate(panels.current(), onValidPerformer);
1911            }
1912
1913            if (ev.getSource() == cancelButton) {
1914                if (backgroundValidationTask != null) {
1915                    backgroundValidationTask.cancel();
1916                }
1917                Object JavaDoc oldValue = getValue();
1918                setValueWithoutPCH(CANCEL_OPTION);
1919
1920                if (Arrays.asList(getClosingOptions()).contains(cancelButton)) {
1921                    try {
1922                        resetWizard();
1923                    } catch (RuntimeException JavaDoc x) {
1924                        // notify to log
1925
err.log(Level.FINE, null, x);
1926                    }
1927
1928                }
1929
1930                firePropertyChange(PROP_VALUE, oldValue, CANCEL_OPTION);
1931            }
1932        }
1933    }
1934
1935    /** Listenes on a users client property changes
1936     */

1937    private class PropL implements PropertyChangeListener JavaDoc {
1938        PropL() {
1939        }
1940
1941        /** Accepts client property changes of user component */
1942        public void propertyChange(PropertyChangeEvent JavaDoc e) {
1943            if (wizardPanel == null) {
1944                return;
1945            }
1946
1947            String JavaDoc propName = e.getPropertyName();
1948            setPanelProperties((JComponent JavaDoc) wizardPanel.getRightComponent());
1949
1950            if (PROP_CONTENT_DATA.equals(propName)) {
1951                wizardPanel.setContent(contentData);
1952                updateButtonAccessibleDescription();
1953            } else if (PROP_CONTENT_SELECTED_INDEX.equals(propName)) {
1954                wizardPanel.setSelectedIndex(contentSelectedIndex);
1955                updateButtonAccessibleDescription();
1956            } else if (PROP_CONTENT_BACK_COLOR.equals(propName)) {
1957                wizardPanel.setContentBackColor(contentBackColor);
1958            } else if (PROP_CONTENT_FOREGROUND_COLOR.equals(propName)) {
1959                wizardPanel.setContentForegroundColor(contentForegroundColor);
1960            } else if (PROP_IMAGE.equals(propName)) {
1961                wizardPanel.setImage(image);
1962            } else if (PROP_IMAGE_ALIGNMENT.equals(propName)) {
1963                wizardPanel.setImageAlignment(imageAlignment);
1964            } else if (PROP_HELP_URL.equals(propName)) {
1965                wizardPanel.setHelpURL(helpURL);
1966            }
1967        }
1968    }
1969
1970    // end of calling to InstantiatingIterator
1971

1972    /** Panel which paints image as its background.
1973     */

1974    private static class ImagedPanel extends JComponent JavaDoc implements Accessible JavaDoc, Runnable JavaDoc {
1975        /** background image */
1976        Image JavaDoc image;
1977
1978        /** helper variables for passing image between threads and painting
1979         * methods */

1980        Image JavaDoc tempImage;
1981
1982        /** helper variables for passing image between threads and painting
1983         * methods */

1984        Image JavaDoc image2Load;
1985
1986        /** true if default image is used */
1987        boolean isDefault = false;
1988
1989        /** true if loading of image is in progress, false otherwise */
1990        boolean loadPending = false;
1991        boolean north = true;
1992
1993        /** sync lock for image variables access */
1994        private final Object JavaDoc IMAGE_LOCK = new Object JavaDoc();
1995
1996        /** Constrcuts panel with given image on background.
1997         * @param im background image, null means default image
1998         */

1999        public ImagedPanel(Image JavaDoc im) {
2000            setImage(im);
2001            setLayout(new BorderLayout JavaDoc());
2002            setOpaque(true);
2003        }
2004
2005        /** Overriden to paint backround image */
2006        protected void paintComponent(Graphics JavaDoc graphics) {
2007            graphics.setColor(getBackground());
2008            graphics.fillRect(0, 0, getWidth(), getHeight());
2009
2010            if (image != null) {
2011                graphics.drawImage(image, 0, north ? 0 : (getHeight() - image.getHeight(null)), this);
2012            } else if (image2Load != null) {
2013                loadImageInBackground(image2Load);
2014                image2Load = null;
2015            }
2016        }
2017
2018        public void setImageAlignment(String JavaDoc align) {
2019            north = "North".equals(align); // NOI18N
2020
}
2021
2022        /** Sets background image for this component. Image will be loaded
2023         * asynchronously if not loaded yet. Null means default image.
2024         */

2025        public void setImage(Image JavaDoc im) {
2026            if (im != null) {
2027                loadImage(im);
2028                isDefault = false;
2029
2030                return;
2031            }
2032
2033            if (!isDefault) {
2034                loadImage(getDefaultImage());
2035                isDefault = true;
2036            }
2037        }
2038
2039        private void loadImage(Image JavaDoc im) {
2040            // check image and just set variable if fully loaded already
2041
MediaTracker JavaDoc mt = new MediaTracker JavaDoc(this);
2042            mt.addImage(im, 0);
2043
2044            if (mt.checkID(0)) {
2045                image = im;
2046
2047                if (isShowing()) {
2048                    repaint();
2049                }
2050
2051                return;
2052            }
2053
2054            // start loading in background or just mark that loading should
2055
// start when paint is invoked
2056
if (isShowing()) {
2057                loadImageInBackground(im);
2058            } else {
2059                synchronized (IMAGE_LOCK) {
2060                    image = null;
2061                }
2062
2063                image2Load = im;
2064            }
2065        }
2066
2067        private void loadImageInBackground(Image JavaDoc image) {
2068            synchronized (IMAGE_LOCK) {
2069                tempImage = image;
2070
2071                // coalesce with previous task if hasn't really started yet
2072
if (loadPending) {
2073                    return;
2074                }
2075
2076                loadPending = true;
2077            }
2078
2079            // 30ms is safety time to ensure code will run asynchronously
2080
RequestProcessor.getDefault().post(this, 30);
2081        }
2082
2083        /** Loads image stored in image2Load variable.
2084         * Then invokes repaint when image is fully loaded.
2085         */

2086        public void run() {
2087            Image JavaDoc localImage;
2088
2089            // grab value
2090
synchronized (IMAGE_LOCK) {
2091                localImage = tempImage;
2092                tempImage = null;
2093                loadPending = false;
2094            }
2095
2096            // actually loads image
2097
ImageIcon JavaDoc localImageIcon = new ImageIcon JavaDoc(localImage);
2098            boolean shouldRepaint = false;
2099
2100            synchronized (IMAGE_LOCK) {
2101                // don't commit results if another loading was started after us
2102
if (!loadPending) {
2103                    image = localImageIcon.getImage();
2104
2105                    // keep repaint call out of sync section
2106
shouldRepaint = true;
2107                }
2108            }
2109
2110            if (shouldRepaint) {
2111                repaint();
2112            }
2113        }
2114    }
2115
2116    /** Text list cell renderer. Wraps text of items at specified width. Allows numbering
2117     * of items.
2118     */

2119    private static class WrappedCellRenderer extends JPanel JavaDoc implements ListCellRenderer JavaDoc {
2120        JTextArea JavaDoc ta = new JTextArea JavaDoc();
2121        JLabel JavaDoc numberLabel;
2122        int selected = -1;
2123        boolean contentNumbered;
2124        int taWidth;
2125
2126        /**
2127         * @param contentNumbered Whether content will be numbered
2128         * @param wrappingWidth Width of list item.
2129         */

2130        private WrappedCellRenderer(boolean contentNumbered, int wrappingWidth) {
2131            super(new BorderLayout JavaDoc());
2132            this.contentNumbered = contentNumbered;
2133
2134            ta.setOpaque(false);
2135            ta.setEditable(false);
2136            ta.setLineWrap(true);
2137            ta.setWrapStyleWord(true);
2138            ta.setFont(UIManager.getFont("Label.font")); // NOI18N
2139
ta.getAccessibleContext().setAccessibleDescription(""); // NOI18N
2140

2141            taWidth = wrappingWidth - 12 - 12;
2142
2143            numberLabel = new JLabel JavaDoc() {
2144                        protected void paintComponent(Graphics JavaDoc g) {
2145                            super.paintComponent(g);
2146
2147                            // #9804. Draw bullet if the content is not numbered.
2148
if (!WrappedCellRenderer.this.contentNumbered) {
2149                                java.awt.Rectangle JavaDoc rect = g.getClipBounds();
2150                                g.fillOval(rect.x, rect.y, 7, 7);
2151                            }
2152                        }
2153                    };
2154            numberLabel.setLabelFor(ta); // a11y
2155
numberLabel.setHorizontalAlignment(SwingConstants.LEFT);
2156            numberLabel.setFont(ta.getFont());
2157            numberLabel.setOpaque(false);
2158            numberLabel.setPreferredSize(new Dimension JavaDoc(25, 0));
2159            add(numberLabel, BorderLayout.WEST);
2160            taWidth -= 25;
2161
2162            Insets JavaDoc taInsets = ta.getInsets();
2163            ta.setSize(taWidth, taInsets.top + taInsets.bottom + 1);
2164
2165            add(ta, BorderLayout.CENTER);
2166            setBorder(BorderFactory.createEmptyBorder(0, 12, 0, 12));
2167            setOpaque(false);
2168        }
2169
2170        public Component JavaDoc getListCellRendererComponent(
2171            JList JavaDoc list, Object JavaDoc value, int index, boolean isSelected, boolean cellHasFocus
2172        ) {
2173            if (index == selected) {
2174                numberLabel.setFont(doDeriveFont(numberLabel.getFont(), Font.BOLD));
2175                ta.setFont(doDeriveFont(ta.getFont(), Font.BOLD));
2176            } else {
2177                numberLabel.setFont(doDeriveFont(numberLabel.getFont(), Font.PLAIN));
2178                ta.setFont(doDeriveFont(ta.getFont(), Font.PLAIN));
2179            }
2180
2181            if (contentNumbered) {
2182                numberLabel.setText(Integer.toString(index + 1) + "."); // NOI18N
2183
}
2184
2185            // #21322: on JDK1.4 wrapping width is cleared between two rendering runs
2186
Insets JavaDoc taInsets = ta.getInsets();
2187            ta.setSize(taWidth, taInsets.top + taInsets.bottom + 1);
2188            ta.setText((String JavaDoc) value);
2189
2190            return this;
2191        }
2192
2193        private void setSelectedIndex(int i) {
2194            selected = i;
2195        }
2196
2197        private void setForegroundColor(Color JavaDoc color) {
2198            if (numberLabel != null) {
2199                numberLabel.setForeground(color);
2200                numberLabel.setBackground(color);
2201            }
2202
2203            ta.setForeground(color);
2204        }
2205    }
2206
2207    /** Wizard panel. Allows auto layout of content, wizard panel name and input panel.
2208     */

2209    private static class WizardPanel extends JPanel JavaDoc {
2210        /** Users panel is inserted into this panel. */
2211        private JPanel JavaDoc rightPanel = new JPanel JavaDoc(new BorderLayout JavaDoc());
2212
2213        /** Name of the users panel. */
2214        private JLabel JavaDoc panelName = new JLabel JavaDoc("Step"); //NOI18N
2215

2216        /** List of content. */
2217        private JList JavaDoc contentList;
2218
2219        /** Users component. Should be held for removing from rightPanel */
2220        private Component JavaDoc rightComponent;
2221
2222        /** Panel which paints image */
2223        private ImagedPanel contentPanel;
2224
2225        /** Name of content. Can be switched off. */
2226        private JPanel JavaDoc contentLabelPanel;
2227
2228        /** Wrapped list cell renderer */
2229        private WrappedCellRenderer cellRenderer;
2230
2231        /** Tabbed pane is used only when both content and help are displayed */
2232        private JTabbedPane JavaDoc tabbedPane;
2233
2234        /** HTML Browser is used only when help is displayed in the left pane */
2235        private HtmlBrowser htmlBrowser;
2236
2237        /** Each wizard panel have to be larger or same as this */
2238        private Dimension JavaDoc cachedDimension;
2239
2240        /** Label of steps pane */
2241        private JLabel JavaDoc label;
2242        
2243        private JPanel JavaDoc progressBarPanel;
2244
2245        /** Selected index of content */
2246        private int selectedIndex;
2247        private javax.swing.JLabel JavaDoc m_lblMessage;
2248        private Color JavaDoc nbErrorForeground;
2249        private Color JavaDoc nbWarningForeground;
2250
2251        /** Creates new <CODE>WizardPanel<CODE>.
2252         * @param contentDisplayed whether content will be displayed in the left pane
2253         * @param helpDisplayed whether help will be displayed in the left pane
2254         * @param contentNumbered whether content will be numbered
2255         * @param leftDimension dimension of content or help pane
2256         */

2257        public WizardPanel(
2258            boolean contentDisplayed, boolean helpDispalyed, boolean contentNumbered, Dimension JavaDoc leftDimension
2259        ) {
2260            super(new BorderLayout JavaDoc());
2261            initComponents(contentDisplayed, helpDispalyed, contentNumbered, leftDimension);
2262            setOpaque(false);
2263            resetPreferredSize();
2264        }
2265
2266        private void initComponents(
2267            boolean contentDisplayed, boolean helpDisplayed, boolean contentNumbered, Dimension JavaDoc leftDimension
2268        ) {
2269            if (contentDisplayed) {
2270                createContentPanel(contentNumbered, leftDimension);
2271
2272                if (!helpDisplayed) {
2273                    add(contentPanel, BorderLayout.WEST);
2274                }
2275            }
2276
2277            if (helpDisplayed) {
2278                htmlBrowser = new BoundedHtmlBrowser(leftDimension);
2279                htmlBrowser.setPreferredSize(leftDimension);
2280
2281                if (!contentDisplayed) {
2282                    add(htmlBrowser, BorderLayout.WEST);
2283                }
2284            }
2285
2286            if (helpDisplayed && contentDisplayed) {
2287                tabbedPane = new JTabbedPane JavaDoc(JTabbedPane.BOTTOM);
2288                tabbedPane.addTab(NbBundle.getMessage(WizardDescriptor.class, "CTL_ContentName"), contentPanel);
2289                tabbedPane.addTab(NbBundle.getMessage(WizardDescriptor.class, "CTL_HelpName"), htmlBrowser);
2290                tabbedPane.setEnabledAt(1, false);
2291                tabbedPane.setOpaque(false);
2292
2293                // tabbedPane.setPreferredSize(leftDimension);
2294
add(tabbedPane, BorderLayout.WEST);
2295            }
2296
2297            panelName.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, panelName.getForeground()));
2298            panelName.setFont(doDeriveFont(panelName.getFont(), Font.BOLD));
2299
2300            JPanel JavaDoc labelPanel = new JPanel JavaDoc(new BorderLayout JavaDoc());
2301            labelPanel.add(panelName, BorderLayout.NORTH);
2302            labelPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 11));
2303            rightPanel.setBorder(BorderFactory.createEmptyBorder(0, 12, 11, 11));
2304            panelName.setLabelFor(labelPanel);
2305
2306            nbErrorForeground = UIManager.getColor("nb.errorForeground"); //NOI18N
2307
if (nbErrorForeground == null) {
2308                //nbErrorForeground = new Color(89, 79, 191); // RGB suggested by Bruce in #28466
2309
nbErrorForeground = new Color JavaDoc(255, 0, 0); // RGB suggested by jdinga in #65358
2310
}
2311            
2312            nbWarningForeground = UIManager.getColor("nb.warningForeground"); //NOI18N
2313
if (nbWarningForeground == null) {
2314                nbWarningForeground = new Color JavaDoc(51, 51, 51); // Label.foreground
2315
}
2316            
2317            JPanel JavaDoc errorPanel = new JPanel JavaDoc(new BorderLayout JavaDoc());
2318            errorPanel.setBorder(BorderFactory.createEmptyBorder(0, 12, 12, 11));
2319            m_lblMessage = new FixedHeightLabel ();
2320            m_lblMessage.setForeground (nbErrorForeground);
2321            errorPanel.add(m_lblMessage, BorderLayout.CENTER);
2322            
2323            progressBarPanel = new JPanel JavaDoc (new BorderLayout JavaDoc ());
2324            progressBarPanel.setVisible (false);
2325            
2326            if (contentDisplayed) {
2327                // place for visualize progress bar in content panel (if contentDisplayed)
2328
progressBarPanel.setOpaque (false);
2329                progressBarPanel.setBorder (BorderFactory.createEmptyBorder (0, 4, 7, 4));
2330                contentPanel.add (progressBarPanel, BorderLayout.SOUTH);
2331            } else {
2332                // placeholder for progress bar components in WizardPanel (if no contentDisplayed set)
2333
progressBarPanel.add (new JLabel JavaDoc (), BorderLayout.NORTH);
2334                JProgressBar JavaDoc pb = new JProgressBar JavaDoc ();
2335                pb.setOrientation (JProgressBar.HORIZONTAL);
2336                pb.setAlignmentX(0.5f);
2337                pb.setAlignmentY(0.5f);
2338                pb.setString ("0"); // NOI18N
2339
progressBarPanel.add (pb, BorderLayout.CENTER);
2340
2341                progressBarPanel.setBorder (BorderFactory.createEmptyBorder (4, 0, 0, 0));
2342                errorPanel.add (progressBarPanel, BorderLayout.SOUTH);
2343            }
2344
2345            JPanel JavaDoc fullRightPanel = new JPanel JavaDoc(new BorderLayout JavaDoc());
2346            fullRightPanel.add(labelPanel, BorderLayout.NORTH);
2347            fullRightPanel.add(rightPanel, BorderLayout.CENTER);
2348            fullRightPanel.add(errorPanel, BorderLayout.SOUTH);
2349
2350            // #65506: the wizard panel should fit into window w/o scrollbar
2351
add(fullRightPanel, BorderLayout.CENTER);
2352
2353            if (getBorder() == null) {
2354                // Look & Feel has not set the border already
2355
JSeparator JavaDoc sep = new JSeparator JavaDoc();
2356                sep.setForeground(Color.darkGray);
2357                add(sep, BorderLayout.SOUTH);
2358            }
2359        }
2360
2361        public void setErrorMessage(String JavaDoc msg, Boolean JavaDoc canContinue) {
2362            m_lblMessage.setForeground(nbErrorForeground);
2363            if (msg != null && msg.trim ().length () > 0 && canContinue != null) {
2364                if (canContinue.booleanValue ()) {
2365                    m_lblMessage.setIcon (new ImageIcon JavaDoc (Utilities.loadImage ("org/netbeans/modules/dialogs/warning.gif"))); // NOI18N
2366
m_lblMessage.setForeground (nbWarningForeground);
2367                } else {
2368                    m_lblMessage.setIcon (new ImageIcon JavaDoc (Utilities.loadImage ("org/netbeans/modules/dialogs/error.gif"))); // NOI18N
2369
}
2370                m_lblMessage.setToolTipText (msg);
2371            } else {
2372                m_lblMessage.setIcon (null);
2373                m_lblMessage.setToolTipText (null);
2374            }
2375            
2376            m_lblMessage.setText(msg);
2377        }
2378        
2379        private void setProgressComponent (JComponent JavaDoc progressComp, JLabel JavaDoc progressLabel) {
2380            if (progressLabel != null) {
2381                progressLabel.setText (PROGRESS_BAR_DISPLAY_NAME);
2382                progressBarPanel.add (progressLabel, BorderLayout.NORTH);
2383            }
2384            progressBarPanel.add (progressComp, BorderLayout.CENTER);
2385            progressBarPanel.setVisible (true);
2386        }
2387
2388        /** Creates content panel.
2389         * @param contentNumbered <CODE>boolean</CODE> whether content will be numbered
2390         * @param leftDimension <CODE>Dimension</CODE> dimension of content pane
2391         */

2392        private void createContentPanel(boolean contentNumbered, Dimension JavaDoc leftDimension) {
2393            contentList = new JList JavaDoc();
2394            cellRenderer = new WrappedCellRenderer(contentNumbered, leftDimension.width);
2395            cellRenderer.setOpaque(false);
2396            contentList.setCellRenderer(cellRenderer);
2397            contentList.setOpaque(false);
2398            contentList.setEnabled(false);
2399            contentList.getAccessibleContext().setAccessibleDescription(""); // NOI18N
2400

2401            JScrollPane JavaDoc scroll = new JScrollPane JavaDoc(contentList);
2402            scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
2403            scroll.getViewport().setOpaque(false);
2404            scroll.setBorder(null);
2405            scroll.setOpaque(false);
2406            // #89392: remove GTK's viewport border
2407
scroll.setViewportBorder(null);
2408
2409            label = new JLabel JavaDoc(NbBundle.getMessage(WizardDescriptor.class, "CTL_ContentName"));
2410            label.setForeground(Color.white);
2411            label.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, label.getForeground()));
2412            label.setFont(doDeriveFont(label.getFont(), Font.BOLD));
2413            contentLabelPanel = new JPanel JavaDoc(new BorderLayout JavaDoc());
2414            contentLabelPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 11, 11));
2415            contentLabelPanel.setOpaque(false);
2416            contentLabelPanel.add(label, BorderLayout.NORTH);
2417
2418            contentPanel = new ImagedPanel(null);
2419            contentPanel.add(contentLabelPanel, BorderLayout.NORTH);
2420            contentPanel.add(scroll, BorderLayout.CENTER);
2421
2422            contentPanel.setPreferredSize(leftDimension);
2423            label.setLabelFor(contentList);
2424        }
2425
2426        /** Setter for lists items.
2427         * @param content Array of list items.
2428         */

2429        public void setContent(final String JavaDoc[] content) {
2430            final JList JavaDoc list = contentList;
2431
2432            if (list == null) {
2433                return;
2434            }
2435
2436            // #18055: Ensure it runs in AWT thread.
2437
// Remove this when component handling will be assured
2438
// by other means that runs always in AWT.
2439
Mutex.EVENT.writeAccess(
2440                new Runnable JavaDoc() {
2441                    public void run() {
2442                        list.setListData(content);
2443                        list.revalidate();
2444                        list.repaint();
2445                        contentLabelPanel.setVisible(content.length > 0);
2446                    }
2447                }
2448            );
2449        }
2450
2451        /** Setter for selected list item.
2452         * @param index Index of selected item in the list.
2453         */

2454        public void setSelectedIndex(final int index) {
2455            selectedIndex = index;
2456
2457            if (cellRenderer != null) {
2458                cellRenderer.setSelectedIndex(index);
2459
2460                final JList JavaDoc list = contentList;
2461
2462                if (list == null) {
2463                    return;
2464                }
2465
2466                // #18055. See previous #18055 comment.
2467
Mutex.EVENT.readAccess(
2468                    new Runnable JavaDoc() {
2469                        public void run() {
2470                            list.ensureIndexIsVisible(index);
2471
2472                            // Fix of #10787.
2473
// This is workaround for swing bug - BasicListUI doesn't ask for preferred
2474
// size of rendered list cell as a result of property selectedIndex change.
2475
// It does only on certain JList property changes (e.g. fixedCellWidth).
2476
// Maybe subclassing BasicListUI could be better fix.
2477
list.setFixedCellWidth(0);
2478                            list.setFixedCellWidth(-1);
2479                        }
2480                    }
2481                );
2482            }
2483        }
2484
2485        /** Setter for content background color.
2486         * @param color content background color.
2487         */

2488        public void setContentBackColor(Color JavaDoc color) {
2489            if (contentPanel != null) {
2490                contentPanel.setBackground(color);
2491            }
2492        }
2493
2494        /** Setter for content foreground color.
2495         * @param color content foreground color.
2496         */

2497        public void setContentForegroundColor(Color JavaDoc color) {
2498            if (cellRenderer == null) {
2499                return;
2500            }
2501
2502            cellRenderer.setForegroundColor(color);
2503            label.setForeground(color);
2504            label.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, label.getForeground()));
2505        }
2506
2507        /** Setter for content background image.
2508         * @param image content background image
2509         */

2510        public void setImage(Image JavaDoc image) {
2511            if (contentPanel != null) {
2512                contentPanel.setImage(image);
2513            }
2514        }
2515
2516        /** Setter for image alignment.
2517         * @param align image alignment - 'North', 'South'
2518         */

2519        public void setImageAlignment(String JavaDoc align) {
2520            if (contentPanel != null) {
2521                contentPanel.setImageAlignment(align);
2522            }
2523        }
2524
2525        /** Setter for user's component.
2526         * @param c user's component
2527         */

2528        public void setRightComponent(Component JavaDoc c) {
2529            if (rightComponent != null) {
2530                rightPanel.remove(rightComponent);
2531            }
2532
2533            rightComponent = c;
2534            rightPanel.add(rightComponent, BorderLayout.CENTER);
2535
2536            // validate();
2537
}
2538
2539        /** Getter for user's component.
2540         * @return <CODE>Component</CODE> user's component
2541         */

2542        public Component JavaDoc getRightComponent() {
2543            return rightComponent;
2544        }
2545
2546        /** Setter for wizard panel name.
2547         * @param name panel name
2548         */

2549        public void setPanelName(String JavaDoc name) {
2550            panelName.setText(name);
2551        }
2552
2553        /** Setter for help URL.
2554         * @param helpURL help URL
2555         */

2556        public void setHelpURL(URL JavaDoc helpURL) {
2557            if (htmlBrowser == null) {
2558                return;
2559            }
2560
2561            if (helpURL != null) {
2562                if (!helpURL.equals(htmlBrowser.getDocumentURL())) {
2563                    htmlBrowser.setURL(helpURL);
2564                }
2565
2566                if (tabbedPane != null) {
2567                    tabbedPane.setEnabledAt(tabbedPane.indexOfComponent(htmlBrowser), true);
2568                }
2569            } else if (tabbedPane != null) {
2570                tabbedPane.setSelectedComponent(contentPanel);
2571                tabbedPane.setEnabledAt(tabbedPane.indexOfComponent(htmlBrowser), false);
2572            }
2573        }
2574
2575        public void resetPreferredSize() {
2576            cachedDimension = new Dimension JavaDoc(600, 365);
2577        }
2578
2579        public Dimension JavaDoc getPreferredSize() {
2580            Dimension JavaDoc dim = super.getPreferredSize();
2581
2582            if (dim.height > cachedDimension.height) {
2583                cachedDimension.height = dim.height;
2584            }
2585
2586            if (dim.width > cachedDimension.width) {
2587                cachedDimension.width = dim.width;
2588            }
2589
2590            return cachedDimension;
2591        }
2592
2593        /** Overriden to delegate call to user component.
2594         */

2595        public void requestFocus() {
2596            if ((rightComponent != null) && rightComponent.isDisplayable()) {
2597                JComponent JavaDoc comp = (JComponent JavaDoc) rightComponent;
2598                Container JavaDoc rootAnc = comp.getFocusCycleRootAncestor();
2599                FocusTraversalPolicy JavaDoc policy = rootAnc.getFocusTraversalPolicy();
2600                Component JavaDoc focus = policy.getComponentAfter(rootAnc, comp);
2601
2602                if (focus != null) {
2603                    focus.requestFocus();
2604                } else {
2605                    comp.requestFocus();
2606                }
2607            } else {
2608                super.requestFocus();
2609            }
2610        }
2611
2612        /** Overriden to delegate call to user component.
2613         */

2614        @Deprecated JavaDoc
2615        public boolean requestDefaultFocus() {
2616            if (rightComponent instanceof JComponent JavaDoc) {
2617                return ((JComponent JavaDoc) rightComponent).requestDefaultFocus();
2618            }
2619
2620            return super.requestDefaultFocus();
2621        }
2622
2623        public javax.accessibility.AccessibleContext JavaDoc getAccessibleContext() {
2624            if (accessibleContext == null) {
2625                accessibleContext = new AccessibleWizardPanel();
2626            }
2627
2628            return accessibleContext;
2629        }
2630
2631        private class AccessibleWizardPanel extends AccessibleJPanel {
2632            AccessibleWizardPanel() {
2633            }
2634
2635            public String JavaDoc getAccessibleDescription() {
2636                if (accessibleDescription != null) {
2637                    return accessibleDescription;
2638                }
2639
2640                if (rightComponent instanceof Accessible JavaDoc) {
2641                    if (rightComponent.getAccessibleContext().getAccessibleDescription() == null) {
2642                        return null;
2643                    }
2644
2645                    return NbBundle.getMessage(
2646                        WizardDescriptor.class, "ACSD_WizardPanel", new Integer JavaDoc(selectedIndex + 1), panelName.getText(),
2647                        rightComponent.getAccessibleContext().getAccessibleDescription()
2648                    );
2649                }
2650
2651                return super.getAccessibleDescription();
2652            }
2653        }
2654    }
2655
2656    /** Overriden to return wished preferred size */
2657    private static class BoundedHtmlBrowser extends HtmlBrowser {
2658        Dimension JavaDoc dim;
2659
2660        public BoundedHtmlBrowser(Dimension JavaDoc d) {
2661            super(false, false);
2662            dim = d;
2663        }
2664
2665        public Dimension JavaDoc getPreferredSize() {
2666            return dim;
2667        }
2668    }
2669
2670    // helper, make possible close wizard as finish
2671
static class FinishAction extends Object JavaDoc {
2672        ActionListener JavaDoc listner;
2673
2674        public void addActionListener(ActionListener JavaDoc ac) {
2675            listner = ac;
2676        }
2677
2678        public void removeActionListener(ActionListener JavaDoc ac) {
2679            listner = null;
2680        }
2681
2682        public void fireActionPerformed() {
2683            if (listner != null) {
2684                listner.actionPerformed(new ActionEvent JavaDoc(this, 0, ""));
2685            }
2686        }
2687    }
2688    
2689    private static final class FixedHeightLabel extends JLabel JavaDoc {
2690        
2691        private static final int ESTIMATED_HEIGHT = 16;
2692
2693        public FixedHeightLabel () {
2694            super ();
2695        }
2696        
2697        public Dimension JavaDoc getPreferredSize() {
2698            Dimension JavaDoc preferredSize = super.getPreferredSize();
2699            assert ESTIMATED_HEIGHT == Utilities.loadImage ("org/netbeans/modules/dialogs/warning.gif").getHeight (null) : "Use only 16px icon.";
2700            preferredSize.height = Math.max (ESTIMATED_HEIGHT, preferredSize.height);
2701            return preferredSize;
2702        }
2703    }
2704    
2705    private static final class SettingsAndIterator<Data> {
2706        private final Iterator<Data> panels;
2707        private final Data settings;
2708        private final boolean useThis;
2709        /** current panel */
2710        private Panel JavaDoc<Data> current;
2711
2712        
2713        public SettingsAndIterator(Iterator<Data> iterator, Data settings) {
2714            this(iterator, settings, false);
2715        }
2716        public SettingsAndIterator(Iterator<Data> iterator, Data settings, boolean useThis) {
2717            this.panels = iterator;
2718            this.settings = settings;
2719            this.useThis = useThis;
2720        }
2721        public static SettingsAndIterator<WizardDescriptor> create(Iterator<WizardDescriptor> iterator) {
2722            return new SettingsAndIterator<WizardDescriptor>(iterator, null, true);
2723        }
2724
2725        public Iterator<Data> getIterator(WizardDescriptor caller) {
2726            return panels;
2727        }
2728        
2729        @SuppressWarnings JavaDoc("unchecked")
2730        public Data getSettings(WizardDescriptor caller) {
2731            return useThis ? (Data)caller : settings;
2732        }
2733        
2734        public SettingsAndIterator<Data> clone(Iterator<Data> it) {
2735            SettingsAndIterator<Data> s = new SettingsAndIterator<Data>(it, settings, useThis);
2736            return s;
2737        }
2738    }
2739}
2740
Popular Tags