KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > core > windows > RegistryImpl


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

19
20 package org.netbeans.core.windows;
21
22 import org.openide.nodes.Node;
23 import org.openide.util.WeakSet;
24 import org.openide.windows.TopComponent;
25
26 import javax.swing.*;
27 import java.awt.*;
28 import java.beans.PropertyChangeListener JavaDoc;
29 import java.beans.PropertyChangeSupport JavaDoc;
30 import java.util.Arrays JavaDoc;
31 import java.util.HashSet JavaDoc;
32 import java.util.Set JavaDoc;
33
34 /** Implementstion of registry of top components. This implementation
35  * receives information about top component changes from the window
36  * manager implementation, to which is listening to.
37  *
38  * @author Peter Zavadsky
39  */

40 public final class RegistryImpl extends Object JavaDoc implements TopComponent.Registry {
41     
42     // fields
43
/** Activated top component */
44     private TopComponent activatedTopComponent;
45     /** Set of opened TopComponents */
46     private final Set<TopComponent> openSet = new WeakSet<TopComponent>(30);
47     /** Currently selected nodes. */
48     private Node[] currentNodes;
49     /** Last non-null value of current nodes. (If null -> it means they are
50      * not initialized and weren't fired yet. */

51     private Node[] activatedNodes;
52     /** PropertyChange support */
53     private final PropertyChangeSupport JavaDoc support = new PropertyChangeSupport JavaDoc(this);
54     
55     /** Debugging flag. */
56     private static final boolean DEBUG = Debug.isLoggable(RegistryImpl.class);
57
58     /** Creates new RegistryImpl */
59     public RegistryImpl() {
60     }
61     
62     /** Get all opened componets in the system.
63      *
64      * @return immutable set of {@link TopComponent}s
65      */

66     public synchronized Set<TopComponent> getOpened() {
67         return java.util.Collections.unmodifiableSet(openSet);
68     }
69     
70     /** Get the currently selected element.
71      * @return the selected top component, or <CODE>null</CODE> if there is none
72      */

73     public TopComponent getActivated() {
74         return activatedTopComponent;
75     }
76     
77     /** Getter for the currently selected nodes.
78      * @return array of nodes or null if no component activated. */

79     public Node[] getCurrentNodes() {
80         return currentNodes;
81     }
82     
83     /** Getter for the lastly activated nodes. Comparing
84      * to previous method it always remembers the selected nodes
85      * of the last component that had ones.
86      *
87      * @return array of nodes (not null)
88      */

89     public Node[] getActivatedNodes() {
90         return activatedNodes == null ? new Node[0] : activatedNodes;
91     }
92     
93     /** Add a property change listener.
94      * @param l the listener to add
95      */

96     public void addPropertyChangeListener(PropertyChangeListener JavaDoc l) {
97         support.addPropertyChangeListener(l);
98     }
99     
100     /** Remove a property change listener.
101      * @param l the listener to remove
102      */

103     public void removePropertyChangeListener(PropertyChangeListener JavaDoc l) {
104         support.removePropertyChangeListener(l);
105     }
106
107     
108     //////////////////////////////////////////////////////
109
/// notifications of changes from window manager >>>>>
110
/** Called when a TopComponent is activated.
111      *
112      * @param ev TopComponentChangedEvent
113      */

114     void topComponentActivated(TopComponent tc) {
115         if(activatedTopComponent == tc
116         && activatedNodes != null) { // When null it means were not inited yet.
117
return;
118         }
119         
120         final TopComponent old = activatedTopComponent;
121         activatedTopComponent = tc;
122         
123         Window w = tc == null ? null : SwingUtilities.windowForComponent(tc);
124         cancelMenu(w);
125         
126 /** PENDING: Firing the change asynchronously improves perceived responsiveness
127  considerably (toolbars are updated after the component repaints, so it appears
128  to immediately become selected), but means that
129  for one EQ cycle the activated TopComponent will be out of sync with the
130  global node selection. Needs testing. -Tim
131  
132  C.f. issue 42256 - most of the delay may be called by contention in
133      ProxyLookup, but this fix will have some responsiveness benefits
134      even if that is fixed
135 */

136         SwingUtilities.invokeLater(new Runnable JavaDoc() {
137             public void run() {
138                 doFirePropertyChange(PROP_ACTIVATED, old, activatedTopComponent);
139             }
140         });
141
142         selectedNodesChanged(activatedTopComponent,
143             activatedTopComponent == null ? null : activatedTopComponent.getActivatedNodes());
144     }
145     
146     
147     
148     /** Called when a TopComponent is opened. */
149     synchronized void topComponentOpened(TopComponent tc) {
150         if (openSet.contains(tc)) {
151             return;
152         }
153         Set<TopComponent> old = new HashSet JavaDoc<TopComponent>(openSet);
154         openSet.add(tc);
155         doFirePropertyChange(PROP_TC_OPENED, null, tc);
156         doFirePropertyChange(PROP_OPENED, old, new HashSet JavaDoc<TopComponent>(openSet));
157     }
158     
159     /** Called when a TopComponent is closed. */
160     synchronized void topComponentClosed(TopComponent tc) {
161         if (!openSet.contains(tc)) {
162             return;
163         }
164
165         Set<TopComponent> old = new HashSet JavaDoc<TopComponent>(openSet);
166         openSet.remove(tc);
167         doFirePropertyChange(PROP_TC_CLOSED, null, tc);
168         doFirePropertyChange(PROP_OPENED, old, new HashSet JavaDoc<TopComponent>(openSet));
169
170         if (activatedNodes != null) {
171             Node[] closedNodes = tc.getActivatedNodes();
172             if (closedNodes != null && Arrays.equals(closedNodes, activatedNodes)) {
173                 // The component whose nodes were activated has been closed; cancel the selection.
174
activatedNodes = null;
175                 doFirePropertyChange(PROP_ACTIVATED_NODES, closedNodes, null);
176             }
177         }
178     }
179     
180     /** Called when selected nodes changed. */
181     public void selectedNodesChanged(TopComponent tc, Node[] newNodes) {
182         Node[] oldNodes = currentNodes;
183         
184         //Fixed bug #8933 27 Mar 2001 by Marek Slama
185
//Selected nodes event was processed for other than activated component.
186
//Check if activatedTopComponent is the same as event source top component
187
//If not ignore event
188
if(tc != activatedTopComponent
189         && activatedNodes != null) { // When null it means were not inited yet.
190
return;
191         }
192         //End of bugfix #8933
193

194         if(Arrays.equals(oldNodes, newNodes)
195         && activatedNodes != null) { // When null it means were not inited yet.
196
return;
197         }
198
199         currentNodes = newNodes == null ? null : newNodes.clone();
200         // fire immediatelly only if window manager in proper state
201
tryFireChanges(oldNodes, currentNodes);
202     }
203     /// notifications of changes from window manager <<<<<
204
//////////////////////////////////////////////////////
205

206     /** Cancels the menu if it is not assigned to specified window.
207      * @param window window that the menu should be checked against
208      * (if this window contains the menu, then the menu will not be closed)
209      */

210     /** Closes popup menu.
211      */

212     public static void cancelMenu(Window window) {
213         MenuSelectionManager msm = MenuSelectionManager.defaultManager();
214         MenuElement[] path = msm.getSelectedPath();
215         
216         for (int i = 0; i < path.length; i++) {
217             // if (newPath[i] != path[i]) return;
218
java.awt.Window JavaDoc w = SwingUtilities.windowForComponent(
219                 path[i].getComponent()
220             );
221             
222             // we must check for null because windowForComponent above can return null
223
if ((w != null) && (w == window || w.getOwner() == window)) {
224                 // ok, this menu can stay
225
return;
226             }
227             
228         }
229         
230         msm.clearSelectedPath();
231     }
232     
233     
234     /** If window manager in proper state, fire selected and
235      * activated node changes */

236     private void tryFireChanges(Node[] oldNodes, Node[] newNodes) {
237         doFirePropertyChange(PROP_CURRENT_NODES, oldNodes, newNodes);
238         
239         if(newNodes == null && activatedNodes == null) {
240             // Ensure activated nodes are going to be fired first time in session for this case.
241
newNodes = new Node[0];
242         }
243         
244         if (newNodes != null) {
245             oldNodes = activatedNodes;
246             activatedNodes = newNodes;
247             support.firePropertyChange(PROP_ACTIVATED_NODES, oldNodes, activatedNodes);
248         }
249     }
250     
251     
252     private void doFirePropertyChange(final String JavaDoc propName,
253     final Object JavaDoc oldValue, final Object JavaDoc newValue) {
254         if(DEBUG) {
255             debugLog(""); // NOI18N
256
debugLog("Scheduling event firing: propName=" + propName); // NOI18N
257
debugLog("\toldValue=" + (oldValue instanceof Object JavaDoc[] ? Arrays.asList((Object JavaDoc[])oldValue) : oldValue)); // NOI18N
258
debugLog("\tnewValue=" + (newValue instanceof Object JavaDoc[] ? Arrays.asList((Object JavaDoc[])newValue) : newValue)); // NOI18N
259
}
260         // PENDING When #37529 finished, then uncomment the next row and move the
261
// checks of AWT thread away.
262
// WindowManagerImpl.assertEventDispatchThread();
263
if(SwingUtilities.isEventDispatchThread()) {
264             support.firePropertyChange(propName, oldValue, newValue);
265         } else {
266             SwingUtilities.invokeLater(new Runnable JavaDoc() {
267                 public void run() {
268                     support.firePropertyChange(propName, oldValue, newValue);
269                 }
270             });
271         }
272     }
273     
274     void clear() {
275         activatedTopComponent = null;
276         openSet.clear();
277         currentNodes = null;
278         activatedNodes = null;
279     }
280     
281     private static void debugLog(String JavaDoc message) {
282         Debug.log(RegistryImpl.class, message);
283     }
284     
285 }
286
Popular Tags