Mercurial > projects > dwt2
comparison org.eclipse.jface.databinding/src/org/eclipse/jface/internal/databinding/provisional/viewers/TreeNode.d @ 78:0a55d2d5a946
Added file for databinding
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 14 Apr 2009 11:35:29 +0200 |
parents | |
children | 6be48cf9f95c |
comparison
equal
deleted
inserted
replaced
76:f05e6e8b2f2d | 78:0a55d2d5a946 |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2006, 2008 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Stefan Xenos, IBM - initial API and implementation | |
11 *******************************************************************************/ | |
12 module org.eclipse.jface.internal.databinding.provisional.viewers.TreeNode; | |
13 | |
14 import java.lang.all; | |
15 | |
16 import java.util.Collections; | |
17 import java.util.HashSet; | |
18 import java.util.Set; | |
19 | |
20 import org.eclipse.core.databinding.observable.IStaleListener; | |
21 import org.eclipse.core.databinding.observable.Observables; | |
22 import org.eclipse.core.databinding.observable.StaleEvent; | |
23 import org.eclipse.core.databinding.observable.set.IObservableSet; | |
24 import org.eclipse.core.databinding.observable.set.ISetChangeListener; | |
25 import org.eclipse.core.databinding.observable.set.SetChangeEvent; | |
26 import org.eclipse.core.databinding.observable.set.SetDiff; | |
27 import org.eclipse.jface.databinding.viewers.ObservableListTreeContentProvider; | |
28 import org.eclipse.jface.databinding.viewers.ObservableSetTreeContentProvider; | |
29 import org.eclipse.jface.viewers.TreeViewer; | |
30 import org.eclipse.swt.widgets.Control; | |
31 | |
32 /** | |
33 * | |
34 * @since 1.0 | |
35 * @deprecated Use {@link ObservableSetTreeContentProvider} or | |
36 * {@link ObservableListTreeContentProvider} instead. | |
37 */ | |
38 /* package */ class TreeNode : ISetChangeListener, IStaleListener { | |
39 private UnorderedTreeContentProvider contentProvider; | |
40 private Object element; | |
41 | |
42 // Stores the set of parents (null if there are less than 2) | |
43 private HashSet parents = null; | |
44 | |
45 // Stores one representative parent. If there is more than one parent, | |
46 // the complete set of parents can be found in the parents set. | |
47 Object parent; | |
48 | |
49 /** | |
50 * Set of child elements. | |
51 */ | |
52 private IObservableSet children; | |
53 | |
54 private bool hasPendingNode = false; | |
55 private bool isStale; | |
56 private bool listeningToChildren = false; | |
57 private bool prefetchEnqueued = false; | |
58 | |
59 /** | |
60 * @param element | |
61 * @param cp | |
62 */ | |
63 public this(Object element, UnorderedTreeContentProvider cp) { | |
64 this.element = element; | |
65 this.contentProvider = cp; | |
66 children = contentProvider.createChildSet(element); | |
67 if (children is null) { | |
68 children = Observables.emptyObservableSet(); | |
69 listeningToChildren = true; | |
70 } | |
71 hasPendingNode = children.isStale(); | |
72 } | |
73 | |
74 /** | |
75 * @param parent | |
76 */ | |
77 public void addParent(Object parent) { | |
78 if (this.parent is null) { | |
79 this.parent = parent; | |
80 } else { | |
81 if (parent.equals(this.parent)) { | |
82 return; | |
83 } | |
84 if (parents is null) { | |
85 parents = new HashSet(); | |
86 parents.add(this.parent); | |
87 } | |
88 parents.add(parent); | |
89 } | |
90 } | |
91 | |
92 /** | |
93 * @param parent | |
94 */ | |
95 public void removeParent(Object parent) { | |
96 if (this.parents !is null) { | |
97 parents.remove(parent); | |
98 } | |
99 | |
100 if (parent is this.parent) { | |
101 if (parents is null || parents.isEmpty()) { | |
102 this.parent = null; | |
103 } else { | |
104 this.parent = parents.iterator().next(); | |
105 } | |
106 } | |
107 | |
108 if (this.parents !is null && this.parents.size() <= 1) { | |
109 this.parents = null; | |
110 } | |
111 } | |
112 | |
113 /** | |
114 * Returns the set of children for this node. If new children are discovered later, they | |
115 * will be added directly to the viewer. | |
116 * | |
117 * @return TODO | |
118 */ | |
119 public Set getChildren() { | |
120 if (!listeningToChildren) { | |
121 listeningToChildren = true; | |
122 children.addSetChangeListener(this); | |
123 hasPendingNode = children.isEmpty() && children.isStale(); | |
124 children.addStaleListener(this); | |
125 updateStale(); | |
126 } | |
127 | |
128 // If the child set is stale and empty, show the "pending" node | |
129 if (hasPendingNode) { | |
130 Object pendingNode = contentProvider.getPendingNode(); | |
131 return Collections.singleton(pendingNode); | |
132 } | |
133 return children; | |
134 } | |
135 | |
136 /** | |
137 * @return TODO | |
138 */ | |
139 public IObservableSet getChildrenSet() { | |
140 return children; | |
141 } | |
142 | |
143 private void updateStale() { | |
144 bool willBeStale = children.isStale(); | |
145 if (willBeStale !is isStale) { | |
146 isStale = willBeStale; | |
147 | |
148 contentProvider.changeStale(isStale? 1 : -1); | |
149 } | |
150 } | |
151 | |
152 /** | |
153 * @return TODO | |
154 */ | |
155 public bool isStale() { | |
156 return isStale; | |
157 } | |
158 | |
159 /** | |
160 * Returns true if the viewer should show a plus sign for expanding this | |
161 * node. | |
162 * | |
163 * @return TODO | |
164 */ | |
165 public bool shouldShowPlus() { | |
166 if (children is null) { | |
167 // if (!hasPendingNode) { | |
168 // hasPendingNode = true; | |
169 // contentProvider.add(element, Collections.singleton(contentProvider.getPendingNode())); | |
170 // } | |
171 return true; | |
172 } | |
173 if (!listeningToChildren && !prefetchEnqueued) { | |
174 prefetchEnqueued = true; | |
175 contentProvider.enqueuePrefetch(this); | |
176 } | |
177 return !listeningToChildren || hasPendingNode || !children.isEmpty(); | |
178 } | |
179 | |
180 /** | |
181 * Disposes this node and removes all remaining children. | |
182 */ | |
183 public void dispose() { | |
184 if (children !is null) { | |
185 if (listeningToChildren) { | |
186 contentProvider.remove(element, children, true); | |
187 children.removeSetChangeListener(this); | |
188 children.removeStaleListener(this); | |
189 } | |
190 children.dispose(); | |
191 children = null; | |
192 | |
193 if (listeningToChildren && isStale) { | |
194 contentProvider.changeStale(-1); | |
195 } | |
196 } | |
197 } | |
198 | |
199 /** | |
200 * @return TODO | |
201 */ | |
202 public bool isDisposed() { | |
203 return children is null; | |
204 } | |
205 | |
206 /** | |
207 * Returns one representative parent, or null if this node is unparented. Use | |
208 * getParents() to get the complete set of known parents. | |
209 * | |
210 * @return TODO | |
211 */ | |
212 public Object getParent() { | |
213 return parent; | |
214 } | |
215 | |
216 /** | |
217 * | |
218 * @return the set of all known parents for this node | |
219 */ | |
220 public Set getParents() { | |
221 if (parents is null) { | |
222 if (parent is null) { | |
223 return Collections.EMPTY_SET; | |
224 } | |
225 return Collections.singleton(parent); | |
226 } | |
227 return parents; | |
228 } | |
229 | |
230 /** | |
231 * Called when the child set changes. Should not be called directly by the viewer. | |
232 */ | |
233 public void handleSetChange(SetChangeEvent event) { | |
234 SetDiff diff = event.diff; | |
235 TreeViewer viewer = this.contentProvider.getViewer(); | |
236 if (viewer !is null) { | |
237 Control control = viewer.getControl(); | |
238 if (control !is null) { | |
239 if (control.isDisposed()) { | |
240 // If the widgetry was disposed without notifying the content provider, then | |
241 // dispose the content provider now and stop processing events. | |
242 contentProvider.dispose(); | |
243 return; | |
244 } | |
245 } | |
246 } | |
247 | |
248 bool shouldHavePendingNode = children.isEmpty() && children.isStale(); | |
249 | |
250 Set additions = diff.getAdditions(); | |
251 // Check if we should add the pending node | |
252 if (shouldHavePendingNode && !hasPendingNode) { | |
253 HashSet newAdditions = new HashSet(); | |
254 newAdditions.addAll(additions); | |
255 newAdditions.add(contentProvider.getPendingNode()); | |
256 additions = newAdditions; | |
257 hasPendingNode = true; | |
258 } | |
259 | |
260 Set removals = diff.getRemovals(); | |
261 // Check if we should remove the pending node | |
262 if (!shouldHavePendingNode && hasPendingNode) { | |
263 HashSet newRemovals = new HashSet(); | |
264 newRemovals.addAll(removals); | |
265 newRemovals.add(contentProvider.getPendingNode()); | |
266 removals = newRemovals; | |
267 hasPendingNode = false; | |
268 } | |
269 if (!additions.isEmpty()) { | |
270 contentProvider.add(element, additions); | |
271 } | |
272 if (!removals.isEmpty()) { | |
273 contentProvider.remove(element, removals, children.isEmpty() && !hasPendingNode); | |
274 } | |
275 | |
276 updateStale(); | |
277 } | |
278 | |
279 public void handleStale(StaleEvent staleEvent) { | |
280 TreeViewer viewer = this.contentProvider.getViewer(); | |
281 if (viewer !is null) { | |
282 Control control = viewer.getControl(); | |
283 if (control !is null) { | |
284 if (control.isDisposed()) { | |
285 // If the widgetry was disposed without notifying the content provider, then | |
286 // dispose the content provider now and stop processing events. | |
287 contentProvider.dispose(); | |
288 return; | |
289 } | |
290 } | |
291 } | |
292 | |
293 bool shouldHavePendingNode = children.isEmpty() && children.isStale(); | |
294 | |
295 // Check if we should add the pending node | |
296 if (shouldHavePendingNode && !hasPendingNode) { | |
297 hasPendingNode = shouldHavePendingNode; | |
298 contentProvider.add(element, Collections.singleton(contentProvider.getPendingNode())); | |
299 } | |
300 | |
301 // Check if we should remove the pending node | |
302 if (!shouldHavePendingNode && hasPendingNode) { | |
303 hasPendingNode = shouldHavePendingNode; | |
304 contentProvider.remove(element, Collections.singleton(contentProvider.getPendingNode()), true); | |
305 } | |
306 | |
307 updateStale(); | |
308 } | |
309 | |
310 /** | |
311 * @return TODO | |
312 */ | |
313 public Object getElement() { | |
314 return element; | |
315 } | |
316 | |
317 /** | |
318 * | |
319 */ | |
320 public void prefetch() { | |
321 TreeViewer viewer = this.contentProvider.getViewer(); | |
322 if (viewer !is null) { | |
323 Control control = viewer.getControl(); | |
324 if (control !is null) { | |
325 if (control.isDisposed()) { | |
326 // If the widgetry has been disposed, then avoid sending anything | |
327 // to the viewer. | |
328 return; | |
329 } | |
330 } | |
331 } | |
332 | |
333 Set children = getChildren(); | |
334 if (!children.isEmpty()) { | |
335 contentProvider.add(element, children); | |
336 } else { | |
337 // We need to remove the + sign, and adding/removing elements won't do the trick | |
338 contentProvider.getViewer().refresh(element); | |
339 } | |
340 } | |
341 } |