KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > core > NbMainExplorer


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

19
20 package org.netbeans.core;
21
22 import java.awt.*;
23 import java.beans.*;
24 import java.io.ObjectInput JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.util.*;
27 import java.util.List JavaDoc;
28 import java.util.logging.Level JavaDoc;
29 import java.util.logging.Logger JavaDoc;
30 import java.util.prefs.PreferenceChangeEvent JavaDoc;
31 import java.util.prefs.PreferenceChangeListener JavaDoc;
32
33 import javax.swing.*;
34 import javax.swing.event.*;
35 import org.openide.explorer.*;
36 import org.openide.explorer.view.BeanTreeView;
37 import org.openide.explorer.view.TreeView;
38 import org.openide.nodes.Node;
39 import org.openide.nodes.NodeListener;
40 import org.openide.util.Exceptions;
41 import org.openide.util.HelpCtx;
42 import org.openide.util.NbBundle;
43 import org.openide.util.Mutex;
44 import org.openide.util.WeakListeners;
45 import org.openide.windows.CloneableTopComponent;
46 import org.openide.windows.Mode;
47 import org.openide.windows.TopComponent;
48 import org.openide.windows.WindowManager;
49
50 /** Main explorer - the class remains here for backward compatibility
51 * with older serialization protocol. Its responsibilty is also
52 * to listen to the changes of "roots" nodes and open / close
53 * explorer's top components properly.
54 *
55 * @author Ian Formanek, David Simonek, Jaroslav Tulach
56 */

