KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > explorer > ExplorerPanel


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 package org.openide.explorer;
20
21 import org.netbeans.core.IDESettings;
22 import org.openide.nodes.Node;
23 import org.openide.util.HelpCtx;
24 import org.openide.util.NbBundle;
25 import org.openide.util.NbPreferences;
26 import org.openide.util.WeakListeners;
27 import org.openide.util.io.*;
28 import org.openide.windows.TopComponent;
29 import org.openide.windows.WindowManager;
30 import org.openide.windows.Workspace;
31
32 import java.awt.event.ActionEvent JavaDoc;
33 import java.awt.event.ActionListener JavaDoc;
34
35 import java.beans.PropertyChangeEvent JavaDoc;
36 import java.beans.PropertyChangeListener JavaDoc;
37
38 import java.io.*;
39
40 import java.text.MessageFormat JavaDoc;
41
42 import javax.swing.Timer JavaDoc;
43
44
45 /** Simple top component capable of displaying an Explorer.
46 * Holds one instance of {@link ExplorerManager} and
47 * implements {@link ExplorerManager.Provider} to allow child components to share
48 * the same explorer manager.
49 * <p>Uses {@link java.awt.BorderLayout} by default.
50 * Pays attention to the selected nodes and explored context as indicated by the manager.
51 * Cut/copy/paste actions are sensitive to the activation state of the component.
52 * <p>It is up to you to add a view and other UI apparatus to the panel.
53 *
54 * @deprecated Use {@link ExplorerUtils#actionCopy}, etc, see {@link ExplorerUtils} javadoc
55 * for details
56 * @author Jaroslav Tulach
57 */

