KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > internal > databinding > provisional > viewers > TreeNode


1 /*******************************************************************************
2  * Copyright (c) 2006, 2007 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 package org.eclipse.jface.internal.databinding.provisional.viewers;
13
14 import java.util.Collections JavaDoc;
15 import java.util.HashSet JavaDoc;
16 import java.util.Set JavaDoc;
17
18 import org.eclipse.core.databinding.observable.IStaleListener;
19 import org.eclipse.core.databinding.observable.Observables;
20 import org.eclipse.core.databinding.observable.StaleEvent;
21 import org.eclipse.core.databinding.observable.set.IObservableSet;
22 import org.eclipse.core.databinding.observable.set.ISetChangeListener;
23 import org.eclipse.core.databinding.observable.set.SetChangeEvent;
24 import org.eclipse.core.databinding.observable.set.SetDiff;
25 import org.eclipse.jface.viewers.TreeViewer;
26 import org.eclipse.swt.widgets.Control;
27
28 /* package */ class TreeNode implements ISetChangeListener, IStaleListener {
29     private UnorderedTreeContentProvider contentProvider;
30     private Object JavaDoc element;
31     
32     // Stores the set of parents (null if there are less than 2)
33
private HashSet JavaDoc parents = null;
34     
35     // Stores one representative parent. If there is more than one parent,
36
// the complete set of parents can be found in the parents set.
37
Object JavaDoc parent;
38     
39     /**
40      * Set of child elements.
41      */

42     private IObservableSet children;
43     
44     private boolean hasPendingNode = false;
45     private boolean isStale;
46     private boolean listeningToChildren = false;
47     private boolean prefetchEnqueued = false;
48     
49     /**
50      * @param element
51      * @param cp
52      */

53     public TreeNode(Object JavaDoc element, UnorderedTreeContentProvider cp) {
54         this.element = element;
55         this.contentProvider = cp;
56         children = contentProvider.createChildSet(element);
57         if (children == null) {
58             children = Observables.emptyObservableSet();
59             listeningToChildren = true;
60         }
61         hasPendingNode = children.isStale();
62     }
63     
64     /**
65      * @param parent
66      */

67     public void addParent(Object JavaDoc parent) {
68         if (this.parent == null) {
69             this.parent = parent;
70         } else {
71             if (parent.equals(this.parent)) {
72                 return;
73             }
74             if (parents == null) {
75                 parents = new HashSet JavaDoc();
76                 parents.add(this.parent);
77             }
78             parents.add(parent);
79         }
80     }
81     
82     /**
83      * @param parent
84      */

85     public void removeParent(Object JavaDoc parent) {
86         if (this.parents != null) {
87             parents.remove(parent);
88         }
89         
90         if (parent == this.parent) {
91             if (parents == null || parents.isEmpty()) {
92                 this.parent = null;
93             } else {
94                 this.parent = parents.iterator().next();
95             }
96         }
97         
98         if (this.parents != null && this.parents.size() <= 1) {
99             this.parents = null;
100         }
101     }
102     
103     /**
104      * Returns the set of children for this node. If new children are discovered later, they
105      * will be added directly to the viewer.
106      *
107      * @return TODO
108      */

109     public Set JavaDoc getChildren() {
110         if (!listeningToChildren) {
111             listeningToChildren = true;
112             children.addSetChangeListener(this);
113             hasPendingNode = children.isEmpty() && children.isStale();
114             children.addStaleListener(this);
115             updateStale();
116         }
117         
118         // If the child set is stale and empty, show the "pending" node
119
if (hasPendingNode) {
120             Object JavaDoc pendingNode = contentProvider.getPendingNode();
121             return Collections.singleton(pendingNode);
122         }
123         return children;
124     }
125     
126     /**
127      * @return TODO
128      */

129     public IObservableSet getChildrenSet() {
130         return children;
131     }
132     
133     private void updateStale() {
134         boolean willBeStale = children.isStale();
135         if (willBeStale != isStale) {
136             isStale = willBeStale;
137             
138             contentProvider.changeStale(isStale? 1 : -1);
139         }
140     }
141     
142     /**
143      * @return TODO
144      */

145     public boolean isStale() {
146         return isStale;
147     }
148
149     /**
150      * Returns true if the viewer should show a plus sign for expanding this
151      * node.
152      *
153      * @return TODO
154      */

155     public boolean shouldShowPlus() {
156         if (children == null) {
157 // if (!hasPendingNode) {
158
// hasPendingNode = true;
159
// contentProvider.add(element, Collections.singleton(contentProvider.getPendingNode()));
160
// }
161
return true;
162         }
163         if (!listeningToChildren && !prefetchEnqueued) {
164             prefetchEnqueued = true;
165             contentProvider.enqueuePrefetch(this);
166         }
167         return !listeningToChildren || hasPendingNode || !children.isEmpty();
168     }
169     
170     /**
171      * Disposes this node and removes all remaining children.
172      */

173     public void dispose() {
174         if (children != null) {
175             if (listeningToChildren) {
176                 contentProvider.remove(element, children, true);
177                 children.removeSetChangeListener(this);
178                 children.removeStaleListener(this);
179             }
180             children.dispose();
181             children = null;
182             
183             if (listeningToChildren && isStale) {
184                 contentProvider.changeStale(-1);
185             }
186         }
187     }
188     
189     /**
190      * @return TODO
191      */

192     public boolean isDisposed() {
193         return children == null;
194     }
195     
196     /**
197      * Returns one representative parent, or null if this node is unparented. Use
198      * getParents() to get the complete set of known parents.
199      *
200      * @return TODO
201      */

202     public Object JavaDoc getParent() {
203         return parent;
204     }
205     
206     /**
207      *
208      * @return the set of all known parents for this node
209      */

210     public Set JavaDoc getParents() {
211         if (parents == null) {
212             if (parent == null) {
213                 return Collections.EMPTY_SET;
214             } else {
215                 return Collections.singleton(parent);
216             }
217         } else {
218             return parents;
219         }
220     }
221     
222     /**
223      * Called when the child set changes. Should not be called directly by the viewer.
224      */

225     public void handleSetChange(SetChangeEvent event) {
226         SetDiff diff = event.diff;
227         TreeViewer viewer = this.contentProvider.getViewer();
228         if (viewer != null) {
229             Control control = viewer.getControl();
230             if (control != null) {
231                 if (control.isDisposed()) {
232                     // If the widgetry was disposed without notifying the content provider, then
233
// dispose the content provider now and stop processing events.
234
contentProvider.dispose();
235                     return;
236                 }
237             }
238         }
239         
240         boolean shouldHavePendingNode = children.isEmpty() && children.isStale();
241         
242         Set JavaDoc additions = diff.getAdditions();
243         // Check if we should add the pending node
244
if (shouldHavePendingNode && !hasPendingNode) {
245             HashSet JavaDoc newAdditions = new HashSet JavaDoc();
246             newAdditions.addAll(additions);
247             newAdditions.add(contentProvider.getPendingNode());
248             additions = newAdditions;
249             hasPendingNode = true;
250         }
251
252         Set JavaDoc removals = diff.getRemovals();
253         // Check if we should remove the pending node
254
if (!shouldHavePendingNode && hasPendingNode) {
255             HashSet JavaDoc newRemovals = new HashSet JavaDoc();
256             newRemovals.addAll(removals);
257             newRemovals.add(contentProvider.getPendingNode());
258             removals = newRemovals;
259             hasPendingNode = false;
260         }
261         if (!additions.isEmpty()) {
262             contentProvider.add(element, additions);
263         }
264         if (!removals.isEmpty()) {
265             contentProvider.remove(element, removals, children.isEmpty() && !hasPendingNode);
266         }
267         
268         updateStale();
269     }
270
271     public void handleStale(StaleEvent staleEvent) {
272         TreeViewer viewer = this.contentProvider.getViewer();
273         if (viewer != null) {
274             Control control = viewer.getControl();
275             if (control != null) {
276                 if (control.isDisposed()) {
277                     // If the widgetry was disposed without notifying the content provider, then
278
// dispose the content provider now and stop processing events.
279
contentProvider.dispose();
280                     return;
281                 }
282             }
283         }
284         
285         boolean shouldHavePendingNode = children.isEmpty() && children.isStale();
286         
287         // Check if we should add the pending node
288
if (shouldHavePendingNode && !hasPendingNode) {
289             hasPendingNode = shouldHavePendingNode;
290             contentProvider.add(element, Collections.singleton(contentProvider.getPendingNode()));
291         }
292         
293         // Check if we should remove the pending node
294
if (!shouldHavePendingNode && hasPendingNode) {
295             hasPendingNode = shouldHavePendingNode;
296             contentProvider.remove(element, Collections.singleton(contentProvider.getPendingNode()), true);
297         }
298         
299         updateStale();
300     }
301
302     /**
303      * @return TODO
304      */

305     public Object JavaDoc getElement() {
306         return element;
307     }
308
309     /**
310      *
311      */

312     public void prefetch() {
313         TreeViewer viewer = this.contentProvider.getViewer();
314         if (viewer != null) {
315             Control control = viewer.getControl();
316             if (control != null) {
317                 if (control.isDisposed()) {
318                     // If the widgetry has been disposed, then avoid sending anything
319
// to the viewer.
320
return;
321                 }
322             }
323         }
324         
325         Set JavaDoc children = getChildren();
326         if (!children.isEmpty()) {
327             contentProvider.add(element, children);
328         } else {
329             // We need to remove the + sign, and adding/removing elements won't do the trick
330
contentProvider.getViewer().refresh(element);
331         }
332     }
333 }
334
Popular Tags