57 public final class NbMainExplorer extends CloneableTopComponent {
58
59     static final long serialVersionUID=6021472310669753679L;
60     // static final long serialVersionUID=-9070275145808944151L;
61

62     /** holds list of roots (Node) */
63     private List JavaDoc<Node> prevRoots;
64
65     /** assignes to each node one top component holding explorer panel
66     * (Node, ExplorerTab) */

67     private Map<Node, ExplorerTab> rootsToTCs;
68
69     /** Listener which tracks changes on the root nodes (which are displayed as tabs) */
70     private transient RootsListener rootsListener;
71
72     /** Minimal initial height of this top component */
73     public static final int MIN_HEIGHT = 150;
74     /** Default width of main explorer */
75     public static final int DEFAULT_WIDTH = 350;
76     
77     /** Mapping module tabs to their root node classes */
78     private static Map<Node, ModuleTab> moduleTabs;
79
80     /** Default constructor */
81     public NbMainExplorer () {
82 // System.out.println("NbMainExplorer.<init>");
83
// listening on changes of roots
84
rootsListener = new RootsListener();
85         NbPlaces p = NbPlaces.getDefault();
86         p.addChangeListener(WeakListeners.change (rootsListener, p));
87
88         refreshRoots();
89     }
90
91     public HelpCtx getHelpCtx () {
92         return ExplorerUtils.getHelpCtx (getActivatedNodes (),
93                                          new HelpCtx (NbMainExplorer.class));
94     }
95     
96     /** Finds module tab in mapping of module tabs to their root node classes.
97      * If it is not found it is added when parameter tc is not null. When parameter
98      * tc is null new ModuleTab is created using default constructor. */

99     private static synchronized ModuleTab findModuleTab (Node root, ModuleTab tc) {
100     System.out.println("NbMainExplorer.findModuleTab "+root);
101         if (moduleTabs == null) {
102             moduleTabs = new WeakHashMap<Node, ModuleTab>(5);
103         }
104         ModuleTab tab = moduleTabs.get(root);
105         if (tab != null) {
106             return tab;
107         } else {
108             if (tc != null) {
109                 moduleTabs.put(root, tc);
110                 return tc;
111             } else {
112                 ModuleTab newTC = new ModuleTab();
113                 moduleTabs.put(root, newTC);
114                 return newTC;
115             }
116         }
117     }
118     
119     /** Overriden to open all top components of main explorer and
120     * close this top component, as this top component exists only because of
121     * backward serialization compatibility.
122     * Performed with delay, when WS is in consistent state. */

123     @SuppressWarnings JavaDoc("deprecation")
124     public void open (org.openide.windows.Workspace workspace) {
125         doOpen(workspace);
126     }
127
128     @SuppressWarnings JavaDoc("deprecation")
129     private void doOpen(org.openide.windows.Workspace workspace) {
130         if (workspace == null) {
131             // refresh roots request
132
refreshRoots ();
133         } else {
134             // old explorer open request
135
super.open(workspace);
136             close(workspace);
137             // now open new main explorer top components
138
NbMainExplorer singleton = NbMainExplorer.getExplorer();
139             singleton.openRoots(workspace);
140         }
141     }
142
143     /** Open all main explorer's top components on current workspace */
144     @SuppressWarnings JavaDoc("deprecation")
145     public void openRoots () {
146         openRoots(WindowManager.getDefault().getCurrentWorkspace());
147     }
148
149     /** Open all main explorer's top components on given workspace */
150     @SuppressWarnings JavaDoc("deprecation")
151     public void openRoots (org.openide.windows.Workspace workspace) {
152         // save the tab we should activate
153
ExplorerTab toBeActivated = MainTab.lastActivated;
154         // perform open operation
155
refreshRoots();
156         Node[] rootsArray = getRoots().toArray(new Node[0]);
157         TopComponent tc = null;
158         for (int i = 0; i < rootsArray.length; i++) {
159             tc = getRootPanel(rootsArray[i]);
160             if (tc != null) {
161                 tc.open(workspace);
162             }
163         }
164         // set focus to saved last activated tab or repository tab
165
if (toBeActivated == null) {
166             toBeActivated = getRootPanel(rootsArray[0]);
167         }
168         
169         //Bugfix #9352 20 Feb 2001 by Marek Slama
170
//requestFocus called directly on mode - it sets
171
//deferred request so that requestFocus is performed
172
//on correct workspace when component is shown.
173
//Delayed call of requestFocus on ExplorerTab
174
//was performed on incorrect workspace.
175
/*final ExplorerTab localActivated = toBeActivated;
176         SwingUtilities.invokeLater(new Runnable () {
177                                        public void run () {
178         System.out.println("++*** localActivated:" + localActivated);
179                                            if (localActivated != null) {
180         System.out.println("++*** Call of localActivated.requestFocus()");
181                                                localActivated.requestFocus();
182                                            }
183                                        }
184                                    });*/

185         
186         //Bugfix #9815: added check if toBeActivated is null before
187
//request focus is called.
188
//Bugfix #17956: Make sure that findMode is called after top component
189
//is added to mode.
190
if (SwingUtilities.isEventDispatchThread()) {
191             if (toBeActivated != null) {
192                 Mode mode = workspace.findMode(toBeActivated);
193                 if (mode != null) {
194                     toBeActivated.requestActive();
195                 }
196             }
197         } else {
198             if (toBeActivated != null) {
199                 final ExplorerTab localActivated = toBeActivated;
200                 final org.openide.windows.Workspace localWorkspace = workspace;
201                 SwingUtilities.invokeLater(new Runnable JavaDoc () {
202                     public void run () {
203                         Mode mode = localWorkspace.findMode(localActivated);
204                         if (mode != null) {
205                             localActivated.requestActive();
206                         }
207                     }
208                 });
209             }
210         }
211         //End of bugfix #9815
212
//End of bugfix #9352
213
}
214
215     /** Refreshes current state of main explorer's top components, so they
216     * will reflect new nodes. Called when content of "roots" nodes is changed.
217     */

218     @SuppressWarnings JavaDoc("deprecation") final void refreshRoots () {
219         List JavaDoc<Node> curRoots = getRoots ();
220         // first of all we have to close top components for
221
// the roots that are no longer present in the roots content
222
if (prevRoots != null) {
223             HashSet<Node> toRemove = new HashSet<Node>(prevRoots);
224             toRemove.removeAll(curRoots);
225             // ^^^ toRemove now contains only roots that are used no more
226
for (Map.Entry<Node, ExplorerTab> me: rootsToTCs.entrySet()) {
227                 Node r = me.getKey();
228                 if (toRemove.contains(r)) {
229                     // close top component asociated with this root context
230
// on all workspaces
231
closeEverywhere(me.getValue());
232                 }
233             }
234         } else {
235             // initialize previous roots list
236
prevRoots();
237         }
238
239         // create and open top components for newly added roots
240
List JavaDoc workspaces = whereOpened(
241                               rootsToTCs().values().toArray(new ExplorerTab[0])
242                           );
243         for (Iterator iter = curRoots.iterator(); iter.hasNext(); ) {
244             Node r = (Node)iter.next();
245             ExplorerTab tc = getRootPanel(r);
246             if (tc == null) {
247                 // newly added root -> create new TC and open it on every
248
// workspace where some top compoents from main explorer
249
// are already opened
250
tc = createTC(r, false);
251                 
252                 for (Iterator iter2 = workspaces.iterator(); iter2.hasNext(); ) {
253                     tc.open((org.openide.windows.Workspace)iter2.next());
254                 }
255             }
256         }
257
258         // save roots for use during future changes
259
prevRoots = curRoots;
260     }
261
262     /** Helper method - closes given top component on all workspaces
263     * where it is opened */

264     @SuppressWarnings JavaDoc("deprecation")
265     private static void closeEverywhere (TopComponent tc) {
266         org.openide.windows.Workspace[] workspaces = WindowManager.getDefault().getWorkspaces();
267         for (int i = 0; i < workspaces.length; i++) {
268             if (tc.isOpened(workspaces[i])) {
269                 tc.close(workspaces[i]);
270             }
271         }
272     }
273
274     /** Utility method - returns list of workspaces where at least one from
275     * given list of top components is opened. */

276     @SuppressWarnings JavaDoc("deprecation")
277     private static List JavaDoc<org.openide.windows.Workspace> whereOpened (TopComponent[] tcs) {
278         org.openide.windows.Workspace[] workspaces = WindowManager.getDefault().getWorkspaces();
279         ArrayList<org.openide.windows.Workspace> result = new ArrayList<org.openide.windows.Workspace>(workspaces.length);
280         for (int i = 0; i < workspaces.length; i++) {
281             for (int j = 0; j < tcs.length; j++) {
282                 if (tcs[j].isOpened(workspaces[i])) {
283                     result.add(workspaces[i]);
284                     break;
285                 }
286             }
287         }
288         return result;
289     }
290
291     //Temporary solution for bugfix #9352. There is currently
292
//no way how to select given tab other than focused in split container.
293
//It requires better solution.
294
//Method changed from private to public so it can be used in DefaultCreator.
295

296     /** @return List of "root" nodes which has following structure:<br>
297     * First goes repository, than root nodes added by modules and at last
298     * runtime root node */

299     public static List JavaDoc<Node> getRoots () {
300         NbPlaces places = NbPlaces.getDefault();
301         // build the list of roots
302
LinkedList<Node> result = new LinkedList<Node>();
303   
304         //repository goes first
305
/*
306         #47032: Netbeans hangs for 30 seconds during startup - so commented out
307         Moreover there isn't any ExlorerTab dedicated to show this repository root.
308         result.add(RepositoryNodeFactory.getDefault().repository(DataFilter.ALL));
309 */

310         
311         // roots added by modules (javadoc etc...)
312
result.addAll(Arrays.asList(places.roots()));
313         // runtime
314
result.add(places.environment());
315
316         return result;
317     }
318
319     /** Creates a top component dedicated to exploration of
320     * specified node, which will serve as root context */

321     private ExplorerTab createTC (Node rc, boolean deserialize) {
322         // switch according to the type of the root context
323
MainTab panel = null;
324         NbPlaces places = NbPlaces.getDefault();
325
326         if (rc.equals(places.environment())) {
327             // default tabs
328
if (deserialize) {
329                 TopComponent tc = WindowManager.getDefault().findTopComponent("runtime"); // NOI18N
330
if (tc != null) {
331                     if (tc instanceof MainTab) {
332                         panel = (MainTab) tc;
333                     } else {
334                         //Incorrect settings file?
335
IllegalStateException JavaDoc exc = new IllegalStateException JavaDoc
336                         ("Incorrect settings file. Unexpected class returned." // NOI18N
337
+ " Expected:" + MainTab.class.getName() // NOI18N
338
+ " Returned:" + tc.getClass().getName()); // NOI18N
339
Logger.getLogger(NbMainExplorer.class.getName()).log(Level.WARNING, null, exc);
340                         panel = MainTab.getDefaultMainTab();
341                     }
342                 } else {
343                     panel = MainTab.getDefaultMainTab();
344                 }
345             } else {
346                 panel = MainTab.getDefaultMainTab();
347             }
348             panel.setRootContext(rc, false);
349         } else {
350             // tabs added by modules
351
//We cannot use findTopComponent here because we do not know unique
352
//TC ID ie. proper deserialization of such TC will not work.
353
panel = NbMainExplorer.findModuleTab(rc, null);
354             panel.setRootContext(rc);
355         }
356         
357         
358         rootsToTCs().put(rc, panel);
359         return panel;
360     }
361
362     /** Safe accessor for root context - top component map. */
363     private Map<Node,ExplorerTab> rootsToTCs () {
364         if (rootsToTCs == null) {
365             rootsToTCs = new HashMap<Node,ExplorerTab>(7);
366         }
367         return rootsToTCs;
368     }
369
370     /** Safe accessor for list of previous root nodes */
371     private List JavaDoc<Node> prevRoots () {
372         if (prevRoots == null) {
373             prevRoots = new LinkedList<Node>();
374         }
375         return prevRoots;
376     }
377
378     /** Deserialize this top component, sets as default.
379     * Provided provided here only for backward compatibility
380     * with older serialization protocol */

381     public void readExternal (ObjectInput JavaDoc in)
382     throws IOException JavaDoc, ClassNotFoundException JavaDoc {
383         super.readExternal(in);
384         //System.out.println("READING old main explorer..."); // NOI18N
385
// read explorer panels (and managers)
386
int cnt = in.readInt ();
387         for (int i = 0; i < cnt; i++) {
388             in.readObject();
389         }
390         in.readObject();
391         // read property sheet switcher state...
392
in.readBoolean ();
393         in.readBoolean ();
394         in.readInt();
395         in.readInt();
396     }
397
398     //Temporary solution for bugfix #9352. There is currently
399
//no way how to select given tab other than focused in split container.
400
//It requires better solution.
401
//Method changed from package to public so it can be used in DefaultCreator.
402

403     /** Finds the right panel for given node.
404     * @return the panel or null if no such panel exists
405     */

406     public final ExplorerTab getRootPanel (Node root) {
407         return rootsToTCs().get(root);
408     }
409
410
411     // -------------------------------------------------------------------------
412
// Static methods
413

414     /** Static method to obtains the shared instance of NbMainExplorer
415     * @return the shared instance of NbMainExplorer
416     */

417     public static NbMainExplorer getExplorer () {
418         if (explorer == null) {
419             explorer = new NbMainExplorer ();
420         }
421         return explorer;
422     }
423
424     /** @return The mode for main explorer on given workspace.
425     * Creates explorer mode if no such mode exists on given workspace */

426     @SuppressWarnings JavaDoc("deprecation")
427     private static Mode explorerMode (org.openide.windows.Workspace workspace) {
428         Mode result = workspace.findMode("explorer"); // NOI18N
429
if (result == null) {
430             // create explorer mode on current workspace
431
String JavaDoc displayName = NbBundle.getBundle(NbMainExplorer.class).
432                                  getString("CTL_ExplorerTitle");
433             result = workspace.createMode(
434                          "explorer", // NOI18N
435
displayName,
436                          NbMainExplorer.class.getResource(
437                              "/org/netbeans/core/resources/frames/explorer.gif" // NOI18N
438
)
439                      );
440         }
441         return result;
442     }
443
444     /** Shared instance of NbMainExplorer */
445     private static NbMainExplorer explorer;
446
447
448     /** Common explorer top component which composites bean tree view
449     * to view given context. */

450     public static class ExplorerTab extends org.netbeans.beaninfo.ExplorerPanel
451         implements /*DeferredPerformer.DeferredCommand,*/ TopComponent.Cloneable {
452         static final long serialVersionUID =-8202452314155464024L;
453         /** composited view */
454         protected TreeView view;
455         /** listeners to the root context and IDE settings */
456         private PropertyChangeListener weakRcL;
457         private NodeListener weakNRcL;
458         private IDESettings ideSettings;
459
460         private NodeListener rcListener;
461         /** validity flag */
462         private boolean valid = true;
463         private boolean rootVis = true;
464         
465         /** Used by ModuleTab to set persistence type according
466          * root context node persistence ability. */

467         protected int persistenceType = TopComponent.PERSISTENCE_ALWAYS;
468         
469         public ExplorerTab () {
470             super();
471             // complete initialization of composited explorer actions
472
ideSettings = IDESettings.getInstance();
473             
474             getActionMap().put("delete", ExplorerUtils.actionDelete(getExplorerManager(), ideSettings.getConfirmDelete ()));
475             
476             IDESettings.getPreferences().addPreferenceChangeListener(new PreferenceChangeListener JavaDoc() {
477                 public void preferenceChange(PreferenceChangeEvent JavaDoc evt) {
478                     if (IDESettings.PROP_CONFIRM_DELETE.equals(evt.getKey())) {
479                         getActionMap().put("delete", ExplorerUtils.actionDelete(getExplorerManager(), ideSettings.getConfirmDelete ()));
480                     }
481                 }
482             });
483         }
484         
485         /** Overriden to explicitely set persistence type of ExplorerTab
486          * to PERSISTENCE_ALWAYS
487          */

488         public int getPersistenceType() {
489             return TopComponent.PERSISTENCE_ALWAYS;
490         }
491
492         /** Initialize visual content of component */
493         protected void componentShowing () {
494             super.componentShowing ();
495             
496             if (view == null) {
497                 view = initGui ();
498                 view.setRootVisible(rootVis);
499                 
500                 view.getAccessibleContext().setAccessibleName(NbBundle.getBundle(NbMainExplorer.class).getString("ACSN_ExplorerBeanTree"));
501                 view.getAccessibleContext().setAccessibleDescription(NbBundle.getBundle(NbMainExplorer.class).getString("ACSD_ExplorerBeanTree"));
502             }
503         }
504
505         /** Performs superclass addNotify code, then delegates to
506          * componentShowing if component is used outside window system.
507          * Needed for proper initialization.
508          */

509         public void addNotify () {
510             super.addNotify();
511             if (WindowManager.getDefault().findMode(this) != null) {
512                 return;
513             }
514             componentShowing();
515         }
516         
517         /** Transfer focus to view. */
518         @SuppressWarnings JavaDoc("deprecation") public void requestFocus () {
519             super.requestFocus();
520             if (view != null) {
521                 view.requestFocus();
522             }
523         }
524         
525         /** Transfer focus to view. */
526         @SuppressWarnings JavaDoc("deprecation") public boolean requestFocusInWindow () {
527             super.requestFocusInWindow();
528             if (view != null) {
529                 return view.requestFocusInWindow();
530             } else {
531                 return false;
532             }
533         }
534         
535         /** Initializes gui of this component. Subclasses can override
536         * this method to install their own gui.
537         * @return Tree view that will serve as main view for this explorer.
538         */

539         protected TreeView initGui () {
540             TreeView view = new BeanTreeView();
541             view.setDragSource (true);
542             setLayout(new BorderLayout());
543             add (view);
544             return view;
545         }
546
547         /** Ensures that component is valid before opening */
548         @SuppressWarnings JavaDoc("deprecation") public void open (org.openide.windows.Workspace workspace) {
549             setValidRootContext();
550             
551             super.open(workspace);
552         }
553
554         /** Sets new root context to view. Name, icon, tooltip
555         * of this top component will be updated properly */

556         public void setRootContext (Node rc) {
557             Node oldRC = getExplorerManager().getRootContext();
558             // remove old listener, if possible
559
if (weakRcL != null) {
560                 oldRC.removePropertyChangeListener(weakRcL);
561             }
562             if (weakNRcL != null) {
563                 oldRC.removeNodeListener(weakNRcL);
564             }
565             getExplorerManager().setRootContext(rc);
566             initializeWithRootContext(rc);
567         }
568         
569         public void setRootContext(Node rc, boolean rootVisible) {
570             rootVis = rootVisible;
571             if (view != null) {
572                 view.setRootVisible(rootVisible);
573             }
574             setRootContext(rc);
575         }
576
577         // #16375. Not to try to serialize explored nodes which aren't
578
// serializable (getHandle returns null).
579
/** Adjusts this component persistence according
580          * root context node persistence ability. */

581         public void adjustComponentPersistence() {
582             Node.Handle handle = getExplorerManager().getRootContext().getHandle();
583             if(handle == null) {
584                 // Not persistent.
585
persistenceType = TopComponent.PERSISTENCE_NEVER;
586             } else {
587                 // Persistent.
588
persistenceType = TopComponent.PERSISTENCE_ONLY_OPENED;
589             }
590         }
591
592         public Node getRootContext () {
593             return getExplorerManager().getRootContext();
594         }
595         
596         /** Deserialization of ExploreTab, if subclass overwrites this method it
597             MUST call scheduleValidation() */

598         public Object JavaDoc readResolve() throws java.io.ObjectStreamException JavaDoc {
599             // put a request for later validation
600
// we must do this here, because of ExplorerManager's deserialization.
601
// Root context of ExplorerManager is validated AFTER all other
602
// deserialization, so we must wait for it
603
//Bugfix #17622, call of scheduleValidation() moved from
604
//readExternal().
605
scheduleValidation();
606             return this;
607         }
608
609         private void setValidRootContext() {
610             if (!valid) {
611                 valid = true;
612                 validateRootContext();
613             }
614         }
615
616         /** Validates root context of this top component after deserialization.
617         * It is guaranteed that this method is called at a time when
618         * getExplorerManager().getRootContext() call will return valid result.
619         * Subclasses can override this method and peform further validation
620         * or even set new root context instead of deserialized one.<br>
621         * Default implementation just initializes top component with standard
622         * deserialized root context. */

623         protected void validateRootContext () {
624             initializeWithRootContext(getExplorerManager().getRootContext());
625         }
626
627         // Bugfix #5891 04 Sep 2001 by Jiri Rechtacek
628
// the title is derived from the root context
629
// it isn't changed by a selected node in the tree
630
/** Called when the explored context changes.
631         * Overriden - we don't want title to change in this style.
632         */

633         protected void updateTitle () {
634             // set name by the root context
635
setName(getExplorerManager ().getRootContext().getDisplayName());
636         }
637
638         private NodeListener rcListener () {
639             if (rcListener == null) {
640                 rcListener = new RootContextListener();
641             }
642             return rcListener;
643         }
644
645         /** Initialize this top component properly with information
646         * obtained from specified root context node */

647         private void initializeWithRootContext (Node rc) {
648             // update TC's attributes
649
setIcon(rc.getIcon(BeanInfo.ICON_COLOR_16x16));
650             setToolTipText(rc.getShortDescription());
651             // bugfix #15136
652
setName(rc.getDisplayName());
653             updateTitle();
654
655             if (weakRcL == null) {
656                 weakRcL = WeakListeners.propertyChange(rcListener(), rc);
657             }
658             else {
659                 rc.removePropertyChangeListener(weakRcL);
660             }
661             rc.addPropertyChangeListener(weakRcL);
662             
663             if (weakNRcL == null) {
664                 weakNRcL = org.openide.nodes.NodeOp.weakNodeListener (rcListener(), rc);
665             }
666             else {
667                 rc.removeNodeListener(weakNRcL);
668             }
669             rc.addNodeListener(weakNRcL);
670         }
671         
672         // put a request for later validation
673
// we must do this here, because of ExplorerManager's deserialization.
674
// Root context of ExplorerManager is validated AFTER all other
675
// deserialization, so we must wait for it
676
protected final void scheduleValidation() {
677             valid = false;
678             setValidRootContext();
679         }
680         
681         /* Updated accessible name of the tree view */
682         public void setName(String JavaDoc name) {
683             super.setName(name);
684             if (view != null) {
685                 view.getAccessibleContext().setAccessibleName(name);
686             }
687         }
688         
689         /* Updated accessible description of the tree view */
690         public void setToolTipText(String JavaDoc text) {
691             super.setToolTipText(text);
692             if (view != null) {
693                 view.getAccessibleContext().setAccessibleDescription(text);
694             }
695         }
696
697         public TopComponent cloneComponent() {
698             ExplorerTab nue = new ExplorerTab();
699             nue.getExplorerManager().setRootContext(getExplorerManager().getRootContext());
700             try {
701                 nue.getExplorerManager().setSelectedNodes(getExplorerManager().getSelectedNodes());
702             } catch (PropertyVetoException pve) {
703                 Exceptions.printStackTrace(pve);
704             }
705             return nue;
706         }
707         
708         /** Multi - purpose listener, listens to: <br>
709         * 1) Changes of name, icon, short description of root context.
710         * 2) Changes of IDE settings, namely delete confirmation settings */

711         private final class RootContextListener extends Object JavaDoc implements NodeListener {
712             
713             RootContextListener() {}
714             
715             public void propertyChange (PropertyChangeEvent evt) {
716                 String JavaDoc propName = evt.getPropertyName();
717                 Object JavaDoc source = evt.getSource();
718                 // root context node change
719
final Node n = (Node)source;
720                 if (Node.PROP_DISPLAY_NAME.equals(propName) ||
721                         Node.PROP_NAME.equals(propName)) {
722                     // Fix #39275 start - posted to awt thread.
723
Mutex.EVENT.readAccess(new Runnable JavaDoc() {
724                             public void run() {
725                                 setName(n.getDisplayName());
726                             }
727                         });
728                     // fix #39275 end
729
} else if (Node.PROP_ICON.equals(propName)) {
730                     // Fix #39275 start - posted to awt thread.
731
Mutex.EVENT.readAccess(new Runnable JavaDoc() {
732                             public void run() {
733                                 setIcon(n.getIcon(BeanInfo.ICON_COLOR_16x16));
734                             }
735                         });
736                     // fix #39275 end
737
} else if (Node.PROP_SHORT_DESCRIPTION.equals(propName)) {
738                     setToolTipText(n.getShortDescription());
739                 }
740             }
741             
742             @SuppressWarnings JavaDoc("deprecation") public void nodeDestroyed(org.openide.nodes.NodeEvent nodeEvent) {
743                 ExplorerTab.this.setCloseOperation(TopComponent.CLOSE_EACH);
744                 ExplorerTab.this.close();
745             }
746             
747             public void childrenRemoved(org.openide.nodes.NodeMemberEvent e) {}
748             public void childrenReordered(org.openide.nodes.NodeReorderEvent e) {}
749             public void childrenAdded(org.openide.nodes.NodeMemberEvent e) {}
750             
751         } // end of RootContextListener inner class
752

753     } // end of ExplorerTab inner class
754

755     /** Tab of main explorer. Tries to dock itself to main explorer mode
756     * before opening, if it's not docked already.
757     * Also deserialization is enhanced in contrast to superclass */

758     public static class MainTab extends ExplorerTab {
759         static final long serialVersionUID =4233454980309064344L;
760
761         /** Holds main tab which was last activated.
762         * Used during decision which tab should receive focus
763         * when opening all tabs at once using NbMainExplorer.openRoots()
764         */

765         private static MainTab lastActivated;
766         
767         private static MainTab DEFAULT;
768
769         public static synchronized MainTab getDefaultMainTab() {
770             if (DEFAULT == null) {
771                 DEFAULT = new MainTab();
772                 // put a request for later validation
773
// we must do this here, because of ExplorerManager's deserialization.
774
// Root context of ExplorerManager is validated AFTER all other
775
// deserialization, so we must wait for it
776
DEFAULT.scheduleValidation();
777             }
778             
779             return DEFAULT;
780         }
781         
782         /** Creator/accessor method of Runtime tab singleton. Instance is properly
783          * deserialized by winsys.
784          */

785         public static MainTab findEnvironmentTab () {
786             return (MainTab)getExplorer().createTC(
787                 NbPlaces.getDefault().environment(), true
788             );
789         }
790         
791         /** Creator/accessor method used ONLY by winsys for first time instantiation
792          * of Runtime tab. Use <code>findEnvironmentTab</code> to properly deserialize
793          * singleton instance.
794          */

795         public static MainTab createEnvironmentTab () {
796             return (MainTab)getExplorer().createTC(
797             NbPlaces.getDefault().environment(), false
798             );
799         }
800         
801         /** Overriden to explicitely set persistence type of MainTab
802          * to PERSISTENCE_ALWAYS */

803         public int getPersistenceType() {
804             return TopComponent.PERSISTENCE_ALWAYS;
805         }
806         
807         protected String JavaDoc preferredID () {
808             return "runtime"; //NOI18N
809
}
810         
811         public HelpCtx getHelpCtx () {
812             return ExplorerUtils.getHelpCtx (getExplorerManager ().getSelectedNodes (),
813                     new HelpCtx (EnvironmentNode.class));
814     }
815
816         /** Deserialization of RepositoryTab */
817         public Object JavaDoc readResolve() throws java.io.ObjectStreamException JavaDoc {
818             if (DEFAULT == null) {
819                 DEFAULT = this;
820             }
821             getDefaultMainTab().scheduleValidation();
822             return getDefaultMainTab();
823         }
824         
825         @SuppressWarnings JavaDoc("deprecation") public void open (org.openide.windows.Workspace workspace) {
826             org.openide.windows.Workspace realWorkspace = (workspace == null)
827                                       ? WindowManager.getDefault().getCurrentWorkspace()
828                                       : workspace;
829             Mode ourMode = realWorkspace.findMode(this);
830             if (ourMode == null) {
831                 explorerMode(realWorkspace).dockInto(this);
832             }
833             super.open(workspace);
834         }
835
836         /** Called when the explored context changes.
837         * Overriden - we don't want title to chnage in this style.
838         */

839         protected void updateTitle () {
840             // empty to keep the title unchanged
841
}
842
843         /** Overrides superclass' version, remembers last activated
844         * main tab */

845         protected void componentActivated () {
846             super.componentActivated();
847             lastActivated = this;
848         }
849
850         /** Registers root context in main explorer in addition to superclass'
851         * version */

852         protected void validateRootContext () {
853             super.validateRootContext();
854             registerRootContext(getExplorerManager().getRootContext());
855         }
856
857         /* Add given root context and this top component
858         * to the map of main explorer's top components and nodes */

859         protected void registerRootContext (Node rc) {
860             NbMainExplorer explorer = NbMainExplorer.getExplorer();
861             explorer.prevRoots().add(rc);
862             explorer.rootsToTCs().put(rc, this);
863         }
864
865     } // end of MainTab inner class
866

867     /** Special class for tabs added by modules to the main explorer */
868     public static class ModuleTab extends MainTab {
869         static final long serialVersionUID =8089827754534653731L;
870         
871         public ModuleTab() {
872 // System.out.println("NbMainExplorer.ModuleTab");
873
}
874                 
875         
876         public void setRootContext(Node root) {
877             super.setRootContext(root);
878             adjustComponentPersistence();
879         }
880         
881         /** Overriden to explicitely set persistence type of ModuleTab
882          * to selected type */

883         public int getPersistenceType() {
884             return persistenceType;
885         }
886         
887         /** Throws deserialized root context and sets proper node found
888         * in roots set as new root context for this top component.
889         * The reason for such construction is to keep the uniquennes of
890         * root context node after deserialization. */

891         protected void validateRootContext () {
892             // find proper node
893
Class JavaDoc nodeClass = getExplorerManager().getRootContext().getClass();
894             Node[] roots = NbPlaces.getDefault().roots();
895             for (int i = 0; i < roots.length; i++) {
896                 if (nodeClass.equals(roots[i].getClass())) {
897                     setRootContext(roots[i]);
898                     registerRootContext(roots[i]);
899                     break;
900                 }
901             }
902         }
903         
904         /** Deserialization of ModuleTab */
905         public Object JavaDoc readResolve() throws java.io.ObjectStreamException JavaDoc {
906             Node root = getExplorerManager().getRootContext();
907             
908             ModuleTab tc = NbMainExplorer.findModuleTab(root, this);
909             if(tc == null) {
910                 throw new java.io.InvalidObjectException JavaDoc(
911                     "Cannot deserialize ModuleTab for node " + root); // NOI18N
912
}
913             
914             tc.scheduleValidation();
915             return tc;
916         }
917
918     } // end of ModuleTab inner class
919

920     /** Listener on roots, listens to changes of roots content */
921     private static final class RootsListener extends Object JavaDoc implements ChangeListener JavaDoc {
922         
923         RootsListener() {}
924         
925         public void stateChanged(ChangeEvent JavaDoc e) {
926             NbMainExplorer.getExplorer().doOpen(null);
927         }
928     } // end of RootsListener inner class
929

930     public static void main (String JavaDoc[] args) throws Exception JavaDoc {
931         NbMainExplorer e = new NbMainExplorer ();
932         e.open ();
933     }
934 }
935
Popular Tags