58 public class ExplorerPanel extends TopComponent implements ExplorerManager.Provider {
59     /** serial version UID */
60     static final long serialVersionUID = 5522528786650751459L;
61
62     /** The message formatter for Explorer title */
63     private static MessageFormat JavaDoc formatExplorerTitle;
64
65     /** Init delay for second change of the activated nodes. */
66     private static final int INIT_DELAY = 70;
67
68     /** Maximum delay for repeated change of the activated nodes. */
69     private static final int MAX_DELAY = 350;
70     private static Boolean JavaDoc scheduleAcivatedNodes;
71
72     /** mapping from ExplorerManagers to the ExplorerPanels they are associated
73      * with. ExplorerManager -> Reference (ExplorerPanel)
74      */

75     private static java.util.WeakHashMap JavaDoc panels = new java.util.WeakHashMap JavaDoc();
76
77     /** the instance of the explorer manager*/
78     private ExplorerManager manager;
79
80     /** listens on the selected nodes in the ExporerManager */
81     transient private final PropertyChangeListener JavaDoc managerListener = new PropL();
82
83     /** action handler for cut/copy/paste/delete for this panel */
84     private ExplorerActions actions;
85     private transient DelayedSetter delayedSetter;
86
87     /** Initialize the explorer panel with the provided manager.
88     * @param manager the explorer manager to use
89     */

90     public ExplorerPanel(ExplorerManager manager) {
91         this(manager, null);
92     }
93
94     /** Default constructor. Uses newly created manager.
95     */

96     public ExplorerPanel() {
97         this(null, null);
98     }
99
100     /** Allows to create an explorer with disabled delete confirmation.
101      * @param confirm false if delete action should not be confirmed
102      */

103     ExplorerPanel(ExplorerManager manager, boolean confirm) {
104         this(manager, Boolean.valueOf(confirm));
105     }
106
107     private ExplorerPanel(ExplorerManager manager, Boolean JavaDoc confirm) {
108         if (manager == null) {
109             manager = new ExplorerManager();
110         }
111
112         this.manager = manager;
113         panels.put(manager, new java.lang.ref.WeakReference JavaDoc(this));
114
115         setLayout(new java.awt.BorderLayout JavaDoc());
116         initActionMap(confirm);
117         initListening();
118     }
119
120     // bugfix #36509, added 3-state (true/false/unset) parameter for confirm delete
121
// unset means read parameter from the global ConfirmDelete option
122

123     /** Initializes actions map. */
124     private void initActionMap(Boolean JavaDoc confirm) {
125         ExplorerActions a = new ExplorerActions(false);
126
127         if (confirm != null) {
128             a.setConfirmDelete(confirm.booleanValue());
129         }
130
131         a.attach(getExplorerManager());
132     }
133
134     /** Called from a ExplorerActions.attach, to notify that these
135      * ExplorerActions will now be responsible for given explorer
136      * manager.
137      *
138      * @param actions the actions
139      * @param em the manager
140      */

141     static void associateActions(ExplorerActions actions, ExplorerManager em) {
142         java.lang.ref.Reference JavaDoc ref = (java.lang.ref.Reference JavaDoc) panels.get(em);
143         ExplorerPanel p = (ref == null) ? null : (ExplorerPanel) ref.get();
144
145         if (p != null) {
146             p.getActionMap().put(javax.swing.text.DefaultEditorKit.copyAction, actions.copyAction());
147             p.getActionMap().put(javax.swing.text.DefaultEditorKit.cutAction, actions.cutAction());
148             p.getActionMap().put(javax.swing.text.DefaultEditorKit.pasteAction, actions.pasteAction());
149             p.getActionMap().put("delete", actions.deleteAction() // NOI18N
150
);
151
152             // and remember the actions
153
p.actions = actions;
154         }
155     }
156
157     /** Initializes listening on ExplorerManager property changes. */
158     private void initListening() {
159         // Attaches listener if there is not one already.
160
ExplorerManager man = getExplorerManager();
161         man.addPropertyChangeListener(org.openide.util.WeakListeners.propertyChange(managerListener, man));
162         setActivatedNodes(manager.getSelectedNodes());
163     }
164
165     /* Add a listener to the explorer panel in addition to the normal
166     * open behaviour.
167     */

168     public void open() {
169         open(WindowManager.getDefault().getCurrentWorkspace());
170     }
171
172     /* Add a listener to the explorer panel in addition to the normal
173     * open behaviour.
174     */

175     public void open(Workspace workspace) {
176         super.open(workspace);
177         setActivatedNodes(getExplorerManager().getSelectedNodes());
178         updateTitle();
179     }
180
181     /* Provides the explorer manager to all who are interested.
182     * @return the manager
183     */

184     public ExplorerManager getExplorerManager() {
185         return manager;
186     }
187
188     /** Activates copy/cut/paste actions.
189      */

190     protected void componentActivated() {
191         if (actions != null) {
192             actions.attach(getExplorerManager());
193         }
194     }
195
196     /* Deactivates copy/cut/paste actions.
197      */

198     protected void componentDeactivated() {
199         if (actions != null) {
200             actions.detach();
201         }
202     }
203
204     /** Called when the explored context changes.
205     * The default implementation updates the title of the window.
206     */

207     protected void updateTitle() {
208         String JavaDoc name = ""; // NOI18N
209

210         ExplorerManager em = getExplorerManager();
211
212         if (em != null) {
213             Node n = em.getExploredContext();
214
215             if (n != null) {
216                 String JavaDoc nm = n.getDisplayName();
217
218                 if (nm != null) {
219                     name = nm;
220                 }
221             }
222         }
223
224         if (formatExplorerTitle == null) {
225             formatExplorerTitle = new MessageFormat JavaDoc(NbBundle.getMessage(ExplorerPanel.class, "explorerTitle"));
226         }
227
228         setName(formatExplorerTitle.format(new Object JavaDoc[] { name }));
229     }
230
231     /** Get context help for an explorer window.
232     * Looks at the manager's node selection.
233     * @return the help context
234     * @see #getHelpCtx(Node[],HelpCtx)
235     */

236     public HelpCtx getHelpCtx() {
237         return getHelpCtx(getExplorerManager().getSelectedNodes(), new HelpCtx(ExplorerPanel.class));
238     }
239
240     /** Utility method to get context help from a node selection.
241     * Tries to find context helps for selected nodes.
242     * If there are some, and they all agree, uses that.
243     * In all other cases, uses the supplied generic help.
244     * @param sel a list of nodes to search for help in
245     * @param def the default help to use if they have none or do not agree
246     * @return a help context
247     */

248     public static HelpCtx getHelpCtx(Node[] sel, HelpCtx def) {
249         return ExplorerUtils.getHelpCtx(sel, def);
250     }
251
252     /** Set whether deletions should have to be confirmed on all Explorer panels.
253     * @param confirmDelete <code>true</code> to confirm, <code>false</code> to delete at once
254     */

255     public static void setConfirmDelete(boolean confirmDelete) {
256         NbPreferences.root().node("/org/netbeans/core").putBoolean("confirmDelete",confirmDelete);//NOI18N
257
}
258
259     /** Are deletions confirmed on all Explorer panels?
260     * @return <code>true</code> if they must be confirmed
261     */

262     public static boolean isConfirmDelete() {
263         return NbPreferences.root().node("/org/netbeans/core").getBoolean("confirmDelete",true);//NOI18N
264
}
265
266     /** Stores the manager */
267     public void writeExternal(ObjectOutput oo) throws IOException {
268         super.writeExternal(oo);
269         oo.writeObject(new NbMarshalledObject(manager));
270     }
271
272     /** Reads the manager.
273     * Deserialization may throw {@link SafeException} in case
274     * the manager cannot be loaded correctly but the stream is still uncorrupted.
275     */

276     public void readExternal(ObjectInput oi) throws IOException, ClassNotFoundException JavaDoc {
277         super.readExternal(oi);
278
279         Object JavaDoc anObj = oi.readObject();
280
281         if (anObj instanceof ExplorerManager) {
282             manager = (ExplorerManager) anObj;
283             panels.put(manager, new java.lang.ref.WeakReference JavaDoc(this));
284             initActionMap(null);
285             initListening();
286
287             return;
288         }
289
290         NbMarshalledObject obj = (NbMarshalledObject) anObj;
291
292         // --- read all data from main stream, it is OK now ---
293
try {
294             manager = (ExplorerManager) obj.get();
295             panels.put(manager, new java.lang.ref.WeakReference JavaDoc(this));
296             initActionMap(null);
297             initListening();
298         } catch (SafeException se) {
299             throw se;
300         } catch (IOException ioe) {
301             throw new SafeException(ioe);
302         }
303     }
304
305     // temporary workaround the issue #31244
306
private boolean delayActivatedNodes() {
307         if (scheduleAcivatedNodes == null) {
308             if (System.getProperty("netbeans.delay.tc") != null) { // NOI18N
309
scheduleAcivatedNodes = Boolean.getBoolean("netbeans.delay.tc") ? Boolean.TRUE : Boolean.FALSE; // NOI18N
310
} else {
311                 scheduleAcivatedNodes = Boolean.FALSE;
312             }
313         }
314
315         return scheduleAcivatedNodes.booleanValue();
316     }
317
318     // schudule activation the nodes
319
private final void scheduleActivatedNodes(Node[] nodes) {
320         synchronized (this) {
321             if (delayedSetter == null) {
322                 delayedSetter = new DelayedSetter();
323             }
324         }
325
326         delayedSetter.scheduleActivatedNodes(nodes);
327     }
328
329     /** Listener on the explorer manager properties.
330     * Changes selected nodes of this frame.
331     */

332     private final class PropL extends Object JavaDoc implements PropertyChangeListener JavaDoc {
333         PropL() {
334         }
335
336         public void propertyChange(PropertyChangeEvent JavaDoc evt) {
337             if (evt.getSource() != manager) {
338                 return;
339             }
340
341             if (ExplorerManager.PROP_SELECTED_NODES.equals(evt.getPropertyName())) {
342                 if (delayActivatedNodes()) {
343                     scheduleActivatedNodes(manager.getSelectedNodes());
344                 } else {
345                     setActivatedNodes(manager.getSelectedNodes());
346                 }
347
348                 return;
349             }
350
351             if (ExplorerManager.PROP_EXPLORED_CONTEXT.equals(evt.getPropertyName())) {
352                 updateTitle();
353
354                 return;
355             }
356         }
357     }
358
359     private class DelayedSetter implements ActionListener JavaDoc {
360         private Node[] nodes;
361         private Timer JavaDoc timer;
362         private boolean firstChange = true;
363
364         DelayedSetter() {
365         }
366
367         public void scheduleActivatedNodes(Node[] nodes) {
368             synchronized (this) {
369                 this.nodes = nodes;
370
371                 if (timer == null) {
372                     // start timer with INIT_DELAY
373
timer = new Timer JavaDoc(INIT_DELAY, this);
374                     timer.setCoalesce(true);
375                     timer.setRepeats(false);
376                 }
377
378                 if (timer.isRunning()) {
379                     // if timer is running then double init delay
380
if (timer.getInitialDelay() < MAX_DELAY) {
381                         timer.setInitialDelay(timer.getInitialDelay() * 2);
382                     }
383
384                     firstChange = false;
385                 } else {
386                     // the first change is set immediatelly
387
setActivatedNodes(nodes);
388                     firstChange = true;
389                 }
390
391                 // make sure timer is running
392
timer.restart();
393             }
394         }
395
396         public void actionPerformed(ActionEvent JavaDoc evt) {
397             synchronized (this) {
398                 synchronized (this) {
399                     timer.stop();
400                 }
401             }
402
403             // set activated nodes for 2nd and next changes
404
if (!firstChange) {
405                 setActivatedNodes(nodes);
406             }
407         }
408     }
409 }
410
Popular Tags