Added
Link Here
|
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.nodes; |
20 |
|
21 |
import java.awt.Image; |
22 |
import java.lang.Thread; |
23 |
import java.util.Collections; |
24 |
import java.util.List; |
25 |
import org.openide.util.NbBundle; |
26 |
import org.openide.util.RequestProcessor; |
27 |
import org.openide.util.Utilities; |
28 |
|
29 |
/** |
30 |
* Children object which creates its keys on a background thread. To use, |
31 |
* implement AsynchChildren.Provider and pass that to the constructor. |
32 |
* |
33 |
* @author Tim Boudreau |
34 |
*/ |
35 |
public final class AsynchChildren extends Children.Keys <Object> { |
36 |
private final Provider provider; |
37 |
private final RequestProcessor.Task task; |
38 |
private static final RequestProcessor PROC = new RequestProcessor("Asynch " //NOI18N |
39 |
+ "children creator", Thread.NORM_PRIORITY, true); //NOI18N |
40 |
private final R r = new R(); |
41 |
/** |
42 |
* Create a new AsyncChildren instance with the passed provider object |
43 |
* which will manufacture key objects and nodes. |
44 |
* @param provider An object which can provide a list of keys and make |
45 |
* Nodes for them |
46 |
*/ |
47 |
public AsynchChildren(Provider provider) { |
48 |
this.provider = provider; |
49 |
task = PROC.create(r, true); |
50 |
} |
51 |
|
52 |
protected void addNotify() { |
53 |
if (task.isFinished() || r.cancelled) { |
54 |
r.cancelled = false; |
55 |
setKeys (new Object[] { new WaitNode() }); |
56 |
task.schedule(0); |
57 |
} |
58 |
} |
59 |
|
60 |
@SuppressWarnings("unchecked") |
61 |
protected void removeNotify() { |
62 |
r.cancelled = true; |
63 |
task.cancel(); |
64 |
setKeys (Collections.EMPTY_LIST); |
65 |
} |
66 |
|
67 |
/** |
68 |
* Notify this AsynchChildren that it should reconstruct its children, |
69 |
* calling <code>provider.asynchCreateKeys()</code> and setting the |
70 |
* keys to that. Call this method if the list of child objects is known |
71 |
* or likely to have changed. |
72 |
* @param immediate If true, the keys are updated synchronously from the |
73 |
* calling thread. Set this to true only if you know that updating |
74 |
* the keys will <i>not</i> be an expensive or time-consuming operation. |
75 |
*/ |
76 |
@SuppressWarnings("unchecked") //NOI18N |
77 |
public void update(boolean immediate) { |
78 |
if (immediate) { |
79 |
setKeys (provider.asynchCreateKeys()); |
80 |
} else { |
81 |
task.schedule (0); |
82 |
} |
83 |
} |
84 |
|
85 |
public Node[] getNodes(boolean optimalResult) { |
86 |
if (optimalResult) { |
87 |
task.waitFinished(); |
88 |
} |
89 |
return super.getNodes(); |
90 |
} |
91 |
|
92 |
@SuppressWarnings("unchecked") |
93 |
protected Node[] createNodes(Object key) { |
94 |
if (key instanceof WaitNode) { |
95 |
return new Node[] { (Node) key }; |
96 |
} else { |
97 |
return provider.createNodes (key); |
98 |
} |
99 |
} |
100 |
|
101 |
/** |
102 |
* Factory for keys and child nodes for an instance of AsynchChildren. |
103 |
*/ |
104 |
public static interface Provider <T extends Object> { |
105 |
/** |
106 |
* Create Nodes for a given key object (one from the <code>List</code> |
107 |
* returned by asynchCreateKeys()). |
108 |
* @param key An object from the list returned by |
109 |
* <code>asynchCreateKeys()</code> |
110 |
* @return zero or more Nodes to represent this key |
111 |
*/ |
112 |
public Node[] createNodes (T key); |
113 |
/** |
114 |
* Create a list of keys which can be individually passed to |
115 |
* createNodes() to create child Nodes. Implementations of |
116 |
* this method should regularly check Thread.interrupted(), and |
117 |
* if it returns true (meaning the parent Node was collapsed or |
118 |
* destroyed), stop creating keys immediately and return |
119 |
* null. This method is guaranteed <i>not</i> to be called on the |
120 |
* AWT event thread. |
121 |
* |
122 |
* @return A <code>List</code> of objects to use as keys, or null |
123 |
* if cancelled |
124 |
*/ |
125 |
public List <T> asynchCreateKeys(); |
126 |
} |
127 |
|
128 |
private final class R implements Runnable { |
129 |
volatile boolean cancelled = false; |
130 |
|
131 |
@SuppressWarnings("unchecked") |
132 |
public void run() { |
133 |
if (Thread.interrupted()) { |
134 |
doSetKeys (Collections.EMPTY_LIST); |
135 |
return; |
136 |
} |
137 |
List <Object> keys = provider.asynchCreateKeys(); |
138 |
if (keys == null || Thread.interrupted()) { |
139 |
keys = Collections.EMPTY_LIST; |
140 |
} |
141 |
doSetKeys (keys); |
142 |
} |
143 |
|
144 |
private void doSetKeys (List <Object> keys) { |
145 |
setKeys (keys); |
146 |
justComputeNodes(); |
147 |
} |
148 |
|
149 |
} |
150 |
|
151 |
//We need a type that no Children class will use as a key |
152 |
private static final class WaitNode extends AbstractNode { |
153 |
public WaitNode () { |
154 |
super (Children.LEAF); |
155 |
setDisplayName (NbBundle.getMessage (WaitNode.class, "LBL_WAIT")); //NOI18N |
156 |
} |
157 |
|
158 |
public Image getIcon (int type) { |
159 |
return Utilities.loadImage ("org/openide/nodes/wait.gif"); //NOI18N |
160 |
} |
161 |
} |
162 |
} |