KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > junit > wizards > SimpleTestStepLocation


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 2004-2007 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.junit.wizards;
21
22 import java.awt.BorderLayout JavaDoc;
23 import java.awt.Component JavaDoc;
24 import java.awt.Container JavaDoc;
25 import java.awt.GridBagConstraints JavaDoc;
26 import java.awt.GridBagLayout JavaDoc;
27 import java.awt.GridLayout JavaDoc;
28 import java.awt.Insets JavaDoc;
29 import java.awt.Point JavaDoc;
30 import java.awt.event.ActionEvent JavaDoc;
31 import java.awt.event.ActionListener JavaDoc;
32 import java.awt.event.FocusEvent JavaDoc;
33 import java.awt.event.FocusListener JavaDoc;
34 import java.awt.event.HierarchyEvent JavaDoc;
35 import java.awt.event.HierarchyListener JavaDoc;
36 import java.awt.event.ItemEvent JavaDoc;
37 import java.awt.event.ItemListener JavaDoc;
38 import java.awt.event.MouseEvent JavaDoc;
39 import java.io.File JavaDoc;
40 import java.util.ArrayList JavaDoc;
41 import java.util.Arrays JavaDoc;
42 import java.util.Collection JavaDoc;
43 import java.util.Iterator JavaDoc;
44 import java.util.List JavaDoc;
45 import java.util.Map JavaDoc;
46 import java.util.ResourceBundle JavaDoc;
47 import java.util.Set JavaDoc;
48 import javax.swing.AbstractAction JavaDoc;
49 import javax.swing.AbstractButton JavaDoc;
50 import javax.swing.Action JavaDoc;
51 import javax.swing.ActionMap JavaDoc;
52 import javax.swing.BorderFactory JavaDoc;
53 import javax.swing.Box JavaDoc;
54 import javax.swing.BoxLayout JavaDoc;
55 import javax.swing.DefaultComboBoxModel JavaDoc;
56 import javax.swing.JButton JavaDoc;
57 import javax.swing.JCheckBox JavaDoc;
58 import javax.swing.JComboBox 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.JRootPane JavaDoc;
64 import javax.swing.JSeparator JavaDoc;
65 import javax.swing.JTextField JavaDoc;
66 import javax.swing.ListSelectionModel JavaDoc;
67 import javax.swing.SwingUtilities JavaDoc;
68 import javax.swing.border.BevelBorder JavaDoc;
69 import javax.swing.event.ChangeEvent JavaDoc;
70 import javax.swing.event.ChangeListener JavaDoc;
71 import javax.swing.event.DocumentEvent JavaDoc;
72 import javax.swing.event.DocumentListener JavaDoc;
73 import javax.swing.event.ListSelectionEvent JavaDoc;
74 import javax.swing.event.ListSelectionListener JavaDoc;
75 import javax.swing.event.MouseInputListener JavaDoc;
76 import javax.swing.text.AbstractDocument JavaDoc;
77 import javax.swing.text.AttributeSet JavaDoc;
78 import javax.swing.text.BadLocationException JavaDoc;
79 import javax.swing.text.DocumentFilter JavaDoc;
80 import javax.swing.text.NavigationFilter JavaDoc;
81 import javax.swing.text.Position JavaDoc;
82 import org.netbeans.api.java.classpath.ClassPath;
83 import org.netbeans.api.project.Project;
84 import org.netbeans.api.project.ProjectUtils;
85 import org.netbeans.api.project.SourceGroup;
86 import org.netbeans.modules.junit.GuiUtils;
87 import org.netbeans.modules.junit.JUnitCfgOfCreate;
88 import org.netbeans.modules.junit.MessageStack;
89 import org.netbeans.modules.junit.NamedObject;
90 import org.netbeans.modules.junit.SizeRestrictedPanel;
91 import org.netbeans.modules.junit.TestCreator;
92 import org.netbeans.spi.java.project.support.ui.PackageView;
93 import org.openide.DialogDescriptor;
94 import org.openide.DialogDisplayer;
95 import org.openide.ErrorManager;
96 import org.openide.NotifyDescriptor;
97 import org.openide.WizardDescriptor;
98 import org.openide.awt.Mnemonics;
99 import org.openide.filesystems.FileObject;
100 import org.openide.filesystems.FileUtil;
101 import org.openide.loaders.DataObject;
102 import org.openide.loaders.TemplateWizard;
103 import org.openide.nodes.AbstractNode;
104 import org.openide.nodes.Children;
105 import org.openide.nodes.FilterNode;
106 import org.openide.nodes.Node;
107 import org.openide.nodes.NodeAcceptor;
108 import org.openide.nodes.NodeOperation;
109 import org.openide.util.HelpCtx;
110 import org.openide.util.NbBundle;
111 import org.openide.util.UserCancelException;
112
113 /**
114  *
115  * @author Marian Petras
116  */

