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 |
|
20 |
package org.netbeans.spi.project.ui.support; |
21 |
|
22 |
import java.io.IOException; |
23 |
import java.util.ArrayList; |
24 |
import java.util.Arrays; |
25 |
import java.util.Collections; |
26 |
import java.util.Enumeration; |
27 |
import java.util.HashMap; |
28 |
import java.util.Iterator; |
29 |
import java.util.List; |
30 |
import java.util.Map; |
31 |
import javax.swing.event.ChangeEvent; |
32 |
import javax.swing.event.ChangeListener; |
33 |
import org.netbeans.api.project.Project; |
34 |
import org.openide.ErrorManager; |
35 |
import org.openide.cookies.InstanceCookie; |
36 |
import org.openide.filesystems.FileAttributeEvent; |
37 |
import org.openide.filesystems.FileChangeListener; |
38 |
import org.openide.filesystems.FileEvent; |
39 |
import org.openide.filesystems.FileObject; |
40 |
import org.openide.filesystems.FileRenameEvent; |
41 |
import org.openide.filesystems.Repository; |
42 |
import org.openide.loaders.DataFolder; |
43 |
import org.openide.loaders.DataObject; |
44 |
import org.openide.loaders.DataObjectNotFoundException; |
45 |
import org.openide.loaders.FolderLookup; |
46 |
import org.openide.loaders.InstanceDataObject; |
47 |
import org.openide.nodes.Children; |
48 |
import org.openide.nodes.Node; |
49 |
import org.openide.util.Lookup; |
50 |
import org.openide.util.LookupEvent; |
51 |
import org.openide.util.LookupListener; |
52 |
|
53 |
/** |
54 |
* Support class for creating Project node's children nodes from NodeFactory instances |
55 |
* in layers. |
56 |
* @author mkleint |
57 |
* @since org.netbeans.modules.projectuiapi 1.17 |
58 |
*/ |
59 |
public class NodeFactorySupport { |
60 |
|
61 |
/** |
62 |
* Creates a new instance of NodeFactorySupport |
63 |
*/ |
64 |
private NodeFactorySupport() { |
65 |
} |
66 |
|
67 |
/** |
68 |
* create Node' Children instance that works on top of NodeFactory instances |
69 |
* in the layers. |
70 |
*/ |
71 |
public static Children createCompositeChildren(Project project, String folderPath) { |
72 |
return new DelegateChildren(project, folderPath); |
73 |
} |
74 |
/** |
75 |
* Utility method for creating a non variable NodeList instance. |
76 |
*/ |
77 |
public static NodeList fixedNodeList(Node[] nodes) { |
78 |
return new FixedNodeList(nodes); |
79 |
} |
80 |
|
81 |
/** |
82 |
* Utility method to create empty NodeList instance. Useful in case when a particular project instance is not |
83 |
* relevant to the NodeFactory |
84 |
*/ |
85 |
public static NodeList emptyNodeList() { |
86 |
return new FixedNodeList(new Node[0]); |
87 |
} |
88 |
|
89 |
|
90 |
private static class FixedNodeList implements NodeList { |
91 |
|
92 |
private List nodes; |
93 |
|
94 |
FixedNodeList(Node[] nds) { |
95 |
nodes = Arrays.asList(nds); |
96 |
} |
97 |
public List keys() { |
98 |
return nodes; |
99 |
} |
100 |
|
101 |
public void addChangeListener(ChangeListener l) { } |
102 |
|
103 |
public void removeChangeListener(ChangeListener l) { } |
104 |
|
105 |
public Node node(Object key) { |
106 |
return (Node)key; |
107 |
} |
108 |
|
109 |
public void addNotify() { |
110 |
} |
111 |
|
112 |
public void removeNotify() { |
113 |
} |
114 |
} |
115 |
|
116 |
static class DelegateChildren extends Children.Keys implements LookupListener, ChangeListener { |
117 |
|
118 |
private String folderPath; |
119 |
private Project project; |
120 |
private List nodeLists = new ArrayList(); |
121 |
private List factories = new ArrayList(); |
122 |
private Lookup.Result result; |
123 |
|
124 |
public DelegateChildren(Project proj, String path) { |
125 |
folderPath = path; |
126 |
project = proj; |
127 |
} |
128 |
|
129 |
// protected for tests.. |
130 |
protected Lookup createLookup() { |
131 |
FileObject root = Repository.getDefault().getDefaultFileSystem().findResource(folderPath); |
132 |
DataFolder folder = DataFolder.findFolder(root); |
133 |
return new FolderLookup(folder).getLookup(); |
134 |
} |
135 |
|
136 |
protected Node[] createNodes(Object key) { |
137 |
NodeList lst = (NodeList)key; |
138 |
Iterator it = lst.keys().iterator(); |
139 |
List toRet = new ArrayList(); |
140 |
while (it.hasNext()) { |
141 |
Object elem = it.next(); |
142 |
Node nd = lst.node(elem); |
143 |
if (nd != null) { |
144 |
toRet.add(nd); |
145 |
} |
146 |
} |
147 |
return (Node[])toRet.toArray(new Node[toRet.size()]); |
148 |
} |
149 |
|
150 |
protected void addNotify() { |
151 |
super.addNotify(); |
152 |
result = createLookup().lookup(new Lookup.Template(NodeFactory.class)); |
153 |
Iterator it = result.allInstances().iterator(); |
154 |
while (it.hasNext()) { |
155 |
NodeFactory factory = (NodeFactory) it.next(); |
156 |
NodeList lst = factory.createNodes(project); |
157 |
assert lst != null; |
158 |
nodeLists.add(lst); |
159 |
lst.addNotify(); |
160 |
lst.addChangeListener(this); |
161 |
factories.add(factory); |
162 |
} |
163 |
result.addLookupListener(this); |
164 |
setKeys(nodeLists); |
165 |
} |
166 |
|
167 |
protected void removeNotify() { |
168 |
super.removeNotify(); |
169 |
setKeys(Collections.EMPTY_LIST); |
170 |
Iterator it = nodeLists.iterator(); |
171 |
while (it.hasNext()) { |
172 |
NodeList elem = (NodeList) it.next(); |
173 |
elem.removeChangeListener(this); |
174 |
elem.removeNotify(); |
175 |
} |
176 |
nodeLists.clear(); |
177 |
factories.clear(); |
178 |
if (result != null) { |
179 |
result.removeLookupListener(this); |
180 |
result = null; |
181 |
} |
182 |
} |
183 |
|
184 |
public void stateChanged(ChangeEvent e) { |
185 |
refreshKey(e.getSource()); |
186 |
} |
187 |
|
188 |
public void resultChanged(LookupEvent ev) { |
189 |
Iterator it = result.allInstances().iterator(); |
190 |
int index = 0; |
191 |
while (it.hasNext()) { |
192 |
NodeFactory factory = (NodeFactory) it.next(); |
193 |
if (!factories.contains(factory)) { |
194 |
factories.add(index, factory); |
195 |
NodeList lst = factory.createNodes(project); |
196 |
assert lst != null; |
197 |
nodeLists.add(index, lst); |
198 |
lst.addNotify(); |
199 |
lst.addChangeListener(this); |
200 |
} else { |
201 |
while (!factory.equals(factories.get(index))) { |
202 |
factories.remove(index); |
203 |
NodeList lst = (NodeList)nodeLists.remove(index); |
204 |
lst.removeNotify(); |
205 |
lst.removeChangeListener(this); |
206 |
} |
207 |
} |
208 |
index++; |
209 |
} |
210 |
setKeys(nodeLists); |
211 |
} |
212 |
|
213 |
} |
214 |
|
215 |
} |