117 public final class SimpleTestStepLocation implements WizardDescriptor.Panel {
118     
119     /**
120      * message layer for displaying messages about problems with checkbox
121      * selection
122      *
123      * @see MessageStack
124      */

125     private static final int MSG_LAYER_CHECKBOXES = 0;
126     /**
127      * message layer for displaying messages about problems with classname
128      *
129      * @see MessageStack
130      */

131     private static final int MSG_LAYER_CLASSNAME = 1;
132     
133     private final String JavaDoc testClassNameSuffix
134             = NbBundle.getMessage(TestCreator.class,
135                                   "PROP_test_classname_suffix"); //NOI18N
136

137     private Component JavaDoc visualComp;
138     private List JavaDoc<ChangeListener JavaDoc> changeListeners;
139     private JTextField JavaDoc tfClassToTest;
140     private JButton JavaDoc btnBrowse;
141     private JTextField JavaDoc tfTestClass;
142     private JTextField JavaDoc tfProjectName;
143     private JComboBox JavaDoc cboxLocation;
144     private JTextField JavaDoc tfCreatedFile;
145     
146     private JCheckBox JavaDoc chkPublic;
147     private JCheckBox JavaDoc chkProtected;
148     private JCheckBox JavaDoc chkPackagePrivate;
149     private JCheckBox JavaDoc chkSetUp;
150     private JCheckBox JavaDoc chkTearDown;
151     private JCheckBox JavaDoc chkMethodBodies;
152     private JCheckBox JavaDoc chkJavadoc;
153     private JCheckBox JavaDoc chkHints;
154
155     /** message stack for displaying error messages */
156     private final MessageStack msgStack = new MessageStack(2);
157     private String JavaDoc msgClassNameInvalid;
158     private String JavaDoc msgClassToTestDoesNotExist;
159     private String JavaDoc msgChkBoxesInvalid;
160
161     
162     /**
163      * project to create a test class in
164      */

165     private Project project;
166     private TemplateWizard wizard;
167     
168
169     // focus change detection mechanism
170

171     /**
172      * true, if the current chosen project have multiple testable SourceGroups.
173      * If it does, class name entered in the Class to Test textfield must be
174      * checked agains all of them (to detect ambiguity) and if there are
175      * multiple classes matching, the user must be forced to choose one
176      * before leaving the textfield.
177      * <p>
178      * The focus change detection mechanism is activated by the
179      * {@link #hierarchyListener} after this wizard panel is added
180      * to the wizard dialog. The listener activates the mechanism
181      * only if the mechanism is
182      * {@linkplain #focusChangeDetectionEnabled enabled}.
183      *
184      * @see #setUp
185      */

186     private boolean multipleSourceRoots;
187     /**
188      * true if the focus change detection mechanism is enabled.
189      * Being it enabled does not mean that it is activated
190      * - it cannot be activated until the visual component is added
191      * to the wizard dialog
192      */

193     private boolean interactionRestrictionsEnabled = false;
194     /**
195      * true if the focus change detection mechanism is active
196      */

197     private boolean interactionRestrictionsActive = false;
198     /** <!-- PENDING --> */
199     private boolean interactionRestrictionsSuspended = false;
200     /** */
201     private boolean mouseClicksBlocked = false;
202     /**
203      * hierarchy listener that detects when the visual component
204      * is added to the wizard dialog. Once it is added to the dialog,
205      * the focus change detection mechanism can be activated.
206      *
207      * @see #focusChangeDetectionEnabled
208      */

209     private HierarchyListener JavaDoc displayabilityListener;
210     /** root pane of the wizard dialog */
211     private JRootPane JavaDoc rootPane;
212     /**
213      * default button of the wizard.
214      * It is actually the default button of the dialog's {@link #rootPane}.
215      */

216     private JButton JavaDoc defaultButton;
217     /**
218      * action key of the root pane's original default action
219      * <!-- PENDING -->
220      */

221     private String JavaDoc rootPaneDefaultActionKey;
222     /**
223      * root pane's original default action
224      * <!-- PENDING -->
225      */

226     private Action JavaDoc rootPaneDefaultAction;
227     /**
228      * mouse listener of the wizard dialog's glass pane.
229      * It is a part of the focus change detection mechanism.
230      */

231     private MouseInputListener JavaDoc glassPaneListener;
232     /**
233      * UI components on which mouse events are checked and evauluated.
234      * The mouse events are checked only if there are
235      * {@link #multipleSourceRoots}.
236      */

237     private Component JavaDoc[] mouseBlocked;
238     /**
239      * UI components on which mnemonic activation is checked and evaluated.
240      * Mnemonic activation events are checked only if there are
241      * {@link #multipleSourceRoots}.
242      */

243     private JComponent JavaDoc[] mnemonicBlocked;
244     /**
245      * information about actions mapped to action keys of UI components
246      * accessible using mnemonics.
247      * This is used for blocking access to those components using
248      * mnemonics and for restoring the UI components' action maps
249      * to the original state.
250      *
251      * @see #blockMnemonics
252      * @see #unblockMnemonics
253      */

254     private ActionMappingInfo[] actionMappingInfo;
255     /**
256      * component that is explicitely allowed to gain focus.
257      * This is used when a button press event is about to be dispatched
258      * to the button, so that the focus listener does not interrupt
259      * focus transfer to the button.
260      */

261     private Component JavaDoc focusGainAllowedFor;
262     
263
264     // project structure (static)
265

266     /**
267      * <code>SourceGroups</code> that have at least one test
268      * <code>SourceGroup</code> assigned. It is equal to set of keys
269      * of the {@link #sourcesToTestsMap}.
270      * It is updated whenever {@link #project} changes.
271      *
272      * @see #setUp
273      */

274     private SourceGroup[] testableSourceGroups;
275     /** root folders of {@link #testableSourceGroups} */
276     private FileObject[] testableSourceGroupsRoots;
277     /** <!-- PENDING --> */
278     private SourceGroup[] allTestSourceGroups;
279     /**
280      * relation between <code>SourceGroup</code>s
281      * and their respective test <code>SourceGroup</code>s.
282      * It is updated whenever {@link #project} changes.
283      *
284      * @see #setUp
285      */

286     private Map JavaDoc<SourceGroup,Object JavaDoc[]> sourcesToTestsMap;
287     
288
289     // entered and computed data
290

291     /**
292      * index of the first <code>SourceGroup</code> where a file named
293      * according to contents of {@link #srcRelFileNameSys} was found.
294      * The search is performed in {@link #testableSourceGroupsRoots}.
295      * If such a file is not found in any of the source groups roots,
296      * this variable is set to <code>-1</code>.
297      *
298      * @see #classExists
299      */

300     private int sourceGroupParentIndex = -1;
301     /** */
302     private FileObject srcFile;
303     private SourceGroup srcGroup = null;
304     private String JavaDoc testsRootDirName = ""; //NOI18N
305
private String JavaDoc srcRelFileNameSys = ""; //NOI18N
306
private String JavaDoc testRelFileName = ""; //NOI18N
307
/** */
308     private FileObject testRootFolder;
309     /** */
310     private int classNameLength = 0;
311     /** length of the string denoting name of the selected SourceGroup */
312     private boolean srcGroupNameDisplayed = false;
313     /** <!-- PENDING --> */
314     private boolean programmaticChange = false;
315     /** <!-- PENDING --> */
316     private boolean navigationFilterEnabled = false;
317     /** <!-- PENDING --> */
318     private ClsNameNavigationFilter clsNameNavigationFilter;
319     /** <!-- PENDING --> */
320     private ClsNameDocumentFilter clsNameDocumentFilter;
321     
322     /** */
323     private boolean ignoreCboxItemChanges = false;
324     /** */
325     private boolean ignoreClsNameChanges = false;
326
327     
328     // validation of entered data
329

330     /**
331      * <code>true</code> if data entered in the form are valid.
332      * The data are valid if the entered class name denotes an existing
333      * class and at least one of the <em>Method Access Levels</em>
334      * checkboxes is selected.
335      */

336     private boolean isValid = false;
337     /** is the class name non-empty and valid? */
338     private boolean classNameValid = false;
339     /**
340      * <code>true</code> if and only if a file named
341      * according to contents of {@link #srcRelFileNameSys} was found.
342      * The search is performed in {@link #testableSourceGroupsRoots}.
343      * If this variable is <code>true</code>, variable
344      * {@link #sourceGroupParentIndex} is set to a non-negative value.
345      */

346     private boolean classExists = false;
347     /**
348      * <code>true</code> if and only if at least one of the checkboxes
349      * in the <em>Method Access Levels</em> group is selected
350      */

351     private boolean chkBoxesValid = false;
352
353     
354     //--------------------------------------------------------------------------
355

356     public SimpleTestStepLocation() {
357         visualComp = createVisualComp();
358     }
359     
360     private Component JavaDoc createVisualComp() {
361         JLabel JavaDoc lblClassToTest = new JLabel JavaDoc();
362         JLabel JavaDoc lblCreatedTestClass = new JLabel JavaDoc();
363         JLabel JavaDoc lblProject = new JLabel JavaDoc();
364         JLabel JavaDoc lblLocation = new JLabel JavaDoc();
365         JLabel JavaDoc lblFile = new JLabel JavaDoc();
366         tfClassToTest = new JTextField JavaDoc(35);
367         btnBrowse = new JButton JavaDoc();
368         tfTestClass = new JTextField JavaDoc();
369         tfProjectName = new JTextField JavaDoc();
370         cboxLocation = new JComboBox JavaDoc();
371         tfCreatedFile = new JTextField JavaDoc();
372         
373         ResourceBundle JavaDoc bundle
374                 = NbBundle.getBundle(SimpleTestStepLocation.class);
375         
376         Mnemonics.setLocalizedText(lblClassToTest,
377                                    bundle.getString("LBL_ClassToTest"));//NOI18N
378
Mnemonics.setLocalizedText(lblCreatedTestClass,
379                                    bundle.getString("LBL_TestClass")); //NOI18N
380
Mnemonics.setLocalizedText(lblProject,
381                                    bundle.getString("LBL_Project")); //NOI18N
382
Mnemonics.setLocalizedText(lblLocation,
383                                    bundle.getString("LBL_Location")); //NOI18N
384
Mnemonics.setLocalizedText(lblFile,
385                                    bundle.getString("LBL_CreatedFile"));//NOI18N
386
Mnemonics.setLocalizedText(btnBrowse,
387                                    bundle.getString("LBL_Browse")); //NOI18N
388

389         lblClassToTest.setLabelFor(tfClassToTest);
390         lblCreatedTestClass.setLabelFor(tfTestClass);
391         lblProject.setLabelFor(tfProjectName);
392         lblFile.setLabelFor(tfCreatedFile);
393         lblLocation.setLabelFor(cboxLocation);
394         
395         tfTestClass.setEditable(false);
396         tfProjectName.setEditable(false);
397         tfCreatedFile.setEditable(false);
398         
399         tfTestClass.setFocusable(false);
400         tfProjectName.setFocusable(false);
401         tfCreatedFile.setFocusable(false);
402         
403         cboxLocation.setEditable(false);
404         
405         JCheckBox JavaDoc[] chkBoxes;
406         
407         JComponent JavaDoc accessLevels = GuiUtils.createChkBoxGroup(
408                 NbBundle.getMessage(
409                         GuiUtils.class,
410                         "JUnitCfgOfCreate.groupAccessLevels"), //NOI18N
411
chkBoxes = GuiUtils.createCheckBoxes(new String JavaDoc[] {
412                         GuiUtils.CHK_PUBLIC,
413                         GuiUtils.CHK_PROTECTED,
414                         GuiUtils.CHK_PACKAGE}));
415         chkPublic = chkBoxes[0];
416         chkProtected = chkBoxes[1];
417         chkPackagePrivate = chkBoxes[2];
418         
419         JComponent JavaDoc optCode = GuiUtils.createChkBoxGroup(
420                 NbBundle.getMessage(
421                         GuiUtils.class,
422                         "JUnitCfgOfCreate.groupOptCode"), //NOI18N
423
chkBoxes = GuiUtils.createCheckBoxes(new String JavaDoc[] {
424                         GuiUtils.CHK_SETUP,
425                         GuiUtils.CHK_TEARDOWN,
426                         GuiUtils.CHK_METHOD_BODIES}));
427         chkSetUp = chkBoxes[0];
428         chkTearDown = chkBoxes[1];
429         chkMethodBodies = chkBoxes[2];
430         
431         JComponent JavaDoc optComments = GuiUtils.createChkBoxGroup(
432                 NbBundle.getMessage(
433                         GuiUtils.class,
434                         "JUnitCfgOfCreate.groupOptComments"), //NOI18N
435
chkBoxes = GuiUtils.createCheckBoxes(new String JavaDoc[] {
436                         GuiUtils.CHK_JAVADOC,
437                         GuiUtils.CHK_HINTS}));
438         chkJavadoc = chkBoxes[0];
439         chkHints = chkBoxes[1];
440                         
441         /* set layout of the components: */
442         JPanel JavaDoc targetPanel
443                 = new SizeRestrictedPanel(new GridBagLayout JavaDoc(), false, true);
444         
445         GridBagConstraints JavaDoc gbcLeft = new GridBagConstraints JavaDoc();
446         gbcLeft.anchor = GridBagConstraints.WEST;
447         gbcLeft.gridwidth = 1;
448         gbcLeft.insets = new Insets JavaDoc(0, 0, 6, 12);
449         gbcLeft.fill = GridBagConstraints.NONE;
450         gbcLeft.weightx = 0.0f;
451         
452         GridBagConstraints JavaDoc gbcRight = new GridBagConstraints JavaDoc();
453         gbcRight.anchor = GridBagConstraints.WEST;
454         gbcRight.gridwidth = GridBagConstraints.REMAINDER;
455         gbcRight.insets = new Insets JavaDoc(0, 0, 6, 0);
456         gbcRight.fill = GridBagConstraints.BOTH;
457         gbcRight.weightx = 1.0f;
458         
459         // Class to Test:
460

461         gbcRight.gridwidth = 1;
462         
463         GridBagConstraints JavaDoc gbcBrowse = new GridBagConstraints JavaDoc();
464         gbcBrowse.insets = new Insets JavaDoc(0, 11, 6, 0);
465         gbcBrowse.gridwidth = GridBagConstraints.REMAINDER;
466         
467         targetPanel.add(lblClassToTest, gbcLeft);
468         targetPanel.add(tfClassToTest, gbcRight);
469         targetPanel.add(btnBrowse, gbcBrowse);
470         
471         // Created Test Class:
472

473         gbcLeft.insets.bottom = gbcRight.insets.bottom = 24;
474         
475         targetPanel.add(lblCreatedTestClass, gbcLeft);
476         targetPanel.add(tfTestClass, gbcRight);
477         targetPanel.add(new JPanel JavaDoc(), gbcBrowse); //filler
478

479         // Project:
480

481         gbcRight.gridwidth = GridBagConstraints.REMAINDER;
482         
483         gbcLeft.insets.bottom = gbcRight.insets.bottom = 6;
484         
485         targetPanel.add(lblProject, gbcLeft);
486         targetPanel.add(tfProjectName, gbcRight);
487         
488         // Location:
489

490         gbcLeft.insets.bottom = gbcRight.insets.bottom = 12;
491         
492         targetPanel.add(lblLocation, gbcLeft);
493         targetPanel.add(cboxLocation, gbcRight);
494         
495         // Created File:
496

497         gbcLeft.insets.bottom = gbcRight.insets.bottom = 0;
498         
499         targetPanel.add(lblFile, gbcLeft);
500         targetPanel.add(tfCreatedFile, gbcRight);
501         
502         //
503

504         JComponent JavaDoc accessLevelsBox = new SizeRestrictedPanel(true, false);
505         accessLevelsBox.setLayout(
506                 new BoxLayout JavaDoc(accessLevelsBox, BoxLayout.Y_AXIS));
507         accessLevelsBox.add(accessLevels);
508         accessLevelsBox.add(Box.createVerticalGlue());
509         
510         JComponent JavaDoc optionalCodeBox = new SizeRestrictedPanel(true, false);
511         optionalCodeBox.setLayout(
512                 new BoxLayout JavaDoc(optionalCodeBox, BoxLayout.Y_AXIS));
513         optionalCodeBox.add(optCode);
514         optionalCodeBox.add(Box.createVerticalStrut(11));
515         optionalCodeBox.add(optComments);
516         optionalCodeBox.add(Box.createVerticalGlue());
517         
518         JComponent JavaDoc optionsBox = new SizeRestrictedPanel(false, true);
519         optionsBox.setLayout(
520                 new BoxLayout JavaDoc(optionsBox, BoxLayout.X_AXIS));
521         optionsBox.add(accessLevelsBox);
522         optionsBox.add(Box.createHorizontalStrut(18));
523         optionsBox.add(optionalCodeBox);
524         optionsBox.add(Box.createHorizontalGlue());
525         
526         final Box JavaDoc result = Box.createVerticalBox();
527         result.add(targetPanel);
528         result.add(Box.createVerticalStrut(12));
529             JPanel JavaDoc separatorPanel = new SizeRestrictedPanel(new GridLayout JavaDoc(),
530                                                             false, true);
531             separatorPanel.add(new JSeparator JavaDoc());
532         result.add(separatorPanel);
533         result.add(Box.createVerticalStrut(12));
534         result.add(optionsBox);
535         //result.add(Box.createVerticalGlue()); //not necessary
536

537         /* tune layout of the components within the box: */
538         targetPanel.setAlignmentX(0.0f);
539         optionsBox.setAlignmentX(0.0f);
540         optCode.setAlignmentX(0.0f);
541         optComments.setAlignmentX(0.0f);
542         
543         result.setName(bundle.getString("LBL_panel_ChooseClass"));
544         
545         addAccessibilityDescriptions(result);
546         setUpInteraction();
547         
548         return result;
549     }
550     
551     /**
552      * Sets up tooltips and accessibility names and descriptions
553      * for GUI elements of the wizard panel.
554      *
555      * @param wizPanel wizard panel whose elements need to be made accessible.
556      */

557     private void addAccessibilityDescriptions(Component JavaDoc wizPanel) {
558         final ResourceBundle JavaDoc bundle
559                 = NbBundle.getBundle(SimpleTestStepLocation.class);
560         
561         tfClassToTest.setToolTipText(
562                 bundle.getString("SimpleTest.classToTest.toolTip")); //NOI18N
563
tfClassToTest.getAccessibleContext().setAccessibleName(
564                 bundle.getString("SimpleTest.classToTest.AN")); //NOI18N
565
tfClassToTest.getAccessibleContext().setAccessibleDescription(
566                 bundle.getString("SimpleTest.classToTest.AD")); //NOI18N
567

568         btnBrowse.setToolTipText(
569                 bundle.getString("SimpleTest.btnBrowse.toolTip")); //NOI18N
570
btnBrowse.getAccessibleContext().setAccessibleName(
571                 bundle.getString("SimpleTest.btnBrowse.AN")); //NOI18N
572
btnBrowse.getAccessibleContext().setAccessibleDescription(
573                 bundle.getString("SimpleTest.btnBrowse.AD")); //NOI18N
574

575         cboxLocation.setToolTipText(
576                 bundle.getString("SimpleTest.location.toolTip")); //NOI18N
577
cboxLocation.getAccessibleContext().setAccessibleName(
578                 bundle.getString("SimpleTest.location.AN")); //NOI18N
579
cboxLocation.getAccessibleContext().setAccessibleDescription(
580                 bundle.getString("SimpleTest.location.AD")); //NOI18N
581

582         wizPanel.getAccessibleContext().setAccessibleDescription(
583                 bundle.getString("SimpleTest.AD")); //NOI18N
584
}
585     
586     /**
587      * <!-- PENDING -->
588      *
589      * @return <code>true</code> if the selected item has changed,
590      * <code>false</code> otherwise
591      */

592     private boolean updateLocationComboBox() {
593         Object JavaDoc[] srcRootsToOffer;
594         
595         if ((allTestSourceGroups.length == 1) || (srcGroup == null)) {
596             srcRootsToOffer = allTestSourceGroups;
597         } else {
598             srcRootsToOffer = (Object JavaDoc[]) sourcesToTestsMap.get(srcGroup);
599         }
600         
601         Object JavaDoc previousSelectedItem = cboxLocation.getSelectedItem();
602         
603         ignoreCboxItemChanges = true;
604         try {
605             Object JavaDoc[] items = createNamedItems(srcRootsToOffer);
606             cboxLocation.setModel(new DefaultComboBoxModel JavaDoc(items));
607             if (previousSelectedItem != null) {
608                 cboxLocation.setSelectedItem(previousSelectedItem);//may not process
609
}
610         } finally {
611             ignoreCboxItemChanges = false;
612         }
613         
614         Object JavaDoc newSelectedItem = cboxLocation.getSelectedItem();
615         
616         return !newSelectedItem.equals(previousSelectedItem);
617     }
618     
619     /**
620      */

621     private static NamedObject[] createNamedItems(final Object JavaDoc[] srcRoots) {
622         
623         //PENDING - should not the source groups be sorted (alphabetically)?
624
NamedObject[] items = new NamedObject[srcRoots.length];
625         for (int i = 0; i < srcRoots.length; i++) {
626             String JavaDoc name = (srcRoots[i] instanceof SourceGroup)
627                           ? ((SourceGroup) srcRoots[i]).getDisplayName()
628                           : (srcRoots[i] instanceof FileObject)
629                             ? FileUtil.getFileDisplayName((FileObject)
630                                                           srcRoots[i])
631                             : srcRoots[i].toString();
632             items[i] = new NamedObject(srcRoots[i],
633                                        name);
634         }
635         return items;
636     }
637     
638     /**
639      */

640     private void setUpInteraction() {
641         
642         class UIListener implements ActionListener JavaDoc, DocumentListener JavaDoc,
643                                     FocusListener JavaDoc, ItemListener JavaDoc {
644             public void actionPerformed(ActionEvent JavaDoc e) {
645                 
646                 /* button Browse... pressed */
647                 
648                 chooseClass();
649             }
650             public void insertUpdate(DocumentEvent JavaDoc e) {
651                 classNameChanged();
652             }
653             public void removeUpdate(DocumentEvent JavaDoc e) {
654                 classNameChanged();
655             }
656             public void changedUpdate(DocumentEvent JavaDoc e) {
657                 classNameChanged();
658             }
659             public void focusGained(FocusEvent JavaDoc e) {
660                 Object JavaDoc source = e.getSource();
661                 if (source == tfClassToTest) {
662                     //tfClassToTest.getDocument().addDocumentListener(this);
663
}
664             }
665             public void focusLost(FocusEvent JavaDoc e) {
666                 Object JavaDoc source = e.getSource();
667                 if (source == tfClassToTest) {
668                     //tfClassToTest.getDocument().removeDocumentListener(this);
669
if (!e.isTemporary()) {
670                         tfClassToTestFocusLost(e);
671                     }
672                 } else if ((source == btnBrowse) && !e.isTemporary()) {
673                     btnBrowseFocusLost(e);
674                 }
675             }
676             public void itemStateChanged(ItemEvent JavaDoc e) {
677                 if (e.getSource() == cboxLocation) {
678                     if (!ignoreCboxItemChanges) {
679                         locationChanged();
680                     }
681                 } else {
682                     /*
683                      * source is one of the Method Access Levels ckeck-boxes
684                      */

685                     checkChkBoxesValidity();
686                     setValidity();
687                 }
688             }
689         }
690         
691         final UIListener listener = new UIListener();
692         
693         btnBrowse.addActionListener(listener);
694         tfClassToTest.addFocusListener(listener);
695         btnBrowse.addFocusListener(listener);
696         cboxLocation.addItemListener(listener);
697         chkPublic.addItemListener(listener);
698         chkProtected.addItemListener(listener);
699         chkPackagePrivate.addItemListener(listener);
700         tfClassToTest.getDocument().addDocumentListener(listener);
701     }
702     
703     /**
704      */

705     private void tfClassToTestFocusLost(FocusEvent JavaDoc e) {
706         final Component JavaDoc allowFocusGain = focusGainAllowedFor;
707         focusGainAllowedFor = null;
708         
709         if (multipleSourceRoots
710                 && interactionRestrictionsActive
711                 && !interactionRestrictionsSuspended) {
712
713             final Component JavaDoc opposite = e.getOppositeComponent();
714
715             if ((allowFocusGain != null) && (opposite == allowFocusGain)) {
716                 return;
717             }
718             if (opposite == btnBrowse) {
719                 return;
720             }
721             if ((opposite instanceof JLabel JavaDoc)
722                     && (((JLabel JavaDoc) opposite).getLabelFor() == tfClassToTest)) {
723                 /*
724                  * When a JLabel's mnemonic key is pressed, the JLabel gains focus
725                  * until the key is released again. That's why we must ignore such
726                  * focus transfers.
727                  */

728                 return;
729             }
730             
731             if (!maybeDisplaySourceGroupChooser()) {
732                 
733                 /* send the request back to the Test to Class textfield: */
734                 tfClassToTest.requestFocus();
735             }
736         }
737     }
738     
739     /**
740      */

741     private void btnBrowseFocusLost(FocusEvent JavaDoc e) {
742         final Component JavaDoc allowFocusGain = focusGainAllowedFor;
743         focusGainAllowedFor = null;
744         
745         if (multipleSourceRoots
746                 && interactionRestrictionsActive
747                 && !interactionRestrictionsSuspended) {
748
749             final Component JavaDoc opposite = e.getOppositeComponent();
750
751             if ((allowFocusGain != null) && (opposite == allowFocusGain)) {
752                 return;
753             }
754             if (opposite == tfClassToTest) {
755                 return;
756             }
757             if ((opposite instanceof JLabel JavaDoc)
758                     && (((JLabel JavaDoc) opposite).getLabelFor() == tfClassToTest)) {
759                 /*
760                  * When a JLabel's mnemonic key is pressed, the JLabel gains focus
761                  * until the key is released again. That's why we must ignore such
762                  * focus transfers.
763                  */

764                 return;
765             }
766
767             if (!maybeDisplaySourceGroupChooser()) {
768                 
769                 /* send the request back to the Browse... button: */
770                 btnBrowse.requestFocus();
771             }
772         }
773     }
774     
775     /**
776      * <!-- PENDING -->
777      *
778      * @return <code>false</code> if the SourceGroup chooser was displayed
779      * and the user cancelled the choice; <code>true</code> otherwise
780      */

781     private boolean maybeDisplaySourceGroupChooser() {
782         assert multipleSourceRoots;
783         
784         if (classExists && (srcGroup == null)) {
785             SourceGroup[] candidates = findParentGroupCandidates();
786             
787             assert candidates.length != 0; //because the class exists
788

789             if (candidates.length == 1) {
790                 setSelectedSrcGroup(candidates[0]);
791                 return true;
792             } else {
793                 SourceGroup chosenSrcGroup = chooseSrcGroup(candidates);
794                 if (chosenSrcGroup != null) {
795                     setSelectedSrcGroup(chosenSrcGroup);
796                     return true;
797                 } else {
798                     return false;
799                 }
800             }
801         } else {
802             return true;
803         }
804     }
805     
806     /**
807      * Displays a source root chooser which allows the user to choose
808      * a parent source root for the entered class name.
809      *
810      * @param candidates source roots to be offered to the user
811      * @return the chosen source root,
812      * or <code>null</code> if the user cancelled the choice
813      */

814     private SourceGroup chooseSrcGroup(final SourceGroup[] candidates) {
815         assert (candidates != null) && (candidates.length != 0);
816
817         final String JavaDoc[] rootNames = new String JavaDoc[candidates.length];
818         for (int i = 0; i < rootNames.length; i++) {
819             rootNames[i] = candidates[i].getDisplayName();
820         }
821         
822         final JButton JavaDoc btn = new JButton JavaDoc(
823                 NbBundle.getMessage(getClass(),
824                                     "LBL_SelectBtn")); //NOI18N
825
final JList JavaDoc list = new JList JavaDoc(rootNames);
826         list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
827         list.setSelectedIndex(0);
828         list.addListSelectionListener(new ListSelectionListener JavaDoc() {
829             public void valueChanged(ListSelectionEvent JavaDoc e) {
830                 btn.setEnabled(!list.isSelectionEmpty());
831             }
832         });
833         JPanel JavaDoc panel = new JPanel JavaDoc(new BorderLayout JavaDoc(0, 0));
834         panel.add(list, BorderLayout.CENTER);
835         panel.setBorder(BorderFactory.createCompoundBorder(
836                 BorderFactory.createEmptyBorder(12, 12, 0, 12),
837                 BorderFactory.createBevelBorder(BevelBorder.LOWERED)));
838         
839         String JavaDoc dialogTitle = NbBundle.getMessage(
840                                     getClass(),
841                                     "LBL_SourceRootChooserTitle"); //NOI18N
842
DialogDescriptor descriptor
843                 = new DialogDescriptor(panel, //component
844
dialogTitle, //title
845
true, //modal
846
new Object JavaDoc[] { //options
847
btn,
848                                                NotifyDescriptor.CANCEL_OPTION},
849                                        btn, //default option
850
DialogDescriptor.DEFAULT_ALIGN,
851                                        (HelpCtx) null,
852                                        (ActionListener JavaDoc) null);
853         Object JavaDoc selected = DialogDisplayer.getDefault().notify(descriptor);
854         return (selected == btn) ? candidates[list.getSelectedIndex()]
855                                  : (SourceGroup) null;
856     }
857     
858     /**
859      */

860     private void setSelectedSrcGroup(SourceGroup srcGroup) {
861         setSelectedSrcGroup(srcGroup, true);
862     }
863     
864     /**
865      * <!-- PENDING -->
866      */

867     private void setSelectedSrcGroup(SourceGroup srcGroup, boolean updateDisp) {
868         assert multipleSourceRoots
869                && ((srcGroup == null) || (classNameValid && classExists));
870         
871         if (!checkObjChanged(this.srcGroup, srcGroup)) {
872             return;
873         }
874         
875         this.srcGroup = srcGroup;
876         
877         if (updateDisp) {
878             
879             /* update the display: */
880             try {
881                 programmaticChange = true;
882
883                 String JavaDoc className = tfClassToTest.getText()
884                                    .substring(0, classNameLength);
885                 String JavaDoc srcGroupDisplay = getSrcGrpDisp(srcGroup);
886                 
887                 ignoreClsNameChanges = true;
888                 tfClassToTest.setText(className + srcGroupDisplay);
889                 ignoreClsNameChanges = false;
890                 
891                 classNameLength = className.length();
892                 classNameChanged();
893                 srcGroupNameDisplayed = true;
894                 setNavigationFilterEnabled(true);
895             } finally {
896                 ignoreClsNameChanges = false;
897                 programmaticChange = false;
898             }
899         }
900         
901         updateInteractionRestrictionsState();
902
903             /*
904          * There is no need to check and set validity.
905          * The user should be offered to choose a source root only when
906          * the entered class name is valid and the class exists
907          * in at least two source roots.
908          */

909         
910         /* update target folder: */
911         if (allTestSourceGroups.length > 1) {
912             boolean locationChanged = updateLocationComboBox();
913             if (locationChanged) {
914                 updateTargetFolderData();
915             }
916         }
917         
918         /* update name of the file to be created: */
919         updateCreatedFileName();
920         
921         /* set 'srcFile': */
922         srcFile = (srcGroup != null)
923                   ? srcGroup.getRootFolder().getFileObject(srcRelFileNameSys)
924                   : null;
925         
926         assert (srcGroup == null) || (srcFile != null);
927     }
928     
929     /**
930      */

931     private static String JavaDoc getSrcGrpDisp(SourceGroup srcGroup) {
932         if (srcGroup == null) {
933             return ""; //NOI18N
934
} else {
935             String JavaDoc srcGroupName = srcGroup.getDisplayName();
936             return new StringBuffer JavaDoc(srcGroupName.length() + 3)
937                    .append(' ')
938                    .append('(').append(srcGroupName).append(')')
939                    .toString();
940         }
941     }
942     
943     /**
944      */

945     private void setNavigationFilterEnabled(boolean enabled) {
946         if (enabled == navigationFilterEnabled) {
947             if (enabled) {
948                 clsNameNavigationFilter.ensureCursorInRange();
949             }
950             return;
951         }
952         
953         if (enabled) {
954             if (clsNameNavigationFilter == null) {
955                 clsNameNavigationFilter = new ClsNameNavigationFilter();
956             }
957             tfClassToTest.setNavigationFilter(clsNameNavigationFilter);
958             clsNameNavigationFilter.ensureCursorInRange();
959         } else {
960             tfClassToTest.setNavigationFilter(null);
961         }
962         this.navigationFilterEnabled = enabled;
963     }
964     
965     /**
966      * <!-- PENDING -->
967      */

968     private void updateInteractionRestrictionsState() {
969         setInteractionRestrictionsSuspended(
970                 !classNameValid || !classExists || (srcGroup != null));
971     }
972     
973     /**
974      */

975     private void updateTargetFolderData() {
976         Object JavaDoc item = cboxLocation.getSelectedItem();
977         if (item != null) {
978             SourceGroup targetSourceGroup = (SourceGroup)
979                                             ((NamedObject) item).object;
980             testRootFolder = targetSourceGroup.getRootFolder();
981             testsRootDirName = FileUtil.getFileDisplayName(testRootFolder);
982         } else {
983             testRootFolder = null;
984             testsRootDirName = ""; //NOI18N
985
}
986     }
987     
988     /**
989      * Called whenever selection in the Location combo-box is changed.
990      */

991     private void locationChanged() {
992         updateTargetFolderData();
993         updateCreatedFileName();
994     }
995     
996     /**
997      */

998     private void classNameChanged() {
999         if (ignoreClsNameChanges) {
1000            return;
1001        }
1002        
1003        String JavaDoc className;
1004        if (!programmaticChange) {
1005            className = tfClassToTest.getText().trim();
1006            classNameLength = className.length();
1007        } else {
1008            className = tfClassToTest.getText().substring(0, classNameLength);
1009        }
1010        
1011        String JavaDoc testClassName;
1012        if (className.length() != 0) {
1013            srcRelFileNameSys = className.replace('.', '/')
1014                                + ".java"; //NOI18N
1015
testClassName = className + testClassNameSuffix;
1016            testRelFileName = testClassName.replace('.', File.separatorChar)
1017                              + ".java"; //NOI18N
1018
} else {
1019            srcRelFileNameSys = ""; //NOI18N
1020
testClassName = ""; //NOI18N
1021
testRelFileName = ""; //NOI18N
1022
}
1023        tfTestClass.setText(testClassName);
1024        
1025        if (!programmaticChange) {
1026            updateCreatedFileName();
1027            if (checkClassNameValidity()) {
1028                checkSelectedClassExists();
1029            }
1030            setErrorMsg(msgStack.getDisplayedMessage());
1031            setValidity();
1032
1033            /*
1034             * The user modified the class name.
1035             * It may be ambiguous - it may match classes in multiple SourceGroups.
1036             */

1037            if (multipleSourceRoots) {
1038                setSelectedSrcGroup(null, false);
1039            }
1040        }
1041        
1042        if (multipleSourceRoots) {
1043            updateInteractionRestrictionsState();
1044        }
1045    }
1046    
1047    /**
1048     * Identifies all <code>SourceGroup</code>s containing file having the
1049     * name entered by the user.
1050     * This method assumes that at least one such <code>SourceGroup</code>
1051     * has already been found and its index stored in field
1052     * {@link #sourceGroupParentIndex}.
1053     *
1054     * @return array of matching <code>SourceGroup</code>s
1055     * (always contains at least one element)
1056     */

1057    private SourceGroup[] findParentGroupCandidates() {
1058        assert sourceGroupParentIndex >= 0;
1059        
1060        List JavaDoc<SourceGroup> cands = null;
1061        final int count = testableSourceGroups.length;
1062        for (int i = sourceGroupParentIndex + 1; i < count; i++) {
1063            final FileObject groupRoot = testableSourceGroupsRoots[i];
1064            FileObject srcFile = groupRoot.getFileObject(srcRelFileNameSys);
1065            if (srcFile != null && testableSourceGroups[i].contains(srcFile)) {
1066                if (cands == null) {
1067                    cands = new ArrayList JavaDoc<SourceGroup>(testableSourceGroups.length - i + 1);
1068                    cands.add(testableSourceGroups[sourceGroupParentIndex]);
1069                }
1070                cands.add(testableSourceGroups[i]);
1071            }
1072        }
1073        return cands == null
1074              ? new SourceGroup[] {testableSourceGroups[sourceGroupParentIndex]}
1075              : cands.toArray(new SourceGroup[cands.size()]);
1076    }
1077    
1078    /**
1079     */

1080    private void updateCreatedFileName() {
1081        tfCreatedFile.setText(testsRootDirName + File.separatorChar + testRelFileName);
1082    }
1083    
1084    /**
1085     * Checks validity of the entered class name, updates messages
1086     * on the message stack and updates the <code>classNameValid</code> field.
1087     *
1088     * @see #msgStack
1089     * @see #setValidity()
1090     */

1091    private boolean checkClassNameValidity() {
1092        String JavaDoc className = tfClassToTest.getText().trim();
1093        if (srcGroupNameDisplayed) {
1094            className = className.substring(0, classNameLength);
1095        }
1096        
1097        if (className.length() == 0) {
1098            msgStack.clearMessage(MSG_LAYER_CLASSNAME);
1099            classNameValid = false;
1100        } else if (Utils.isValidClassName(className)) {
1101            msgStack.clearMessage(MSG_LAYER_CLASSNAME);
1102            classNameValid = true;
1103        } else {
1104            if (msgClassNameInvalid == null) {
1105                msgClassNameInvalid = NbBundle.getMessage(
1106                        JUnitCfgOfCreate.class,
1107                        "MSG_InvalidClassName"); //NOI18N
1108
}
1109            msgStack.setMessage(MSG_LAYER_CLASSNAME, msgClassNameInvalid);
1110            classNameValid = false;
1111        }
1112        
1113        return classNameValid;
1114    }
1115    
1116    /**
1117     * Checks whether a class having the entered name exists, updates messages
1118     * on the message stack and updates the <code>classExists</code> field.
1119     *
1120     * @see #setValidity()
1121     */

1122    private boolean checkSelectedClassExists() {
1123        sourceGroupParentIndex = -1;
1124        
1125        final int count = testableSourceGroups.length;
1126        for (int i = 0; i < count; i++) {
1127            final FileObject groupRoot = testableSourceGroupsRoots[i];
1128            FileObject srcFile = groupRoot.getFileObject(srcRelFileNameSys);
1129            if (srcFile != null && testableSourceGroups[i].contains(srcFile)) {
1130                this.srcFile = srcFile;
1131                sourceGroupParentIndex = i;
1132                break;
1133            }
1134        }
1135        
1136        classExists = (sourceGroupParentIndex != -1);
1137        
1138        if (classExists) {
1139            msgStack.clearMessage(MSG_LAYER_CLASSNAME);
1140        } else {
1141            if (msgClassToTestDoesNotExist == null) {
1142                msgClassToTestDoesNotExist = NbBundle.getMessage(
1143                        SimpleTestStepLocation.class,
1144                        "MSG_ClassToTestDoesNotExist"); //NOI18N
1145
}
1146            msgStack.setMessage(MSG_LAYER_CLASSNAME,
1147                                msgClassToTestDoesNotExist);
1148        }
1149        
1150        return classExists;
1151    }
1152    
1153    /**
1154     * Checks whether at least one of the <em>Method Access Levels</em>
1155     * checkboxes is selected, updates messages
1156     * on the message stack and updates the <code>chkBoxesValid</code> field.
1157     *
1158     * @see #setValidity()
1159     */

1160    private boolean checkChkBoxesValidity() {
1161        chkBoxesValid = chkPublic.isSelected()
1162                        || chkProtected.isSelected()
1163                        || chkPackagePrivate.isSelected();
1164        String JavaDoc msgUpdate;
1165        if (chkBoxesValid) {
1166            msgUpdate = msgStack.clearMessage(MSG_LAYER_CHECKBOXES);
1167        } else {
1168            if (msgChkBoxesInvalid == null) {
1169                //PENDING - text of the message:
1170
msgChkBoxesInvalid = NbBundle.getMessage(
1171                        JUnitCfgOfCreate.class,
1172                        "MSG_AllMethodTypesDisabled"); //NOI18N
1173
}
1174            msgUpdate = msgStack.setMessage(MSG_LAYER_CHECKBOXES,
1175                                            msgChkBoxesInvalid);
1176        }
1177        if (msgUpdate != null) {
1178            setErrorMsg(msgStack.getDisplayedMessage());
1179        }
1180        return chkBoxesValid;
1181    }
1182    
1183    /**
1184     * Updates the <code>isValid</code> field and notifies all registered
1185     * <code>ChangeListener</code>s if validity has changed.
1186     */

1187    private void setValidity() {
1188        boolean wasValid = isValid;
1189        
1190        isValid = classNameValid && classExists && chkBoxesValid;
1191        
1192        if (isValid != wasValid) {
1193            fireChange();
1194            
1195            updateInteractionRestrictionsState();
1196            
1197            /*
1198             * This must be called after fireChange() because fireChange()
1199             * sets state (enabled/disabled) of the default button.
1200             */

1201            if (isValid
1202                    && interactionRestrictionsEnabled
1203                    && !interactionRestrictionsActive) {
1204                tryActivateInteractionRestrictions();
1205            }
1206        }
1207    }
1208    
1209    /**
1210     * Displays the given message in the wizard's message area.
1211     *
1212     * @param message message to be displayed, or <code>null</code>
1213     * if the message area should be cleared
1214     */

1215    private void setErrorMsg(String JavaDoc message) {
1216        if (wizard != null) {
1217            wizard.putProperty("WizardPanel_errorMessage", message); //NOI18N
1218
}
1219    }
1220    
1221    /**
1222     * Displays a class chooser dialog and lets the user to select a class.
1223     * If the user confirms their choice, full name of the selected class
1224     * is put into the <em>Class To Test</em> text field.
1225     */

1226    private void chooseClass() {
1227        try {
1228            final Node[] sourceGroupNodes
1229                    = new Node[testableSourceGroups.length];
1230            for (int i = 0; i < sourceGroupNodes.length; i++) {
1231                /*
1232                 * Note:
1233                 * Precise structure of this view is *not* specified by the API.
1234                 */

1235                Node srcGroupNode
1236                       = PackageView.createPackageView(testableSourceGroups[i]);
1237                sourceGroupNodes[i]
1238                       = new FilterNode(srcGroupNode,
1239                                        new JavaChildren(srcGroupNode));
1240            }
1241            
1242            Node rootNode;
1243            if (sourceGroupNodes.length == 1) {
1244                rootNode = new FilterNode(
1245                        sourceGroupNodes[0],
1246                        new JavaChildren(sourceGroupNodes[0]));
1247            } else {
1248                Children children = new Children.Array();
1249                children.add(sourceGroupNodes);
1250                
1251                AbstractNode node = new AbstractNode(children);
1252                node.setName("Project Source Roots"); //NOI18N
1253
node.setDisplayName(
1254                        NbBundle.getMessage(getClass(), "LBL_Sources"));//NOI18N
1255
//PENDING - set a better icon for the root node
1256
rootNode = node;
1257            }
1258            
1259            NodeAcceptor acceptor = new NodeAcceptor() {
1260                public boolean acceptNodes(Node[] nodes) {
1261                    Node.Cookie cookie;
1262                    return nodes.length == 1
1263                           && (cookie = nodes[0].getCookie(DataObject.class))
1264                              != null
1265                           && ((DataObject) cookie).getPrimaryFile().isFolder()
1266                              == false;
1267                }
1268            };
1269            
1270            Node selectedNode = NodeOperation.getDefault().select(
1271                    NbBundle.getMessage(SimpleTestStepLocation.class,
1272                                        "LBL_WinTitle_SelectClass"), //NOI18N
1273
NbBundle.getMessage(SimpleTestStepLocation.class,
1274                                        "LBL_SelectClassToTest"), //NOI18N
1275
rootNode,
1276                    acceptor)[0];
1277            
1278            SourceGroup selectedSourceGroup;
1279            if (sourceGroupNodes.length == 1) {
1280                selectedSourceGroup = testableSourceGroups[0];
1281            } else {
1282                Node previous = null;
1283                Node current = selectedNode.getParentNode();
1284                Node parent;
1285                while ((parent = current.getParentNode()) != null) {
1286                    previous = current;
1287                    current = parent;
1288                }
1289                /*
1290                 * 'current' now contains the root node of displayed node
1291                 * hierarchy. 'current' contains a parent node of the source
1292                 * root and 'previous' contains the parent source root of
1293                 * the selected class.
1294                 */

1295                selectedSourceGroup = null;
1296                Node selectedSrcGroupNode = previous;
1297                for (int i = 0; i < sourceGroupNodes.length; i++) {
1298                    if (sourceGroupNodes[i] == selectedSrcGroupNode) {
1299                        selectedSourceGroup = testableSourceGroups[i];
1300                        sourceGroupParentIndex = i;
1301                        break;
1302                    }
1303                }
1304                assert selectedSourceGroup != null;
1305                assert sourceGroupParentIndex >= 0;
1306            }
1307            srcGroup = selectedSourceGroup;
1308            
1309            FileObject selectedFileObj
1310                    = ((DataObject) selectedNode.getCookie(DataObject.class))
1311                      .getPrimaryFile();
1312            
1313            /* display selected class name: */
1314            try {
1315                programmaticChange = true;
1316                
1317                String JavaDoc className = getClassName(selectedFileObj);
1318                classNameLength = className.length();
1319                if (!multipleSourceRoots) {
1320                    tfClassToTest.setText(className);
1321                } else {
1322                    String JavaDoc srcGroupDisplay = getSrcGrpDisp(selectedSourceGroup);
1323
1324                    ignoreClsNameChanges = true;
1325                    tfClassToTest.setText(className + srcGroupDisplay);
1326                    ignoreClsNameChanges = false;
1327                    
1328                    classNameLength = className.length();
1329                    classNameChanged();
1330                    srcGroupNameDisplayed = true;
1331                    setNavigationFilterEnabled(true);
1332                }
1333                /*
1334                 * Change of text of the Class to Test text-field triggers
1335                 * update of variable 'testRelFileName'.
1336                 */

1337            } finally {
1338                ignoreClsNameChanges = false;
1339                programmaticChange = false;
1340            }
1341            
1342            /* set class name validity: */
1343            classNameValid = true;
1344            classExists = true;
1345            String JavaDoc msgUpdate = msgStack.clearMessage(MSG_LAYER_CLASSNAME);
1346            if (msgUpdate != null) {
1347                setErrorMsg(msgUpdate);
1348            }
1349            setValidity();
1350            updateInteractionRestrictionsState();
1351            
1352            /* update target folder: */
1353            if (multipleSourceRoots && (allTestSourceGroups.length > 1)) {
1354                boolean locationChanged = updateLocationComboBox();
1355                if (locationChanged) {
1356                    updateTargetFolderData(); //sets also 'testRootFolder'
1357
}
1358            }
1359            
1360            /* update name of the file to be created: */
1361            updateCreatedFileName();
1362            
1363            /* set 'srcFile': */
1364            srcFile = selectedFileObj;
1365            
1366        } catch (UserCancelException ex) {
1367            // if the user cancels the choice, do nothing
1368
}
1369    }
1370    
1371    private static String JavaDoc getClassName(FileObject fileObj) {
1372        //PENDING: is it ensured that the classpath is non-null?
1373
return ClassPath.getClassPath(fileObj, ClassPath.SOURCE)
1374               .getResourceName(fileObj, '.', false);
1375    }
1376    
1377    public Component JavaDoc getComponent() {
1378        return visualComp;
1379    }
1380    
1381    public boolean isValid() {
1382        return isValid;
1383    }
1384    
1385    public HelpCtx getHelp() {
1386        //PENDINGg
1387
return null;
1388    }
1389    
1390    public void readSettings(Object JavaDoc settings) {
1391        wizard = (TemplateWizard) settings;
1392        
1393        chkPublic.setSelected(
1394               Boolean.TRUE.equals(wizard.getProperty(GuiUtils.CHK_PUBLIC)));
1395        chkProtected.setSelected(
1396               Boolean.TRUE.equals(wizard.getProperty(GuiUtils.CHK_PROTECTED)));
1397        chkPackagePrivate.setSelected(
1398               Boolean.TRUE.equals(wizard.getProperty(GuiUtils.CHK_PACKAGE)));
1399        chkSetUp.setSelected(
1400               Boolean.TRUE.equals(wizard.getProperty(GuiUtils.CHK_SETUP)));
1401        chkTearDown.setSelected(
1402               Boolean.TRUE.equals(wizard.getProperty(GuiUtils.CHK_TEARDOWN)));
1403        chkMethodBodies.setSelected(
1404           Boolean.TRUE.equals(wizard.getProperty(GuiUtils.CHK_METHOD_BODIES)));
1405        chkJavadoc.setSelected(
1406               Boolean.TRUE.equals(wizard.getProperty(GuiUtils.CHK_JAVADOC)));
1407        chkHints.setSelected(
1408               Boolean.TRUE.equals(wizard.getProperty(GuiUtils.CHK_HINTS)));
1409    }
1410    
1411    public void storeSettings(Object JavaDoc settings) {
1412        wizard = (TemplateWizard) settings;
1413        
1414        wizard.putProperty(SimpleTestCaseWizard.PROP_CLASS_TO_TEST,
1415                           srcFile);
1416        wizard.putProperty(SimpleTestCaseWizard.PROP_TEST_ROOT_FOLDER,
1417                           testRootFolder);
1418        wizard.putProperty(GuiUtils.CHK_PUBLIC,
1419                           Boolean.valueOf(chkPublic.isSelected()));
1420        wizard.putProperty(GuiUtils.CHK_PROTECTED,
1421                           Boolean.valueOf(chkProtected.isSelected()));
1422        wizard.putProperty(GuiUtils.CHK_PACKAGE,
1423                           Boolean.valueOf(chkPackagePrivate.isSelected()));
1424        wizard.putProperty(GuiUtils.CHK_SETUP,
1425                           Boolean.valueOf(chkSetUp.isSelected()));
1426        wizard.putProperty(GuiUtils.CHK_TEARDOWN,
1427                           Boolean.valueOf(chkTearDown.isSelected()));
1428        wizard.putProperty(GuiUtils.CHK_METHOD_BODIES,
1429                           Boolean.valueOf(chkMethodBodies.isSelected()));
1430        wizard.putProperty(GuiUtils.CHK_JAVADOC,
1431                           Boolean.valueOf(chkJavadoc.isSelected()));
1432        wizard.putProperty(GuiUtils.CHK_HINTS,
1433                           Boolean.valueOf(chkHints.isSelected()));
1434    }
1435    
1436    public void addChangeListener(ChangeListener JavaDoc l) {
1437        if (changeListeners == null) {
1438            changeListeners = new ArrayList JavaDoc<ChangeListener JavaDoc>(4);
1439        }
1440        changeListeners.add(l);
1441    }
1442    
1443    public void removeChangeListener(ChangeListener JavaDoc l) {
1444        if (changeListeners != null) {
1445            if (changeListeners.remove(l) && changeListeners.isEmpty()) {
1446                changeListeners = null;
1447            }
1448        }
1449    }
1450    
1451    private void fireChange() {
1452        if (changeListeners != null) {
1453            ChangeEvent JavaDoc e = new ChangeEvent JavaDoc(this);
1454            for (ChangeListener JavaDoc l : changeListeners) {
1455                l.stateChanged(e);
1456            }
1457        }
1458    }
1459    
1460    /**
1461     */

1462    void setUp(final Utils utils) {
1463        final Project project = utils.getProject();
1464        
1465        if (project == this.project) {
1466            return;
1467        }
1468        
1469        this.project = project;
1470        this.sourcesToTestsMap = utils.getSourcesToTestsMap(true);
1471        
1472        int sourceGroupsCnt = sourcesToTestsMap.size();
1473        Set JavaDoc<Map.Entry JavaDoc<SourceGroup,Object JavaDoc[]>> mapEntries = sourcesToTestsMap.entrySet();
1474        List JavaDoc<SourceGroup> testGroups = new ArrayList JavaDoc<SourceGroup>(sourceGroupsCnt + 4);
1475        
1476        testableSourceGroups = new SourceGroup[sourceGroupsCnt];
1477        testableSourceGroupsRoots = new FileObject[sourceGroupsCnt];
1478        multipleSourceRoots = (sourceGroupsCnt > 1);
1479        
1480        Iterator JavaDoc<Map.Entry JavaDoc<SourceGroup,Object JavaDoc[]>> iterator = mapEntries.iterator();
1481        for (int i = 0; i < sourceGroupsCnt; i++) {
1482            Map.Entry JavaDoc<SourceGroup,Object JavaDoc[]> entry = iterator.next();
1483            SourceGroup srcGroup = entry.getKey();
1484            
1485            testableSourceGroups[i] = srcGroup;
1486            testableSourceGroupsRoots[i] = srcGroup.getRootFolder();
1487            
1488            Object JavaDoc[] testGroupsSubset = entry.getValue();
1489            for (int j = 0; j < testGroupsSubset.length; j++) {
1490                SourceGroup testGroup = (SourceGroup) testGroupsSubset[j];
1491                if (!testGroups.contains(testGroup)) {
1492                    testGroups.add(testGroup);
1493                }
1494            }
1495        }
1496        allTestSourceGroups = testGroups.toArray(
1497                                            new SourceGroup[testGroups.size()]);
1498        
1499        tfProjectName.setText(
1500                ProjectUtils.getInformation(project).getDisplayName());
1501        try {
1502            programmaticChange = true;
1503            
1504            ignoreClsNameChanges = true;
1505            tfClassToTest.setText(""); //NOI18N
1506
ignoreClsNameChanges = false;
1507            
1508            classNameLength = 0;
1509            classNameChanged();
1510            srcGroupNameDisplayed = false;
1511            setNavigationFilterEnabled(false);
1512        } finally {
1513            ignoreClsNameChanges = false;
1514            programmaticChange = false;
1515        }
1516        if (checkClassNameValidity()) {
1517            checkSelectedClassExists();
1518        } else {
1519            classExists = false;
1520        }
1521        setErrorMsg(msgStack.getDisplayedMessage());
1522        setValidity();
1523        
1524        //PENDING - if possible, we should pre-set the test source group
1525
// corresponding to the currently selected node
1526
updateLocationComboBox();
1527        updateTargetFolderData(); //sets also 'testRootFolder'
1528
updateCreatedFileName();
1529        
1530        srcFile = null;
1531        
1532        if (!multipleSourceRoots) {
1533            setInteractionRestrictionsEnabled(false);
1534        } else {
1535            AbstractDocument JavaDoc doc = (AbstractDocument JavaDoc)
1536                                   tfClassToTest.getDocument();
1537            if (clsNameDocumentFilter == null) {
1538                clsNameDocumentFilter = new ClsNameDocumentFilter();
1539            }
1540            if (doc.getDocumentFilter() != clsNameDocumentFilter) {
1541                doc.setDocumentFilter(clsNameDocumentFilter);
1542            }
1543            setInteractionRestrictionsEnabled(true);
1544        }
1545    }
1546    
1547    /**
1548     */

1549    void cleanUp() {
1550        setInteractionRestrictionsEnabled(false);
1551    }
1552    
1553    /**
1554     * <!-- PENDING -->
1555     */

1556    private void setInteractionRestrictionsEnabled(boolean enabled) {
1557        if (enabled == interactionRestrictionsEnabled) {
1558            return;
1559        }
1560        
1561        class DisplayabilityListener implements HierarchyListener JavaDoc {
1562            public void hierarchyChanged(HierarchyEvent JavaDoc e) {
1563                long flags = e.getChangeFlags();
1564                if ((flags & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
1565                    if (visualComp.isDisplayable()) {
1566                        if (interactionRestrictionsEnabled) {
1567                            setInteractionRestrictionsActive(true);
1568                        }
1569                    } else {
1570                        setInteractionRestrictionsActive(false);
1571                    }
1572                }
1573            }
1574        }
1575        
1576        if (enabled) {
1577            this.interactionRestrictionsEnabled = true;
1578            
1579            assert displayabilityListener == null;
1580            displayabilityListener = new DisplayabilityListener();
1581            visualComp.addHierarchyListener(displayabilityListener);
1582
1583            if (visualComp.isDisplayable()) {
1584                setInteractionRestrictionsActive(true);
1585            }
1586        } else {
1587            this.interactionRestrictionsEnabled = false;
1588            
1589            setInteractionRestrictionsActive(false);
1590            
1591            visualComp.removeHierarchyListener(displayabilityListener);
1592            displayabilityListener = null;
1593        }
1594    }
1595    
1596    /**
1597     * Activates or deactivates the focus detection mechanism.
1598     * <!-- PENDING -->
1599     */

1600    private void setInteractionRestrictionsActive(boolean active) {
1601        if (active == this.interactionRestrictionsActive) {
1602            return;
1603        }
1604        
1605        if (active) {
1606            tryActivateInteractionRestrictions();
1607        } else {
1608            deactivateInteractionRestrictions();
1609        }
1610    }
1611    
1612    /**
1613     */

1614    private void tryActivateInteractionRestrictions() {
1615        assert interactionRestrictionsActive == false;
1616        assert interactionRestrictionsEnabled;
1617
1618        if (rootPane == null) {
1619            rootPane = SwingUtilities.getRootPane(visualComp);
1620        }
1621        
1622        if (rootPane != null) {
1623            defaultButton = rootPane.getDefaultButton();
1624            if (defaultButton != null) {
1625                activateInteractionRestrictions();
1626            }
1627        }
1628    }
1629    
1630    /**
1631     */

1632    private void activateInteractionRestrictions() {
1633        assert interactionRestrictionsActive == false;
1634        assert (rootPane != null) && (defaultButton != null);
1635        
1636        if ((mouseBlocked == null) || (mnemonicBlocked == null)) {
1637            findComponentsToBlock();
1638            assert (mouseBlocked != null) && (mnemonicBlocked != null);
1639        }
1640        blockDefaultRootPaneAction();
1641        blockMnemonics();
1642        setMouseClicksBlockingActive(!interactionRestrictionsSuspended);
1643        
1644        interactionRestrictionsActive = true;
1645    }
1646    
1647    /**
1648     */

1649    private void deactivateInteractionRestrictions() {
1650        assert interactionRestrictionsActive == true;
1651        assert (defaultButton != null) && (rootPane != null);
1652        
1653        setMouseClicksBlockingActive(false);
1654        unblockMnemonics();
1655        unblockDefaultRootPaneAction();
1656        
1657        defaultButton = null;
1658        rootPane = null;
1659
1660        interactionRestrictionsActive = false;
1661        interactionRestrictionsSuspended = false;
1662    }
1663    
1664    /**
1665     */

1666    private void setInteractionRestrictionsSuspended(boolean suspended) {
1667        if (suspended != this.interactionRestrictionsSuspended) {
1668            setMouseClicksBlockingActive(interactionRestrictionsActive
1669                                         && !suspended);
1670            this.interactionRestrictionsSuspended = suspended;
1671        }
1672    }
1673    
1674    /**
1675     */

1676    private void setMouseClicksBlockingActive(boolean blockingActive) {
1677        if (blockingActive != this.mouseClicksBlocked) {
1678            if (blockingActive) {
1679                blockMouseClicks();
1680            } else {
1681                unblockMouseClicks();
1682            }
1683            this.mouseClicksBlocked = blockingActive;
1684        }
1685    }
1686    
1687    /**
1688     * Searches the visual component and collects components
1689     * on which mouse events or activation by mnemonics needs to be check
1690     * and evaluated.
1691     *
1692     * @see #mouseBlocked
1693     * @see #mnemonicBlocked
1694     */

1695    private void findComponentsToBlock() {
1696        assert rootPane != null;
1697        
1698        final Collection JavaDoc<Component JavaDoc> mouseBlocked
1699                = new ArrayList JavaDoc<Component JavaDoc>(20);
1700        final Collection JavaDoc<JComponent JavaDoc> mnemBlocked
1701                = new ArrayList JavaDoc<JComponent JavaDoc>(20);
1702
1703        final List JavaDoc<Component JavaDoc> stack = new ArrayList JavaDoc<Component JavaDoc>(16);
1704        stack.add(rootPane.getContentPane());
1705        int lastIndex = 0;
1706        
1707        while (lastIndex != -1) {
1708            
1709            Component JavaDoc c = stack.remove(lastIndex--);
1710            
1711            if (!c.isVisible()) {
1712                continue;
1713            }
1714            
1715            if (c instanceof JLabel JavaDoc) {
1716                JLabel JavaDoc lbl = (JLabel JavaDoc) c;
1717                Component JavaDoc labelFor = lbl.getLabelFor();
1718                if ((labelFor != null) && (labelFor != tfClassToTest)
1719                        && (lbl.getDisplayedMnemonic() != 0)) {
1720                    mnemBlocked.add(lbl);
1721                }
1722            } else if (c instanceof AbstractButton JavaDoc) {
1723                if (c != btnBrowse) {
1724                    AbstractButton JavaDoc btn = (AbstractButton JavaDoc) c;
1725                    mouseBlocked.add(btn);
1726                    if (btn.getMnemonic() != 0) {
1727                        mnemBlocked.add(btn);
1728                    }
1729                }
1730            } else if (!(c instanceof Container JavaDoc)) {
1731                if (c.isFocusable() && (c != tfClassToTest)) {
1732                    mouseBlocked.add(c);
1733                }
1734            } else {
1735                Component JavaDoc[] content = ((Container JavaDoc) c).getComponents();
1736                switch (content.length) {
1737                    case 0:
1738                        break;
1739                    case 1:
1740                        stack.add(content[0]);
1741                        lastIndex++;
1742                        break;
1743                    default:
1744                        stack.addAll(Arrays.asList(content));
1745                        lastIndex += content.length;
1746                        break;
1747                }
1748            }
1749        }
1750        //mouseBlocked.add(defaultButton);
1751
//mnemBlocked.add(defaultButton);
1752

1753        this.mouseBlocked = new Component JavaDoc[mouseBlocked.size()];
1754        if (mouseBlocked.size() != 0) {
1755            mouseBlocked.toArray(this.mouseBlocked);
1756        }
1757        this.mnemonicBlocked = new JComponent JavaDoc[mnemBlocked.size()];
1758        if (mnemBlocked.size() != 0) {
1759            mnemBlocked.toArray(this.mnemonicBlocked);
1760        }
1761    }
1762    
1763    /**
1764     */

1765    private void blockDefaultRootPaneAction() {
1766        assert (rootPane != null) && (defaultButton != null)
1767               && (rootPane.getDefaultButton() == defaultButton);
1768        
1769        final String JavaDoc actionKey1 = "press"; //NOI18N
1770
final String JavaDoc actionKey2 = "pressed"; //NOI18N
1771
String JavaDoc actionKey;
1772        
1773        ActionMap JavaDoc actionMap = rootPane.getActionMap();
1774        
1775        Action JavaDoc originalAction = actionMap.get(actionKey = actionKey1);
1776        if (originalAction == null) {
1777            originalAction = actionMap.get(actionKey = actionKey2);
1778        }
1779        assert originalAction != null;
1780        
1781        if (originalAction == null) {
1782            return;
1783        }
1784        
1785        actionMap.put(actionKey, new SelectSrcGrpAction(rootPane,
1786                                                        originalAction));
1787        rootPaneDefaultActionKey = actionKey;
1788        rootPaneDefaultAction = originalAction;
1789    }
1790    
1791    /**
1792     */

1793    private void unblockDefaultRootPaneAction() {
1794        assert rootPane != null;
1795        
1796        if (rootPaneDefaultAction == null) {
1797            
1798            /* blockDefaultRootPaneAction() did not pass */
1799            return;
1800        }
1801        
1802        rootPane.getActionMap().put(rootPaneDefaultActionKey,
1803                                    rootPaneDefaultAction);
1804        
1805        rootPaneDefaultActionKey = null;
1806        rootPaneDefaultAction = null;
1807    }
1808    
1809    /**
1810     * Modifies behaviour of the default button.
1811     */

1812    private void blockMnemonics() {
1813        assert rootPane != null;
1814        
1815        if (actionMappingInfo == null) {
1816            findActionMappings();
1817        }
1818        
1819        assert actionMappingInfo != null;
1820        assert actionMappingInfo.length == mnemonicBlocked.length;
1821        
1822        final JComponent JavaDoc[] comps = mnemonicBlocked;
1823        for (int i = 0; i < comps.length; i++) {
1824            ActionMappingInfo mappingInfo = actionMappingInfo[i];
1825            if (mappingInfo != null) {
1826                comps[i].getActionMap().put(
1827                        mappingInfo.actionKey,
1828                        new SelectSrcGrpAction(comps[i],
1829                                               mappingInfo.originalAction));
1830            } else if (comps[i] instanceof JLabel JavaDoc) {
1831                ActionMap JavaDoc map = new JLabelActionMap(comps[i]);
1832                map.setParent(comps[i].getActionMap());
1833                comps[i].setActionMap(map);
1834                continue;
1835            }
1836        }
1837    }
1838    
1839    /**
1840     */

1841    private void unblockMnemonics() {
1842        assert rootPane != null;
1843        
1844        if (actionMappingInfo == null) {
1845            
1846            /* blockMnemonics() did not pass */
1847            return;
1848        }
1849        
1850        assert actionMappingInfo.length == mnemonicBlocked.length;
1851        
1852        final JComponent JavaDoc[] comps = mnemonicBlocked;
1853        for (int i = 0; i < comps.length; i++) {
1854            ActionMappingInfo mappingInfo = actionMappingInfo[i];
1855            if (mappingInfo != null) {
1856                comps[i].getActionMap().put(
1857                        mappingInfo.actionKey,
1858                        mappingInfo.inProximateActionMap
1859                                ? mappingInfo.originalAction
1860                                : (Action JavaDoc) null);
1861            } else if (comps[i] instanceof JLabel JavaDoc) {
1862                comps[i].setActionMap(comps[i].getActionMap().getParent());
1863            }
1864        }
1865    }
1866    
1867    /**
1868     */

1869    private void findActionMappings() {
1870        assert mnemonicBlocked != null;
1871        
1872        final String JavaDoc actionKey1 = "pressed"; //NOI18N
1873
final String JavaDoc actionKey2 = "press"; //NOI18N
1874

1875        actionMappingInfo = new ActionMappingInfo[mnemonicBlocked.length];
1876        
1877        final JComponent JavaDoc[] comps = mnemonicBlocked;
1878        for (int i = 0; i < comps.length; i++) {
1879            JComponent JavaDoc c = comps[i];
1880            
1881            ActionMap JavaDoc actionMap = comps[i].getActionMap();
1882            
1883            String JavaDoc primaryKey = actionKey1;
1884            String JavaDoc secondaryKey = actionKey2;
1885            
1886            if (c instanceof JLabel JavaDoc) {
1887                actionMappingInfo[i] = null;
1888                continue;
1889            }
1890            
1891            String JavaDoc actionKey;
1892            Action JavaDoc originalAction = actionMap.get(actionKey = primaryKey);
1893            if (originalAction == null) {
1894                originalAction = actionMap.get(actionKey = secondaryKey);
1895            }
1896            if (originalAction == null) {
1897                ErrorManager.getDefault()
1898                .log(ErrorManager.EXCEPTION,
1899                     "JUnitWizard - Test for Existing Class: " //NOI18N
1900
+ "press action not found for a " //NOI18N
1901
+ c.getClass().getName() + " component"); //NOI18N
1902
actionMappingInfo[i] = null;
1903                continue;
1904            }
1905            
1906            ActionMappingInfo mappingInfo = new ActionMappingInfo();
1907            mappingInfo.actionKey = actionKey;
1908            mappingInfo.originalAction = originalAction;
1909            /*mappingInfo.inProximateActionMap = false;*/ //it's the default
1910

1911            /* find whether the mapping is defined in the proximate ActionMap */
1912            final String JavaDoc keyToFind = actionKey;
1913            final Object JavaDoc[] keys = actionMap.keys();
1914            if (keys != null) {
1915                for (int j = 0; j < keys.length; j++) {
1916                    if (keyToFind.equals(keys[j])) {
1917                        mappingInfo.inProximateActionMap = true;
1918                        break;
1919                    }
1920                }
1921            }
1922
1923            actionMappingInfo[i] = mappingInfo;
1924        }
1925    }
1926    
1927    /**
1928     * Contains information about <code>ActionMap</code> mapping
1929     * of a UI component.
1930     * There is one instance of this class per each JComponent
1931     * in the {@link #mnemonicBlocked} array.
1932     */

1933    private static class ActionMappingInfo {
1934        /** action key for action which activates the component */
1935        String JavaDoc actionKey;
1936        /** original action mapped to the actionKey */
1937        Action JavaDoc originalAction;
1938        /**
1939         * true if the mapping was defined in the component's
1940         * proximate ActionMap; false otherwise
1941         */

1942        boolean inProximateActionMap;
1943    }
1944    
1945    /**
1946     * <!-- PENDING -->
1947     */

1948    final class JLabelActionMap extends ActionMap JavaDoc {
1949        
1950        private final Component JavaDoc component;
1951        
1952        JLabelActionMap(Component JavaDoc comp) {
1953            super();
1954            this.component = comp;
1955        }
1956        
1957        public Action JavaDoc get(Object JavaDoc key) {
1958            if (key.equals("press")) { //NOI18N
1959
Action JavaDoc defaultAction = super.get(key);
1960                return (defaultAction != null)
1961                       ? new SelectSrcGrpAction(component, defaultAction)
1962                       : null;
1963            } else {
1964                return super.get(key);
1965            }
1966        }
1967        
1968    }
1969    
1970    /**
1971     * Sets up a glass pane - one part of the focus change detection mechanism.
1972     */

1973    private void blockMouseClicks() {
1974        assert rootPane != null;
1975
1976        final Component JavaDoc glassPane = rootPane.getGlassPane();
1977        
1978        if (glassPaneListener == null) {
1979            glassPaneListener = new GlassPaneListener();
1980        }
1981        glassPane.addMouseListener(glassPaneListener);
1982        glassPane.addMouseMotionListener(glassPaneListener);
1983        glassPane.setVisible(true);
1984    }
1985    
1986    /**
1987     * Cleans up a glass pane - one part of the focus change detection
1988     * mechanism.
1989     */

1990    private void unblockMouseClicks() {
1991        assert rootPane != null;
1992        
1993        if (glassPaneListener == null) {
1994            return;
1995        }
1996        
1997        final Component JavaDoc glassPane = rootPane.getGlassPane();
1998        
1999        glassPane.setVisible(false);
2000        glassPane.removeMouseMotionListener(glassPaneListener);
2001        glassPane.removeMouseListener(glassPaneListener);
2002    }
2003
2004    /**
2005     *
2006     */

2007    final class GlassPaneListener implements MouseInputListener JavaDoc {
2008        final Component JavaDoc glassPane = rootPane.getGlassPane();
2009        final Component JavaDoc layeredPane = rootPane.getLayeredPane();
2010        final Container JavaDoc contentPane = rootPane.getContentPane();
2011        
2012        public void mouseMoved(MouseEvent JavaDoc e) {
2013            redispatchEvent(e);
2014        }
2015        public void mouseDragged(MouseEvent JavaDoc e) {
2016            redispatchEvent(e);
2017        }
2018        public void mouseClicked(MouseEvent JavaDoc e) {
2019            redispatchEvent(e);
2020        }
2021        public void mouseEntered(MouseEvent JavaDoc e) {
2022            redispatchEvent(e);
2023        }
2024        public void mouseExited(MouseEvent JavaDoc e) {
2025            redispatchEvent(e);
2026        }
2027        public void mousePressed(MouseEvent JavaDoc e) {
2028            evaluateEvent(e);
2029        }
2030        public void mouseReleased(MouseEvent JavaDoc e) {
2031            redispatchEvent(e);
2032        }
2033        private void evaluateEvent(MouseEvent JavaDoc e) {
2034            assert multipleSourceRoots;
2035            
2036            Component JavaDoc component = getDeepestComponent(e);
2037            if (component == null) {
2038                return;
2039            }
2040
2041            boolean isBlocked = false;
2042            if (SwingUtilities.isLeftMouseButton(e)) {
2043                final Component JavaDoc[] blocked = mouseBlocked;
2044                for (int i = 0; i < blocked.length; i++) {
2045                    if (component == blocked[i]) {
2046                        isBlocked = true;
2047                        break;
2048                    }
2049                }
2050            }
2051            
2052            boolean askUserToChoose;
2053            SourceGroup[] candidates = null;
2054            if (!isBlocked || interactionRestrictionsSuspended) {
2055                askUserToChoose = false;
2056            } else if (component == defaultButton) {
2057                candidates = findParentGroupCandidates();
2058                askUserToChoose = (candidates.length > 1);
2059            } else if (!SwingUtilities.isDescendingFrom(component,
2060                                                        visualComp)) {
2061                askUserToChoose = false;
2062            } else {
2063                candidates = findParentGroupCandidates();
2064                askUserToChoose = (candidates.length > 1);
2065            }
2066            
2067            assert (askUserToChoose == false) || (candidates.length > 1);
2068            
2069            if (askUserToChoose) {
2070                SourceGroup srcGroup = chooseSrcGroup(candidates);
2071                if (srcGroup != null) {
2072                    setSelectedSrcGroup(srcGroup);
2073                    focusGainAllowedFor = component;
2074                    component.requestFocus();
2075                }
2076            } else {
2077                if (candidates != null) {
2078                    assert candidates.length == 1;
2079                    
2080                    setSelectedSrcGroup(candidates[0]);
2081                }
2082                focusGainAllowedFor = component;
2083                try {
2084                    redispatchEvent(e, component);
2085                } finally {
2086                    clearFocusGainAllowedVar();
2087                }
2088            }
2089        }
2090        private void redispatchEvent(MouseEvent JavaDoc e) {
2091            Component JavaDoc deepestComp = getDeepestComponent(e);
2092            if (deepestComp != null) {
2093                redispatchEvent(e, deepestComp);
2094            }
2095        }
2096        private void redispatchEvent(MouseEvent JavaDoc e, Component JavaDoc component) {
2097            Point JavaDoc componentPoint
2098                    = SwingUtilities.convertPoint(glassPane,
2099                                                  e.getPoint(),
2100                                                  component);
2101            component.dispatchEvent(
2102                    new MouseEvent JavaDoc(component,
2103                                   e.getID(),
2104                                   e.getWhen(),
2105                                   e.getModifiers(),
2106                                   componentPoint.x,
2107                                   componentPoint.y,
2108                                   e.getClickCount(),
2109                                   e.isPopupTrigger()));
2110        }
2111        private Component JavaDoc getDeepestComponent(MouseEvent JavaDoc e) {
2112            Point JavaDoc contentPanePoint
2113                    = SwingUtilities.convertPoint(glassPane,
2114                                                  e.getPoint(),
2115                                                  contentPane);
2116            return SwingUtilities.getDeepestComponentAt(
2117                            contentPane,
2118                            contentPanePoint.x,
2119                            contentPanePoint.y);
2120        }
2121    }
2122    
2123    /**
2124     * Action that is activated by a mnemonic keystroke.
2125     */

2126    private class SelectSrcGrpAction extends AbstractAction JavaDoc {
2127        private final Component JavaDoc component;
2128        private final Action JavaDoc delegate;
2129        public SelectSrcGrpAction(Component JavaDoc comp, Action JavaDoc delegate) {
2130            this.component = comp;
2131            this.delegate = delegate;
2132        }
2133        public void actionPerformed(ActionEvent JavaDoc e) {
2134            assert multipleSourceRoots;
2135            
2136            boolean askUserToChoose;
2137            SourceGroup[] candidates = null;
2138            if (interactionRestrictionsSuspended) {
2139                askUserToChoose = false;
2140            } else if ((component == defaultButton)
2141                       || (component == rootPane)) {
2142                candidates = findParentGroupCandidates();
2143                askUserToChoose = (candidates.length > 1);
2144            } else if (!SwingUtilities.isDescendingFrom(component,
2145                                                        visualComp)) {
2146                askUserToChoose = false;
2147            } else {
2148                candidates = findParentGroupCandidates();
2149                askUserToChoose = (candidates.length > 1);
2150            }
2151            
2152            assert (askUserToChoose == false) || (candidates.length > 1);
2153            
2154            if (askUserToChoose) {
2155                SourceGroup srcGroup = chooseSrcGroup(candidates);
2156                if (srcGroup != null) {
2157                    setSelectedSrcGroup(srcGroup);
2158                    if (component == rootPane) {
2159                        defaultButton.requestFocus();
2160                    } else {
2161                        component.requestFocus();
2162                    }
2163                }
2164            } else {
2165                if (candidates != null) {
2166                    assert candidates.length == 1;
2167                    
2168                    setSelectedSrcGroup(candidates[0]);
2169                }
2170                redispatchEvent(e);
2171            }
2172        }
2173        private void redispatchEvent(ActionEvent JavaDoc e) {
2174            focusGainAllowedFor = component;
2175            try {
2176                delegate.actionPerformed(e);
2177            } finally {
2178                clearFocusGainAllowedVar();
2179            }
2180        }
2181        public boolean isEnabled() {
2182            return delegate.isEnabled();
2183        }
2184    }
2185    
2186    /**
2187     * <!-- PENDING -->
2188     */

2189    private class ClsNameDocumentFilter extends DocumentFilter JavaDoc {
2190        public ClsNameDocumentFilter () {}
2191        
2192        public void replace(DocumentFilter.FilterBypass JavaDoc bypass,
2193                            int offset,
2194                            int length,
2195                            String JavaDoc text,
2196                            AttributeSet JavaDoc attrs) throws BadLocationException JavaDoc {
2197            if (!programmaticChange && srcGroupNameDisplayed) {
2198                removeSrcGroupName(bypass);
2199            }
2200            super.replace(bypass, offset, length, text, attrs);
2201        }
2202        public void insertString(
2203                            DocumentFilter.FilterBypass JavaDoc bypass,
2204                            int offset,
2205                            String JavaDoc string,
2206                            AttributeSet JavaDoc attr) throws BadLocationException JavaDoc {
2207            if (!programmaticChange && srcGroupNameDisplayed) {
2208                removeSrcGroupName(bypass);
2209            }
2210            super.insertString(bypass, offset, string, attr);
2211        }
2212        public void remove(DocumentFilter.FilterBypass JavaDoc bypass,
2213                           int offset,
2214                           int length) throws BadLocationException JavaDoc {
2215            if (!programmaticChange && srcGroupNameDisplayed) {
2216                removeSrcGroupName(bypass);
2217            }
2218            super.remove(bypass, offset, length);
2219        }
2220        private void removeSrcGroupName(DocumentFilter.FilterBypass JavaDoc bypass)
2221                                                throws BadLocationException JavaDoc {
2222            bypass.remove(classNameLength,
2223                          tfClassToTest.getText().length() - classNameLength);
2224            srcGroupNameDisplayed = false;
2225            setNavigationFilterEnabled(false);
2226        }
2227    }
2228    
2229    /**
2230     * <!-- PENDING -->
2231     */

2232    private class ClsNameNavigationFilter extends NavigationFilter JavaDoc {
2233        public ClsNameNavigationFilter () {}
2234        
2235        public void setDot(NavigationFilter.FilterBypass JavaDoc bypass,
2236                           int dot,
2237                           Position.Bias JavaDoc bias) {
2238            if (dot > classNameLength) {
2239                bypass.setDot(classNameLength, bias);
2240            } else {
2241                super.setDot(bypass, dot, bias);
2242            }
2243        }
2244        public void moveDot(NavigationFilter.FilterBypass JavaDoc bypass,
2245                           int dot,
2246                           Position.Bias JavaDoc bias) {
2247            if (dot > classNameLength) {
2248                bypass.moveDot(classNameLength, bias);
2249            } else {
2250                super.moveDot(bypass, dot, bias);
2251            }
2252        }
2253        public void ensureCursorInRange() {
2254            if (srcGroupNameDisplayed) {
2255                if (tfClassToTest.getCaretPosition() > classNameLength) {
2256                    tfClassToTest.setCaretPosition(classNameLength);
2257                }
2258            }
2259        }
2260    }
2261    
2262    /**
2263     * Sends a request to clear the {@link #focusGainAllowedFor} variable
2264     * to the end of the event queue.
2265     */

2266    private void clearFocusGainAllowedVar() {
2267        SwingUtilities.invokeLater(new Runnable JavaDoc() {
2268            public void run() {
2269                focusGainAllowedFor = null;
2270            }
2271        });
2272    }
2273    
2274    /**
2275     */

2276    private static boolean checkObjChanged(Object JavaDoc oldObj, Object JavaDoc newObj) {
2277        return ((oldObj != null) || (newObj != null))
2278               && ((oldObj == null) || !oldObj.equals(newObj));
2279    }
2280    
2281    /* *
2282     * /
2283    private static void printCallstack(String header) {
2284        
2285        //PENDING - this method is not needed in the final version
2286        
2287        if (header != null) {
2288            System.out.println(header);
2289        }
2290
2291        StackTraceElement[] frames = new Exception().getStackTrace();
2292        int count = Math.min(5, frames.length);
2293        for (int i = 1; i < frames.length; i++) {
2294            String methodName = frames[i].getMethodName();
2295            if (!methodName.startsWith("access$")) {
2296                System.out.println(" " + methodName + "(...)");
2297                if (--count == 0) {
2298                    break;
2299                }
2300            }
2301        }
2302        System.out.println();
2303    }
2304     */

2305    
2306}
2307
Popular Tags