Mercurial > projects > dwt-addons
annotate dwtx/jface/viewers/AbstractTreeViewer.d @ 104:04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
These new wrappers now use the tango.util.containers instead of the tango.util.collections.
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Thu, 07 Aug 2008 15:01:33 +0200 |
parents | 5df4896124c7 |
children |
rev | line source |
---|---|
10 | 1 /******************************************************************************* |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2 * Copyright (c) 2000, 2008 IBM Corporation and others. |
10 | 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 * Tom Schindl <tom.schindl@bestsolution.at> - bug 153993, bug 167323, bug 175192 | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
11 * Lasse Knudsen, bug 205700 |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
12 * Micah Hainline, bug 210448 |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
13 * Michael Schneider, bug 210747 |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
14 * Bruce Sutton, bug 221768 |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
15 * Matthew Hall, bug 221988 |
10 | 16 * Port to the D programming language: |
17 * Frank Benoit <benoit@tionex.de> | |
18 *******************************************************************************/ | |
19 | |
20 module dwtx.jface.viewers.AbstractTreeViewer; | |
21 | |
22 import dwtx.jface.viewers.ColumnViewer; | |
23 import dwtx.jface.viewers.TreePath; | |
24 import dwtx.jface.viewers.ViewerComparator; | |
25 import dwtx.jface.viewers.ITreeViewerListener; | |
26 import dwtx.jface.viewers.TreeExpansionEvent; | |
27 import dwtx.jface.viewers.CustomHashtable; | |
28 import dwtx.jface.viewers.IContentProvider; | |
29 import dwtx.jface.viewers.ISelection; | |
30 import dwtx.jface.viewers.ColumnViewerEditor; | |
31 import dwtx.jface.viewers.ViewerLabel; | |
32 import dwtx.jface.viewers.ViewerRow; | |
33 import dwtx.jface.viewers.TreePathViewerSorter; | |
34 import dwtx.jface.viewers.ViewerFilter; | |
35 import dwtx.jface.viewers.ViewerColumn; | |
36 import dwtx.jface.viewers.ViewerCell; | |
37 import dwtx.jface.viewers.ITreePathContentProvider; | |
38 import dwtx.jface.viewers.ITreeContentProvider; | |
39 import dwtx.jface.viewers.TreeSelection; | |
40 import dwtx.jface.viewers.DoubleClickEvent; | |
41 import dwtx.jface.viewers.IElementComparer; | |
42 import dwtx.jface.viewers.ITreeSelection; | |
43 import dwtx.jface.viewers.IBaseLabelProvider; | |
44 import dwtx.jface.viewers.ITreePathLabelProvider; | |
45 | |
46 | |
47 | |
48 import dwt.DWT; | |
49 import dwt.custom.BusyIndicator; | |
50 import dwt.events.SelectionEvent; | |
51 import dwt.events.SelectionListener; | |
52 import dwt.events.TreeEvent; | |
53 import dwt.events.TreeListener; | |
54 import dwt.graphics.Point; | |
55 import dwt.widgets.Control; | |
56 import dwt.widgets.Item; | |
57 import dwt.widgets.Widget; | |
58 import dwtx.core.runtime.Assert; | |
59 import dwtx.core.runtime.ListenerList; | |
60 import dwtx.jface.util.SafeRunnable; | |
61 | |
62 import dwt.dwthelper.utils; | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
63 import dwtx.dwtxhelper.Collection; |
10 | 64 import dwt.dwthelper.Runnable; |
65 | |
66 /** | |
67 * Abstract base implementation for tree-structure-oriented viewers (trees and | |
68 * table trees). | |
69 * <p> | |
70 * Nodes in the tree can be in either an expanded or a collapsed state, | |
71 * depending on whether the children on a node are visible. This class | |
72 * introduces public methods for controlling the expanding and collapsing of | |
73 * nodes. | |
74 * </p> | |
75 * <p> | |
76 * As of 3.2, AbstractTreeViewer supports multiple equal elements (each with a | |
77 * different parent chain) in the tree. This support requires that clients | |
78 * enable the element map by calling <code>setUseHashLookup(true)</code>. | |
79 * </p> | |
80 * <p> | |
81 * Content providers for abstract tree viewers must implement one of the | |
82 * interfaces <code>ITreeContentProvider</code> or (as of 3.2, to support | |
83 * multiple equal elements) <code>ITreePathContentProvider</code>. | |
84 * </p> | |
85 * | |
86 * @see TreeViewer | |
87 */ | |
88 public abstract class AbstractTreeViewer : ColumnViewer { | |
89 alias ColumnViewer.buildLabel buildLabel; | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
90 alias ColumnViewer.filter filter; |
10 | 91 alias ColumnViewer.setSelection setSelection; |
92 | |
93 /** | |
94 * Constant indicating that all levels of the tree should be expanded or | |
95 * collapsed. | |
96 * | |
97 * @see #expandToLevel(int) | |
98 * @see #collapseToLevel(Object, int) | |
99 */ | |
100 public static const int ALL_LEVELS = -1; | |
101 | |
102 /** | |
103 * List of registered tree listeners (element type: | |
104 * <code>TreeListener</code>). | |
105 */ | |
106 private ListenerList treeListeners; | |
107 | |
108 /** | |
109 * The level to which the tree is automatically expanded each time the | |
110 * viewer's input is changed (that is, by <code>setInput</code>). A value | |
111 * of 0 means that auto-expand is off. | |
112 * | |
113 * @see #setAutoExpandLevel | |
114 */ | |
115 private int expandToLevel_ = 0; | |
116 | |
117 /** | |
118 * Safe runnable used to update an item. | |
119 */ | |
120 class UpdateItemSafeRunnable : SafeRunnable { | |
121 private Object element; | |
122 | |
123 private Item item; | |
124 | |
125 this(Item item, Object element) { | |
126 this.item = item; | |
127 this.element = element; | |
128 } | |
129 | |
130 public void run() { | |
131 doUpdateItem(item, element); | |
132 } | |
133 | |
134 } | |
135 | |
136 /** | |
137 * Creates an abstract tree viewer. The viewer has no input, no content | |
138 * provider, a default label provider, no sorter, no filters, and has | |
139 * auto-expand turned off. | |
140 */ | |
141 protected this() { | |
142 treeListeners = new ListenerList(); | |
143 // do nothing | |
144 } | |
145 | |
146 /** | |
147 * Adds the given child elements to this viewer as children of the given | |
148 * parent element. If this viewer does not have a sorter, the elements are | |
149 * added at the end of the parent's list of children in the order given; | |
150 * otherwise, the elements are inserted at the appropriate positions. | |
151 * <p> | |
152 * This method should be called (by the content provider) when elements have | |
153 * been added to the model, in order to cause the viewer to accurately | |
154 * reflect the model. This method only affects the viewer, not the model. | |
155 * </p> | |
156 * | |
157 * @param parentElementOrTreePath | |
158 * the parent element | |
159 * @param childElements | |
160 * the child elements to add | |
161 */ | |
162 public void add(Object parentElementOrTreePath, Object[] childElements) { | |
163 Assert.isNotNull(parentElementOrTreePath); | |
164 assertElementsNotNull(childElements); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
165 if (checkBusy()) |
10 | 166 return; |
167 Widget[] widgets = internalFindItems(parentElementOrTreePath); | |
168 // If parent hasn't been realized yet, just ignore the add. | |
169 if (widgets.length is 0) { | |
170 return; | |
171 } | |
172 | |
173 for (int i = 0; i < widgets.length; i++) { | |
174 internalAdd(widgets[i], parentElementOrTreePath, childElements); | |
175 } | |
176 } | |
177 | |
178 /** | |
179 * Find the items for the given element of tree path | |
180 * | |
181 * @param parentElementOrTreePath | |
182 * the element or tree path | |
183 * @return the items for that element | |
184 * | |
185 * @since 3.3 | |
186 */ | |
187 final protected Widget[] internalFindItems(Object parentElementOrTreePath) { | |
188 Widget[] widgets; | |
189 if ( auto path = cast(TreePath) parentElementOrTreePath ) { | |
190 Widget w = internalFindItem(path); | |
191 if (w is null) { | |
192 widgets = null; | |
193 } else { | |
194 widgets = [ w ]; | |
195 } | |
196 } else { | |
197 widgets = findItems(parentElementOrTreePath); | |
198 } | |
199 return widgets; | |
200 } | |
201 | |
202 /** | |
203 * Return the item at the given path or <code>null</code> | |
204 * | |
205 * @param path | |
206 * the path | |
207 * @return {@link Widget} the item at that path | |
208 */ | |
209 private Widget internalFindItem(TreePath path) { | |
210 Widget[] widgets = findItems(path.getLastSegment()); | |
211 for (int i = 0; i < widgets.length; i++) { | |
212 Widget widget = widgets[i]; | |
213 if ( auto item = cast(Item)widget ) { | |
214 TreePath p = getTreePathFromItem(item); | |
215 if (p.opEquals(path)) { | |
216 return widget; | |
217 } | |
218 } | |
219 } | |
220 return null; | |
221 } | |
222 | |
223 /** | |
224 * Adds the given child elements to this viewer as children of the given | |
225 * parent element. | |
226 * <p> | |
227 * EXPERIMENTAL. Not to be used except by JDT. This method was added to | |
228 * support JDT's explorations into grouping by working sets, which requires | |
229 * viewers to support multiple equal elements. See bug 76482 for more | |
230 * details. This support will likely be removed in Eclipse 3.2 in favor of | |
231 * proper support for multiple equal elements. | |
232 * </p> | |
233 * | |
234 * @param widget | |
235 * the widget for the parent element | |
236 * @param parentElementOrTreePath | |
237 * the parent element | |
238 * @param childElements | |
239 * the child elements to add | |
240 * @since 3.1 | |
241 */ | |
242 protected void internalAdd(Widget widget, Object parentElementOrTreePath, | |
243 Object[] childElements) { | |
244 Object parent; | |
245 TreePath path; | |
246 if ( auto path = cast(TreePath) parentElementOrTreePath ) { | |
247 parent = path.getLastSegment(); | |
248 } else { | |
249 parent = parentElementOrTreePath; | |
250 path = null; | |
251 } | |
252 | |
253 // optimization! | |
254 // if the widget is not expanded we just invalidate the subtree | |
255 if ( auto ti = cast(Item)widget ) { | |
256 if (!getExpanded(ti)) { | |
257 bool needDummy = isExpandable(ti, path, parent); | |
258 bool haveDummy = false; | |
259 // remove all children | |
260 Item[] items = getItems(ti); | |
261 for (int i = 0; i < items.length; i++) { | |
262 if (items[i].getData() !is null) { | |
263 disassociate(items[i]); | |
264 items[i].dispose(); | |
265 } else { | |
266 if (needDummy && !haveDummy) { | |
267 haveDummy = true; | |
268 } else { | |
269 items[i].dispose(); | |
270 } | |
271 } | |
272 } | |
273 // append a dummy if necessary | |
274 if (needDummy && !haveDummy) { | |
275 newItem(ti, DWT.NULL, -1); | |
276 } | |
277 return; | |
278 } | |
279 } | |
280 | |
281 if (childElements.length > 0) { | |
282 // TODO: Add filtering back? | |
283 Object[] filtered = filter(parentElementOrTreePath, childElements); | |
284 ViewerComparator comparator = getComparator(); | |
285 if (comparator !is null) { | |
286 if ( auto tpvs = cast(TreePathViewerSorter) comparator ) { | |
287 if (path is null) { | |
288 path = internalGetSorterParentPath(widget, comparator); | |
289 } | |
290 tpvs.sort(this, path, filtered); | |
291 } else { | |
292 comparator.sort(this, filtered); | |
293 } | |
294 } | |
295 createAddedElements(widget, filtered); | |
296 } | |
297 } | |
298 | |
299 /** | |
300 * Filter the children elements. | |
301 * | |
302 * @param parentElementOrTreePath | |
303 * the parent element or path | |
304 * @param elements | |
305 * the child elements | |
306 * @return the filter list of children | |
307 */ | |
308 private Object[] filter(Object parentElementOrTreePath, Object[] elements) { | |
309 ViewerFilter[] filters = getFilters(); | |
310 if (filters !is null) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
311 ArrayList filtered = new ArrayList(elements.length); |
10 | 312 for (int i = 0; i < elements.length; i++) { |
313 bool add = true; | |
314 for (int j = 0; j < filters.length; j++) { | |
315 add = filters[j].select(this, parentElementOrTreePath, | |
316 elements[i]); | |
317 if (!add) { | |
318 break; | |
319 } | |
320 } | |
321 if (add) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
322 filtered.add(elements[i]); |
10 | 323 } |
324 } | |
325 return filtered.toArray(); | |
326 } | |
327 return elements; | |
328 } | |
329 | |
330 /** | |
331 * Create the new elements in the parent widget. If the child already exists | |
332 * do nothing. | |
333 * | |
334 * @param widget | |
335 * @param elements | |
336 * Sorted list of elements to add. | |
337 */ | |
338 private void createAddedElements(Widget widget, Object[] elements) { | |
339 | |
340 if (elements.length is 1) { | |
341 if (opEquals(elements[0], widget.getData())) { | |
342 return; | |
343 } | |
344 } | |
345 | |
346 ViewerComparator comparator = getComparator(); | |
347 TreePath parentPath = internalGetSorterParentPath(widget, comparator); | |
348 Item[] items = getChildren(widget); | |
349 | |
350 // Optimize for the empty case | |
351 if (items.length is 0) { | |
352 for (int i = 0; i < elements.length; i++) { | |
353 createTreeItem(widget, elements[i], -1); | |
354 } | |
355 return; | |
356 } | |
357 | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
358 // Optimize for no comparator |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
359 if (comparator is null) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
360 for (int i = 0; i < elements.length; i++) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
361 Object element = elements[i]; |
10 | 362 if (itemExists(items, element)) { |
363 internalRefresh(element); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
364 } else { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
365 createTreeItem(widget, element, -1); |
10 | 366 } |
367 } | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
368 return; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
369 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
370 // As the items are sorted already we optimize for a |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
371 // start position. This is the insertion position relative to the |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
372 // original item array. |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
373 int indexInItems = 0; |
71 | 374 |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
375 // Count of elements we have added. See bug 205700 for why this is needed. |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
376 int newItems = 0; |
71 | 377 |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
378 elementloop: for (int i = 0; i < elements.length; i++) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
379 Object element = elements[i]; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
380 // update the index relative to the original item array |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
381 indexInItems = insertionPosition(items, comparator, |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
382 indexInItems, element, parentPath); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
383 if (indexInItems is items.length) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
384 createTreeItem(widget, element, -1); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
385 newItems++; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
386 } else { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
387 // Search for an item for the element. The comparator might |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
388 // regard elements as equal when they are not. |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
389 |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
390 // Use a separate index variable to search within the existing |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
391 // elements that compare equally, see |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
392 // TreeViewerTestBug205700.testAddEquallySortedElements. |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
393 int insertionIndexInItems = indexInItems; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
394 while( insertionIndexInItems < items.length |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
395 && internalCompare(comparator, parentPath, element, |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
396 items[insertionIndexInItems].getData()) is 0) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
397 // As we cannot assume the sorter is consistent with |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
398 // equals() - therefore we can |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
399 // just check against the item prior to this index (if |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
400 // any) |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
401 if (items[insertionIndexInItems].getData().opEquals(element)) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
402 // Found the item for the element. |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
403 // Refresh the element in case it has new children. |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
404 internalRefresh(element); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
405 // Do not create a new item - continue with the next element. |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
406 continue elementloop; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
407 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
408 insertionIndexInItems++; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
409 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
410 // Did we get to the end? |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
411 if (insertionIndexInItems is items.length) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
412 createTreeItem(widget, element, -1); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
413 newItems++; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
414 } else { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
415 // InsertionIndexInItems is the index in the original array. We |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
416 // need to correct by the number of new items we have |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
417 // created. See bug 205700. |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
418 createTreeItem(widget, element, insertionIndexInItems + newItems); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
419 newItems++; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
420 } |
10 | 421 } |
422 } | |
423 } | |
424 | |
425 /** | |
426 * See if element is the data of one of the elements in items. | |
427 * | |
428 * @param items | |
429 * @param element | |
430 * @return <code>true</code> if the element matches. | |
431 */ | |
432 private bool itemExists(Item[] items, Object element) { | |
433 if (usingElementMap()) { | |
434 Widget[] existingItems = findItems(element); | |
435 // optimization for two common cases | |
436 if (existingItems.length is 0) { | |
437 return false; | |
438 } else if (existingItems.length is 1) { | |
439 if (items.length > 0 && null !is cast(Item)existingItems[0] ) { | |
440 Item existingItem = cast(Item) existingItems[0]; | |
441 return getParentItem(existingItem) is getParentItem(items[0]); | |
442 } | |
443 } | |
444 } | |
445 for (int i = 0; i < items.length; i++) { | |
446 if (items[i].getData().opEquals(element)) { | |
447 return true; | |
448 } | |
449 } | |
450 return false; | |
451 } | |
452 | |
453 /** | |
454 * Returns the index where the item should be inserted. It uses sorter to | |
455 * determine the correct position, if sorter is not assigned, returns the | |
456 * index of the element after the last. | |
457 * | |
458 * @param items | |
459 * the items to search | |
460 * @param comparator | |
461 * The comparator to use. | |
462 * @param lastInsertion | |
463 * the start index to start search for position from this allows | |
464 * optimizing search for multiple elements that are sorted | |
465 * themselves. | |
466 * @param element | |
467 * element to find position for. | |
468 * @param parentPath | |
469 * the tree path for the element's parent or <code>null</code> | |
470 * if the element is a root element or the sorter is not a | |
471 * {@link TreePathViewerSorter} | |
472 * @return the index to use when inserting the element. | |
473 * | |
474 */ | |
475 | |
476 private int insertionPosition(Item[] items, ViewerComparator comparator, | |
477 int lastInsertion, Object element, TreePath parentPath) { | |
478 | |
479 int size = items.length; | |
480 if (comparator is null) { | |
481 return size; | |
482 } | |
483 int min = lastInsertion, max = size - 1; | |
484 | |
485 while (min <= max) { | |
486 int mid = (min + max) / 2; | |
487 Object data = items[mid].getData(); | |
488 int compare = internalCompare(comparator, parentPath, data, element); | |
489 if (compare is 0) { | |
490 return mid;// Return if we already match | |
491 } | |
492 if (compare < 0) { | |
493 min = mid + 1; | |
494 } else { | |
495 max = mid - 1; | |
496 } | |
497 } | |
498 return min; | |
499 | |
500 } | |
501 | |
502 /** | |
503 * Returns the index where the item should be inserted. It uses sorter to | |
504 * determine the correct position, if sorter is not assigned, returns the | |
505 * index of the element after the last. | |
506 * | |
507 * @param parent | |
508 * The parent widget | |
509 * @param sorter | |
510 * The sorter to use. | |
511 * @param startIndex | |
512 * the start index to start search for position from this allows | |
513 * optimizing search for multiple elements that are sorted | |
514 * themselves. | |
515 * @param element | |
516 * element to find position for. | |
517 * @param currentSize | |
518 * the current size of the collection | |
519 * @return the index to use when inserting the element. | |
520 * | |
521 */ | |
522 | |
523 /** | |
524 * Returns the index where the item should be inserted. | |
525 * | |
526 * @param parent | |
527 * The parent widget the element will be inserted into. | |
528 * @param element | |
529 * The element to insert. | |
530 * @return the index of the element | |
531 */ | |
532 protected int indexForElement(Widget parent, Object element) { | |
533 ViewerComparator comparator = getComparator(); | |
534 TreePath parentPath = internalGetSorterParentPath(parent, comparator); | |
535 | |
536 Item[] items = getChildren(parent); | |
537 int count = items.length; | |
538 | |
539 if (comparator is null) { | |
540 return count; | |
541 } | |
542 int min = 0, max = count - 1; | |
543 | |
544 while (min <= max) { | |
545 int mid = (min + max) / 2; | |
546 Object data = items[mid].getData(); | |
547 int compare = internalCompare(comparator, parentPath, data, element); | |
548 if (compare is 0) { | |
549 // find first item > element | |
550 while (compare is 0) { | |
551 ++mid; | |
552 if (mid >= count) { | |
553 break; | |
554 } | |
555 data = items[mid].getData(); | |
556 compare = internalCompare(comparator, parentPath, data, | |
557 element); | |
558 } | |
559 return mid; | |
560 } | |
561 if (compare < 0) { | |
562 min = mid + 1; | |
563 } else { | |
564 max = mid - 1; | |
565 } | |
566 } | |
567 return min; | |
568 } | |
569 | |
570 /** | |
571 * Return the tree path that should be used as the parent path for the given | |
572 * widget and sorter. A <code>null</code> is returned if either the sorter | |
573 * is not a {@link TreePathViewerSorter} or if the parent widget is not an | |
574 * {@link Item} (i.e. is the root of the tree). | |
575 * | |
576 * @param parent | |
577 * the parent widget | |
578 * @param comparator | |
579 * the sorter | |
580 * @return the tree path that should be used as the parent path for the | |
581 * given widget and sorter | |
582 */ | |
583 private TreePath internalGetSorterParentPath(Widget parent, | |
584 ViewerComparator comparator) { | |
585 TreePath path; | |
586 if ( null !is cast(TreePathViewerSorter)comparator | |
587 && null !is cast(Item)parent ) { | |
588 Item item = cast(Item) parent; | |
589 path = getTreePathFromItem(item); | |
590 } else { | |
591 path = null; | |
592 } | |
593 return path; | |
594 } | |
595 | |
596 /** | |
597 * Compare the two elements using the given sorter. If the sorter is a | |
598 * {@link TreePathViewerSorter}, the provided tree path will be used. If | |
599 * the tree path is null and the sorter is a tree path sorter, then the | |
600 * elements are root elements | |
601 * | |
602 * @param comparator | |
603 * the sorter | |
604 * @param parentPath | |
605 * the path of the elements' parent | |
606 * @param e1 | |
607 * the first element | |
608 * @param e2 | |
609 * the second element | |
610 * @return the result of comparing the two elements | |
611 */ | |
612 private int internalCompare(ViewerComparator comparator, | |
613 TreePath parentPath, Object e1, Object e2) { | |
614 if ( auto tpvs = cast(TreePathViewerSorter) comparator ) { | |
615 return tpvs.compare(this, parentPath, e1, e2); | |
616 } | |
617 return comparator.compare(this, e1, e2); | |
618 } | |
619 | |
620 /* | |
621 * (non-Javadoc) | |
622 * | |
623 * @see dwtx.jface.viewers.StructuredViewer#getSortedChildren(java.lang.Object) | |
624 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
625 protected override Object[] getSortedChildren(Object parentElementOrTreePath) { |
10 | 626 Object[] result = getFilteredChildren(parentElementOrTreePath); |
627 ViewerComparator comparator = getComparator(); | |
628 if (parentElementOrTreePath !is null | |
629 && null !is cast(TreePathViewerSorter) comparator ) { | |
630 TreePathViewerSorter tpvs = cast(TreePathViewerSorter) comparator; | |
631 | |
632 // be sure we're not modifying the original array from the model | |
633 result = result.dup; | |
634 | |
635 TreePath path = null; | |
636 if ( auto p = cast(TreePath) parentElementOrTreePath ) { | |
637 path = p; | |
638 } else { | |
639 Object parent = parentElementOrTreePath; | |
640 Widget w = internalGetWidgetToSelect(parent); | |
641 if (w !is null) { | |
642 path = internalGetSorterParentPath(w, comparator); | |
643 } | |
644 } | |
645 tpvs.sort(this, path, result); | |
646 } else if (comparator !is null) { | |
647 // be sure we're not modifying the original array from the model | |
648 result = result.dup; | |
649 comparator.sort(this, result); | |
650 } | |
651 return result; | |
652 } | |
653 | |
654 /* | |
655 * (non-Javadoc) | |
656 * | |
657 * @see dwtx.jface.viewers.StructuredViewer#getFilteredChildren(java.lang.Object) | |
658 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
659 protected override Object[] getFilteredChildren(Object parentElementOrTreePath) { |
10 | 660 Object[] result = getRawChildren(parentElementOrTreePath); |
661 ViewerFilter[] filters = getFilters(); | |
662 for (int i = 0; i < filters.length; i++) { | |
663 ViewerFilter filter = filters[i]; | |
664 result = filter.filter(this, parentElementOrTreePath, result); | |
665 } | |
666 return result; | |
667 } | |
668 | |
669 /** | |
670 * Adds the given child element to this viewer as a child of the given | |
671 * parent element. If this viewer does not have a sorter, the element is | |
672 * added at the end of the parent's list of children; otherwise, the element | |
673 * is inserted at the appropriate position. | |
674 * <p> | |
675 * This method should be called (by the content provider) when a single | |
676 * element has been added to the model, in order to cause the viewer to | |
677 * accurately reflect the model. This method only affects the viewer, not | |
678 * the model. Note that there is another method for efficiently processing | |
679 * the simultaneous addition of multiple elements. | |
680 * </p> | |
681 * | |
682 * @param parentElementOrTreePath | |
683 * the parent element or path | |
684 * @param childElement | |
685 * the child element | |
686 */ | |
687 public void add(Object parentElementOrTreePath, Object childElement) { | |
688 add(parentElementOrTreePath, [ childElement ]); | |
689 } | |
690 | |
691 /** | |
692 * Adds the given DWT selection listener to the given DWT control. | |
693 * | |
694 * @param control | |
695 * the DWT control | |
696 * @param listener | |
697 * the DWT selection listener | |
698 * @deprecated | |
699 */ | |
700 protected void addSelectionListener(Control control, | |
701 SelectionListener listener) { | |
702 // do nothing | |
703 } | |
704 | |
705 /** | |
706 * Adds a listener for expand and collapse events in this viewer. Has no | |
707 * effect if an identical listener is already registered. | |
708 * | |
709 * @param listener | |
710 * a tree viewer listener | |
711 */ | |
712 public void addTreeListener(ITreeViewerListener listener) { | |
713 treeListeners.add(cast(Object)listener); | |
714 } | |
715 | |
716 /** | |
717 * Adds the given DWT tree listener to the given DWT control. | |
718 * | |
719 * @param control | |
720 * the DWT control | |
721 * @param listener | |
722 * the DWT tree listener | |
723 */ | |
724 protected abstract void addTreeListener(Control control, | |
725 TreeListener listener); | |
726 | |
727 /* | |
728 * (non-Javadoc) | |
729 * | |
730 * @see StructuredViewer#associate(Object, Item) | |
731 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
732 protected override void associate(Object element, Item item) { |
10 | 733 Object data = item.getData(); |
734 if (data !is null && data !is element && opEquals(data, element)) { | |
735 // workaround for PR 1FV62BT | |
736 // assumption: elements are equal but not identical | |
737 // -> remove from map but don't touch children | |
738 unmapElement(data, item); | |
739 item.setData(element); | |
740 mapElement(element, item); | |
741 } else { | |
742 // recursively disassociate all | |
743 super.associate(element, item); | |
744 } | |
745 } | |
746 | |
747 /** | |
748 * Collapses all nodes of the viewer's tree, starting with the root. This | |
749 * method is equivalent to <code>collapseToLevel(ALL_LEVELS)</code>. | |
750 */ | |
751 public void collapseAll() { | |
752 Object root = getRoot(); | |
753 if (root !is null) { | |
754 collapseToLevel(root, ALL_LEVELS); | |
755 } | |
756 } | |
757 | |
758 /** | |
759 * Collapses the subtree rooted at the given element or tree path to the | |
760 * given level. | |
761 * | |
762 * @param elementOrTreePath | |
763 * the element or tree path | |
764 * @param level | |
765 * non-negative level, or <code>ALL_LEVELS</code> to collapse | |
766 * all levels of the tree | |
767 */ | |
768 public void collapseToLevel(Object elementOrTreePath, int level) { | |
769 Assert.isNotNull(elementOrTreePath); | |
770 Widget w = internalGetWidgetToSelect(elementOrTreePath); | |
771 if (w !is null) { | |
772 internalCollapseToLevel(w, level); | |
773 } | |
774 } | |
775 | |
776 /** | |
777 * Creates all children for the given widget. | |
778 * <p> | |
779 * The default implementation of this framework method assumes that | |
780 * <code>widget.getData()</code> returns the element corresponding to the | |
781 * node. Note: the node is not visually expanded! You may have to call | |
782 * <code>parent.setExpanded(true)</code>. | |
783 * </p> | |
784 * | |
785 * @param widget | |
786 * the widget | |
787 */ | |
788 protected void createChildren(Widget widget) { | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
789 bool oldBusy = isBusy(); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
790 setBusy(true); |
10 | 791 try { |
54
a6683645b0d7
Fix ignored labelprovider for TreeViewer (See WrapperViewerLabelProvider.d), removed the debugging prints
Frank Benoit <benoit@tionex.de>
parents:
53
diff
changeset
|
792 Item[] tis = getChildren(widget); |
10 | 793 if (tis !is null && tis.length > 0) { |
794 Object data = tis[0].getData(); | |
795 if (data !is null) { | |
796 return; // children already there! | |
797 } | |
798 } | |
799 | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
800 BusyIndicator.showWhile(widget.getDisplay(), dgRunnable( (Widget widget_, Item[] tis_){ |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
801 // fix for PR 1FW89L7: |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
802 // don't complain and remove all "dummies" ... |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
803 if (tis_ !is null) { |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
804 for (int i = 0; i < tis_.length; i++) { |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
805 if (tis_[i].getData() !is null) { |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
806 disassociate(tis_[i]); |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
807 Assert.isTrue(tis_[i].getData() is null, |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
808 "Second or later child is non -null");//$NON-NLS-1$ |
10 | 809 |
810 } | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
811 tis_[i].dispose(); |
10 | 812 } |
813 } | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
814 Object d = widget_.getData(); |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
815 if (d !is null) { |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
816 Object parentElement = d; |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
817 Object[] children; |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
818 if (isTreePathContentProvider() && (null !is cast(Item)widget_) ) { |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
819 TreePath path = getTreePathFromItem(cast(Item) widget_); |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
820 children = getSortedChildren(path); |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
821 } else { |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
822 children = getSortedChildren(parentElement); |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
823 } |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
824 for (int i = 0; i < children.length; i++) { |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
825 createTreeItem(widget_, children[i], -1); |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
826 } |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
827 } |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
828 }, widget,tis )); |
10 | 829 } finally { |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
830 setBusy(oldBusy); |
10 | 831 } |
832 } | |
833 | |
834 /** | |
835 * Creates a single item for the given parent and synchronizes it with the | |
836 * given element. | |
837 * | |
838 * @param parent | |
839 * the parent widget | |
840 * @param element | |
841 * the element | |
842 * @param index | |
843 * if non-negative, indicates the position to insert the item | |
844 * into its parent | |
845 */ | |
846 protected void createTreeItem(Widget parent, Object element, int index) { | |
847 Item item = newItem(parent, DWT.NULL, index); | |
848 updateItem(item, element); | |
849 updatePlus(item, element); | |
850 } | |
851 | |
852 /** | |
853 * The <code>AbstractTreeViewer</code> implementation of this method also | |
854 * recurses over children of the corresponding element. | |
855 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
856 protected override void disassociate(Item item) { |
10 | 857 super.disassociate(item); |
858 // recursively unmapping the items is only required when | |
859 // the hash map is used. In the other case disposing | |
860 // an item will recursively dispose its children. | |
861 if (usingElementMap()) { | |
862 disassociateChildren(item); | |
863 } | |
864 } | |
865 | |
866 /** | |
867 * Disassociates the children of the given DWT item from their corresponding | |
868 * elements. | |
869 * | |
870 * @param item | |
871 * the widget | |
872 */ | |
873 private void disassociateChildren(Item item) { | |
874 Item[] items = getChildren(item); | |
875 for (int i = 0; i < items.length; i++) { | |
876 if (items[i].getData() !is null) { | |
877 disassociate(items[i]); | |
878 } | |
879 } | |
880 } | |
881 | |
882 /* (non-Javadoc) Method declared on StructuredViewer. */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
883 protected override Widget doFindInputItem(Object element) { |
10 | 884 // compare with root |
885 Object root = getRoot(); | |
886 if (root is null) { | |
887 return null; | |
888 } | |
889 | |
890 if (opEquals(root, element)) { | |
891 return getControl(); | |
892 } | |
893 return null; | |
894 } | |
895 | |
896 /* (non-Javadoc) Method declared on StructuredViewer. */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
897 protected override Widget doFindItem(Object element) { |
10 | 898 // compare with root |
899 Object root = getRoot(); | |
900 if (root is null) { | |
901 return null; | |
902 } | |
903 | |
904 Item[] items = getChildren(getControl()); | |
905 if (items !is null) { | |
906 for (int i = 0; i < items.length; i++) { | |
907 Widget o = internalFindItem(items[i], element); | |
908 if (o !is null) { | |
909 return o; | |
910 } | |
911 } | |
912 } | |
913 return null; | |
914 } | |
915 | |
916 /** | |
917 * Copies the attributes of the given element into the given DWT item. | |
918 * | |
919 * @param item | |
920 * the DWT item | |
921 * @param element | |
922 * the element | |
923 */ | |
924 protected void doUpdateItem(Item item, Object element) { | |
925 if (item.isDisposed()) { | |
926 unmapElement(element, item); | |
927 return; | |
928 } | |
929 | |
930 int columnCount = doGetColumnCount(); | |
931 if (columnCount is 0)// If no columns are created then fake one | |
932 columnCount = 1; | |
933 | |
934 ViewerRow viewerRowFromItem = getViewerRowFromItem(item); | |
935 | |
936 bool isVirtual = (getControl().getStyle() & DWT.VIRTUAL) !is 0; | |
937 | |
938 // If the control is virtual, we cannot use the cached viewer row object. See bug 188663. | |
939 if (isVirtual) { | |
940 viewerRowFromItem = cast(ViewerRow) viewerRowFromItem.clone(); | |
941 } | |
942 | |
943 for (int column = 0; column < columnCount; column++) { | |
944 ViewerColumn columnViewer = getViewerColumn(column); | |
945 ViewerCell cellToUpdate = updateCell(viewerRowFromItem, column, | |
946 element); | |
947 | |
948 // If the control is virtual, we cannot use the cached cell object. See bug 188663. | |
949 if (isVirtual) { | |
950 cellToUpdate = new ViewerCell(cellToUpdate.getViewerRow(), cellToUpdate.getColumnIndex(), element); | |
951 } | |
952 | |
953 columnViewer.refresh(cellToUpdate); | |
954 | |
955 // clear cell (see bug 201280) | |
956 updateCell(null, 0, null); | |
957 | |
958 // As it is possible for user code to run the event | |
959 // loop check here. | |
960 if (item.isDisposed()) { | |
961 unmapElement(element, item); | |
962 return; | |
963 } | |
964 | |
965 } | |
966 } | |
967 | |
968 /** | |
969 * Returns <code>true</code> if the given list and array of items refer to | |
970 * the same model elements. Order is unimportant. | |
971 * <p> | |
972 * This method is not intended to be overridden by subclasses. | |
973 * </p> | |
974 * | |
975 * @param items | |
976 * the list of items | |
977 * @param current | |
978 * the array of items | |
979 * @return <code>true</code> if the refer to the same elements, | |
980 * <code>false</code> otherwise | |
981 * | |
982 * @since 3.1 in TreeViewer, moved to AbstractTreeViewer in 3.3 | |
983 */ | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
984 protected bool isSameSelection(List items, Item[] current) { |
10 | 985 // If they are not the same size then they are not equivalent |
986 int n = items.size(); | |
987 if (n !is current.length) { | |
988 return false; | |
989 } | |
990 | |
991 CustomHashtable itemSet = newHashtable(n * 2 + 1); | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
992 for (Iterator i = items.iterator(); i.hasNext();) { |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
993 Item item = cast(Item) i.next(); |
10 | 994 Object element = item.getData(); |
995 itemSet.put(element, element); | |
996 } | |
997 | |
998 // Go through the items of the current collection | |
999 // If there is a mismatch return false | |
1000 for (int i = 0; i < current.length; i++) { | |
1001 if (current[i].getData() is null | |
1002 || !itemSet.containsKey(current[i].getData())) { | |
1003 return false; | |
1004 } | |
1005 } | |
1006 | |
1007 return true; | |
1008 } | |
1009 | |
1010 | |
1011 | |
1012 /* (non-Javadoc) Method declared on StructuredViewer. */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1013 protected override void doUpdateItem(Widget widget, Object element, bool fullMap) { |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1014 bool oldBusy = isBusy(); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1015 setBusy(true); |
10 | 1016 try { |
1017 if ( auto item = cast(Item)widget ) { | |
1018 | |
1019 // ensure that back pointer is correct | |
1020 if (fullMap) { | |
1021 associate(element, item); | |
1022 } else { | |
1023 Object data = item.getData(); | |
1024 if (data !is null) { | |
1025 unmapElement(data, item); | |
1026 } | |
1027 item.setData(element); | |
1028 mapElement(element, item); | |
1029 } | |
1030 | |
1031 // update icon and label | |
1032 SafeRunnable.run(new UpdateItemSafeRunnable(item, element)); | |
1033 } | |
1034 } finally { | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1035 setBusy(oldBusy); |
10 | 1036 } |
1037 } | |
1038 | |
1039 /** | |
1040 * Expands all nodes of the viewer's tree, starting with the root. This | |
1041 * method is equivalent to <code>expandToLevel(ALL_LEVELS)</code>. | |
1042 */ | |
1043 public void expandAll() { | |
1044 expandToLevel(ALL_LEVELS); | |
1045 } | |
1046 | |
1047 /** | |
1048 * Expands the root of the viewer's tree to the given level. | |
1049 * | |
1050 * @param level | |
1051 * non-negative level, or <code>ALL_LEVELS</code> to expand all | |
1052 * levels of the tree | |
1053 */ | |
1054 public void expandToLevel(int level) { | |
1055 expandToLevel(getRoot(), level); | |
1056 } | |
1057 | |
1058 /** | |
1059 * Expands all ancestors of the given element or tree path so that the given | |
1060 * element becomes visible in this viewer's tree control, and then expands | |
1061 * the subtree rooted at the given element to the given level. | |
1062 * | |
1063 * @param elementOrTreePath | |
1064 * the element | |
1065 * @param level | |
1066 * non-negative level, or <code>ALL_LEVELS</code> to expand all | |
1067 * levels of the tree | |
1068 */ | |
1069 public void expandToLevel(Object elementOrTreePath, int level) { | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1070 if (checkBusy()) |
10 | 1071 return; |
1072 Widget w = internalExpand(elementOrTreePath, true); | |
1073 if (w !is null) { | |
1074 internalExpandToLevel(w, level); | |
1075 } | |
1076 } | |
1077 | |
1078 /** | |
1079 * Fires a tree collapsed event. Only listeners registered at the time this | |
1080 * method is called are notified. | |
1081 * | |
1082 * @param event | |
1083 * the tree expansion event | |
1084 * @see ITreeViewerListener#treeCollapsed | |
1085 */ | |
1086 protected void fireTreeCollapsed(TreeExpansionEvent event) { | |
1087 Object[] listeners = treeListeners.getListeners(); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1088 bool oldBusy = isBusy(); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1089 setBusy(true); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1090 try { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1091 for (int i = 0; i < listeners.length; ++i) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1092 SafeRunnable.run(new class(event,cast(ITreeViewerListener) listeners[i]) SafeRunnable { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1093 TreeExpansionEvent event_; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1094 ITreeViewerListener l; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1095 this(TreeExpansionEvent a,ITreeViewerListener b){ |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1096 event_=a; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1097 l = b; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1098 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1099 public void run() { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1100 l.treeCollapsed(event_); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1101 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1102 }); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1103 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1104 } finally { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1105 setBusy(oldBusy); |
10 | 1106 } |
1107 } | |
1108 | |
1109 /** | |
1110 * Fires a tree expanded event. Only listeners registered at the time this | |
1111 * method is called are notified. | |
1112 * | |
1113 * @param event | |
1114 * the tree expansion event | |
1115 * @see ITreeViewerListener#treeExpanded | |
1116 */ | |
1117 protected void fireTreeExpanded(TreeExpansionEvent event) { | |
1118 Object[] listeners = treeListeners.getListeners(); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1119 bool oldBusy = isBusy(); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1120 setBusy(true); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1121 try { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1122 for (int i = 0; i < listeners.length; ++i) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1123 SafeRunnable.run(new class( event, cast(ITreeViewerListener) listeners[i]) SafeRunnable { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1124 TreeExpansionEvent event_; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1125 ITreeViewerListener l; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1126 this(TreeExpansionEvent a,ITreeViewerListener b){ |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1127 event_=a; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1128 l = b; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1129 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1130 public void run() { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1131 l.treeExpanded(event_); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1132 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1133 }); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1134 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1135 } finally { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1136 setBusy(oldBusy); |
10 | 1137 } |
1138 } | |
1139 | |
1140 /** | |
1141 * Returns the auto-expand level. | |
1142 * | |
1143 * @return non-negative level, or <code>ALL_LEVELS</code> if all levels of | |
1144 * the tree are expanded automatically | |
1145 * @see #setAutoExpandLevel | |
1146 */ | |
1147 public int getAutoExpandLevel() { | |
1148 return expandToLevel_; | |
1149 } | |
1150 | |
1151 /** | |
1152 * Returns the DWT child items for the given DWT widget. | |
1153 * | |
1154 * @param widget | |
1155 * the widget | |
1156 * @return the child items | |
1157 */ | |
1158 protected abstract Item[] getChildren(Widget widget); | |
1159 | |
1160 /** | |
1161 * Get the child for the widget at index. Note that the default | |
1162 * implementation is not very efficient and should be overridden if this | |
1163 * class is implemented. | |
1164 * | |
1165 * @param widget | |
1166 * the widget to check | |
1167 * @param index | |
1168 * the index of the widget | |
1169 * @return Item or <code>null</code> if widget is not a type that can | |
1170 * contain items. | |
1171 * | |
1172 * @throws ArrayIndexOutOfBoundsException | |
1173 * if the index is not valid. | |
1174 * @since 3.1 | |
1175 */ | |
1176 protected Item getChild(Widget widget, int index) { | |
1177 return getChildren(widget)[index]; | |
1178 } | |
1179 | |
1180 /** | |
1181 * Returns whether the given DWT item is expanded or collapsed. | |
1182 * | |
1183 * @param item | |
1184 * the item | |
1185 * @return <code>true</code> if the item is considered expanded and | |
1186 * <code>false</code> if collapsed | |
1187 */ | |
1188 protected abstract bool getExpanded(Item item); | |
1189 | |
1190 /** | |
1191 * Returns a list of elements corresponding to expanded nodes in this | |
1192 * viewer's tree, including currently hidden ones that are marked as | |
1193 * expanded but are under a collapsed ancestor. | |
1194 * <p> | |
1195 * This method is typically used when preserving the interesting state of a | |
1196 * viewer; <code>setExpandedElements</code> is used during the restore. | |
1197 * </p> | |
1198 * | |
1199 * @return the array of expanded elements | |
1200 * @see #setExpandedElements | |
1201 */ | |
1202 public Object[] getExpandedElements() { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1203 ArrayList items = new ArrayList(); |
10 | 1204 internalCollectExpandedItems(items, getControl()); |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1205 ArrayList result = new ArrayList(items.size()); |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1206 for (Iterator it = items.iterator(); it.hasNext();) { |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1207 Item item = cast(Item) it.next(); |
10 | 1208 Object data = item.getData(); |
1209 if (data !is null) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1210 result.add(data); |
10 | 1211 } |
1212 } | |
1213 return result.toArray(); | |
1214 } | |
1215 | |
1216 /** | |
1217 * Returns whether the node corresponding to the given element or tree path | |
1218 * is expanded or collapsed. | |
1219 * | |
1220 * @param elementOrTreePath | |
1221 * the element | |
1222 * @return <code>true</code> if the node is expanded, and | |
1223 * <code>false</code> if collapsed | |
1224 */ | |
1225 public bool getExpandedState(Object elementOrTreePath) { | |
1226 Assert.isNotNull(elementOrTreePath); | |
1227 Widget item = internalGetWidgetToSelect(elementOrTreePath); | |
1228 if ( auto i = cast(Item)item ) { | |
1229 return getExpanded(i); | |
1230 } | |
1231 return false; | |
1232 } | |
1233 | |
1234 /** | |
1235 * Returns the number of child items of the given DWT control. | |
1236 * | |
1237 * @param control | |
1238 * the control | |
1239 * @return the number of children | |
1240 */ | |
1241 protected abstract int getItemCount(Control control); | |
1242 | |
1243 /** | |
1244 * Returns the number of child items of the given DWT item. | |
1245 * | |
1246 * @param item | |
1247 * the item | |
1248 * @return the number of children | |
1249 */ | |
1250 protected abstract int getItemCount(Item item); | |
1251 | |
1252 /** | |
1253 * Returns the child items of the given DWT item. | |
1254 * | |
1255 * @param item | |
1256 * the item | |
1257 * @return the child items | |
1258 */ | |
1259 protected abstract Item[] getItems(Item item); | |
1260 | |
1261 /** | |
1262 * Returns the item after the given item in the tree, or <code>null</code> | |
1263 * if there is no next item. | |
1264 * | |
1265 * @param item | |
1266 * the item | |
1267 * @param includeChildren | |
1268 * <code>true</code> if the children are considered in | |
1269 * determining which item is next, and <code>false</code> if | |
1270 * subtrees are ignored | |
1271 * @return the next item, or <code>null</code> if none | |
1272 */ | |
1273 protected Item getNextItem(Item item, bool includeChildren) { | |
1274 if (item is null) { | |
1275 return null; | |
1276 } | |
1277 if (includeChildren && getExpanded(item)) { | |
1278 Item[] children = getItems(item); | |
1279 if (children !is null && children.length > 0) { | |
1280 return children[0]; | |
1281 } | |
1282 } | |
1283 | |
1284 // next item is either next sibling or next sibling of first | |
1285 // parent that has a next sibling. | |
1286 Item parent = getParentItem(item); | |
1287 if (parent is null) { | |
1288 return null; | |
1289 } | |
1290 Item[] siblings = getItems(parent); | |
1291 if (siblings !is null) { | |
1292 if (siblings.length <= 1) { | |
1293 return getNextItem(parent, false); | |
1294 } | |
1295 | |
1296 for (int i = 0; i < siblings.length; i++) { | |
1297 if (siblings[i] is item && i < (siblings.length - 1)) { | |
1298 return siblings[i + 1]; | |
1299 } | |
1300 } | |
1301 } | |
1302 return getNextItem(parent, false); | |
1303 } | |
1304 | |
1305 /** | |
1306 * Returns the parent item of the given item in the tree, or | |
1307 * <code>null</code> if there is no parent item. | |
1308 * | |
1309 * @param item | |
1310 * the item | |
1311 * @return the parent item, or <code>null</code> if none | |
1312 */ | |
1313 protected abstract Item getParentItem(Item item); | |
1314 | |
1315 /** | |
1316 * Returns the item before the given item in the tree, or <code>null</code> | |
1317 * if there is no previous item. | |
1318 * | |
1319 * @param item | |
1320 * the item | |
1321 * @return the previous item, or <code>null</code> if none | |
1322 */ | |
1323 protected Item getPreviousItem(Item item) { | |
1324 // previous item is either right-most visible descendent of previous | |
1325 // sibling or parent | |
1326 Item parent = getParentItem(item); | |
1327 if (parent is null) { | |
1328 return null; | |
1329 } | |
1330 Item[] siblings = getItems(parent); | |
1331 if (siblings.length is 0 || siblings[0] is item) { | |
1332 return parent; | |
1333 } | |
1334 Item previous = siblings[0]; | |
1335 for (int i = 1; i < siblings.length; i++) { | |
1336 if (siblings[i] is item) { | |
1337 return rightMostVisibleDescendent(previous); | |
1338 } | |
1339 previous = siblings[i]; | |
1340 } | |
1341 return null; | |
1342 } | |
1343 | |
1344 /* (non-Javadoc) Method declared on StructuredViewer. */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1345 protected override Object[] getRawChildren(Object parentElementOrTreePath) { |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1346 bool oldBusy = isBusy(); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1347 setBusy(true); |
10 | 1348 try { |
1349 Object parent; | |
1350 TreePath path; | |
1351 if ( auto p = cast(TreePath)parentElementOrTreePath ) { | |
1352 path = p; | |
1353 parent = path.getLastSegment(); | |
1354 } else { | |
1355 parent = parentElementOrTreePath; | |
1356 path = null; | |
1357 } | |
1358 if (parent !is null) { | |
1359 if (opEquals(parent, getRoot())) { | |
1360 return super.getRawChildren(parent); | |
1361 } | |
1362 IContentProvider cp = getContentProvider(); | |
1363 if ( auto tpcp = cast(ITreePathContentProvider)cp ) { | |
1364 if (path is null) { | |
1365 // A path was not provided so try and find one | |
1366 Widget w = findItem(parent); | |
1367 if ( auto item = cast(Item)w ) { | |
1368 path = getTreePathFromItem(item); | |
1369 } | |
1370 if (path is null) { | |
1371 path = new TreePath([parent ]); | |
1372 } | |
1373 } | |
1374 Object[] result = tpcp.getChildren(path); | |
1375 if (result !is null) { | |
1376 return result; | |
1377 } | |
1378 } else if ( auto tcp = cast(ITreeContentProvider)cp ) { | |
1379 Object[] result = tcp.getChildren(parent); | |
1380 if (result !is null) { | |
1381 return result; | |
1382 } | |
1383 } | |
1384 } | |
1385 return null; | |
1386 } finally { | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1387 setBusy(oldBusy); |
10 | 1388 } |
1389 } | |
1390 | |
1391 /** | |
1392 * Returns all selected items for the given DWT control. | |
1393 * | |
1394 * @param control | |
1395 * the control | |
1396 * @return the list of selected items | |
1397 */ | |
1398 protected abstract Item[] getSelection(Control control); | |
1399 | |
1400 /* | |
1401 * (non-Javadoc) | |
1402 * | |
1403 * @see dwtx.jface.viewers.StructuredViewer#getSelectionFromWidget() | |
1404 */ | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1405 protected override List getSelectionFromWidget() { |
10 | 1406 Widget[] items = getSelection(getControl()); |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1407 ArrayList list = new ArrayList(items.length); |
10 | 1408 for (int i = 0; i < items.length; i++) { |
1409 Widget item = items[i]; | |
1410 Object e = item.getData(); | |
1411 if (e !is null) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1412 list.add(e); |
10 | 1413 } |
1414 } | |
1415 return list; | |
1416 } | |
1417 | |
1418 /* | |
1419 * Overridden in AbstractTreeViewer to fix bug 108102 (code copied from | |
1420 * StructuredViewer to avoid introducing new API) (non-Javadoc) | |
1421 * | |
1422 * @see dwtx.jface.viewers.StructuredViewer#handleDoubleSelect(dwt.events.SelectionEvent) | |
1423 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1424 protected override void handleDoubleSelect(SelectionEvent event) { |
10 | 1425 // handle case where an earlier selection listener disposed the control. |
1426 Control control = getControl(); | |
1427 if (control !is null && !control.isDisposed()) { | |
1428 // If the double-clicked element can be obtained from the event, use | |
1429 // it | |
1430 // otherwise get it from the control. Some controls like List do | |
1431 // not have the notion of item. | |
1432 // For details, see bug 90161 [Navigator] DefaultSelecting folders | |
1433 // shouldn't always expand first one | |
1434 ISelection selection; | |
1435 if (event.item !is null && event.item.getData() !is null) { | |
1436 | |
1437 // changes to fix bug 108102 follow | |
1438 TreePath treePath = getTreePathFromItem(cast(Item) event.item); | |
1439 selection = new TreeSelection(treePath); | |
1440 // end of changes | |
1441 | |
1442 } else { | |
1443 selection = getSelection(); | |
1444 updateSelection(selection); | |
1445 } | |
1446 fireDoubleClick(new DoubleClickEvent(this, selection)); | |
1447 } | |
1448 } | |
1449 | |
1450 /** | |
1451 * Handles a tree collapse event from the DWT widget. | |
1452 * | |
1453 * @param event | |
1454 * the DWT tree event | |
1455 */ | |
1456 protected void handleTreeCollapse(TreeEvent event) { | |
1457 if (event.item.getData() !is null) { | |
1458 fireTreeCollapsed(new TreeExpansionEvent(this, event.item.getData())); | |
1459 } | |
1460 } | |
1461 | |
1462 /** | |
1463 * Handles a tree expand event from the DWT widget. | |
1464 * | |
1465 * @param event | |
1466 * the DWT tree event | |
1467 */ | |
1468 protected void handleTreeExpand(TreeEvent event) { | |
1469 createChildren(event.item); | |
1470 if (event.item.getData() !is null) { | |
1471 fireTreeExpanded(new TreeExpansionEvent(this, event.item.getData())); | |
1472 } | |
1473 } | |
1474 | |
1475 /* (non-Javadoc) Method declared on Viewer. */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1476 protected override void hookControl(Control control) { |
10 | 1477 super.hookControl(control); |
1478 addTreeListener(control, new class TreeListener { | |
1479 public void treeExpanded(TreeEvent event) { | |
1480 handleTreeExpand(event); | |
1481 } | |
1482 | |
1483 public void treeCollapsed(TreeEvent event) { | |
1484 handleTreeCollapse(event); | |
1485 } | |
1486 }); | |
1487 } | |
1488 | |
1489 /* | |
1490 * (non-Javadoc) Method declared on StructuredViewer. Builds the initial | |
1491 * tree and handles the automatic expand feature. | |
1492 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1493 protected override void inputChanged(Object input, Object oldInput) { |
10 | 1494 preservingSelection(new class Runnable { |
1495 public void run() { | |
1496 Control tree = getControl(); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1497 tree.setRedraw(false); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1498 try { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1499 removeAll(tree); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1500 tree.setData(getRoot()); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1501 internalInitializeTree(tree); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1502 } finally { |
10 | 1503 tree.setRedraw(true); |
1504 } | |
1505 } | |
1506 }); | |
1507 } | |
1508 | |
1509 /** | |
1510 * Initializes the tree with root items, expanding to the appropriate | |
1511 * level if necessary. | |
1512 * | |
1513 * @param tree the tree control | |
1514 * @since 3.3 | |
1515 */ | |
1516 protected void internalInitializeTree(Control tree) { | |
1517 createChildren(tree); | |
1518 internalExpandToLevel(tree, expandToLevel_); | |
1519 } | |
1520 | |
1521 /** | |
1522 * Recursively collapses the subtree rooted at the given widget to the given | |
1523 * level. | |
1524 * <p> | |
1525 * </p> | |
1526 * Note that the default implementation of this method does not call | |
1527 * <code>setRedraw</code>. | |
1528 * | |
1529 * @param widget | |
1530 * the widget | |
1531 * @param level | |
1532 * non-negative level, or <code>ALL_LEVELS</code> to collapse | |
1533 * all levels of the tree | |
1534 */ | |
1535 protected void internalCollapseToLevel(Widget widget, int level) { | |
1536 if (level is ALL_LEVELS || level > 0) { | |
1537 | |
1538 if ( auto i = cast(Item)widget ) { | |
1539 setExpanded(i, false); | |
1540 } | |
1541 | |
1542 if (level is ALL_LEVELS || level > 1) { | |
1543 Item[] children = getChildren(widget); | |
1544 if (children !is null) { | |
1545 int nextLevel = (level is ALL_LEVELS ? ALL_LEVELS | |
1546 : level - 1); | |
1547 for (int i = 0; i < children.length; i++) { | |
1548 internalCollapseToLevel(children[i], nextLevel); | |
1549 } | |
1550 } | |
1551 } | |
1552 } | |
1553 } | |
1554 | |
1555 /** | |
1556 * Recursively collects all expanded items from the given widget. | |
1557 * | |
1558 * @param result | |
1559 * a list (element type: <code>Item</code>) into which to | |
1560 * collect the elements | |
1561 * @param widget | |
1562 * the widget | |
1563 */ | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1564 private void internalCollectExpandedItems(List result, Widget widget) { |
10 | 1565 Item[] items = getChildren(widget); |
1566 for (int i = 0; i < items.length; i++) { | |
1567 Item item = items[i]; | |
1568 if (getExpanded(item)) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1569 result.add(item); |
10 | 1570 } |
1571 internalCollectExpandedItems(result, item); | |
1572 } | |
1573 } | |
1574 | |
1575 /** | |
1576 * Tries to create a path of tree items for the given element or tree path. | |
1577 * This method recursively walks up towards the root of the tree and in the | |
1578 * case of an element (rather than a tree path) assumes that | |
1579 * <code>getParent</code> returns the correct parent of an element. | |
1580 * | |
1581 * @param elementOrPath | |
1582 * the element | |
1583 * @param expand | |
1584 * <code>true</code> if all nodes on the path should be | |
1585 * expanded, and <code>false</code> otherwise | |
1586 * @return Widget | |
1587 */ | |
1588 protected Widget internalExpand(Object elementOrPath, bool expand) { | |
1589 | |
1590 if (elementOrPath is null) { | |
1591 return null; | |
1592 } | |
1593 | |
1594 Widget w = internalGetWidgetToSelect(elementOrPath); | |
1595 if (w is null) { | |
1596 if (opEquals(elementOrPath, getRoot())) { // stop at root | |
1597 return null; | |
1598 } | |
1599 // my parent has to create me | |
1600 Object parent = getParentElement(elementOrPath); | |
1601 if (parent !is null) { | |
1602 Widget pw = internalExpand(parent, false); | |
1603 if (pw !is null) { | |
1604 // let my parent create me | |
1605 createChildren(pw); | |
1606 Object element = internalToElement(elementOrPath); | |
1607 w = internalFindChild(pw, element); | |
1608 if (expand && null !is cast(Item)pw ) { | |
1609 // expand parent items top-down | |
1610 Item item = cast(Item) pw; | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1611 LinkedList toExpandList = new LinkedList(); |
10 | 1612 while (item !is null && !getExpanded(item)) { |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1613 toExpandList.addFirst(item); |
10 | 1614 item = getParentItem(item); |
1615 } | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1616 for (Iterator it = toExpandList.iterator(); it |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1617 .hasNext();) { |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
1618 Item toExpand = cast(Item) it.next(); |
10 | 1619 setExpanded(toExpand, true); |
1620 } | |
1621 } | |
1622 } | |
1623 } | |
1624 } | |
1625 return w; | |
1626 } | |
1627 | |
1628 /** | |
1629 * If the argument is a tree path, returns its last segment, otherwise | |
1630 * return the argument | |
1631 * | |
1632 * @param elementOrPath | |
1633 * an element or a tree path | |
1634 * @return the element, or the last segment of the tree path | |
1635 */ | |
1636 private Object internalToElement(Object elementOrPath) { | |
1637 if (auto tp = cast(TreePath)elementOrPath ) { | |
1638 return tp.getLastSegment(); | |
1639 } | |
1640 return elementOrPath; | |
1641 } | |
1642 | |
1643 /** | |
1644 * This method takes a tree path or an element. If the argument is not a | |
1645 * tree path, returns the parent of the given element or <code>null</code> | |
1646 * if the parent is not known. If the argument is a tree path with more than | |
1647 * one segment, returns its parent tree path, otherwise returns | |
1648 * <code>null</code>. | |
1649 * | |
1650 * @param elementOrTreePath | |
1651 * @return the parent element, or parent path, or <code>null</code> | |
1652 * | |
1653 * @since 3.2 | |
1654 */ | |
1655 protected Object getParentElement(Object elementOrTreePath) { | |
1656 if (auto tp = cast(TreePath)elementOrTreePath) { | |
1657 return tp.getParentPath(); | |
1658 } | |
1659 IContentProvider cp = getContentProvider(); | |
1660 if ( auto tpcp = cast(ITreePathContentProvider)cp ) { | |
1661 TreePath[] paths = tpcp.getParents(elementOrTreePath); | |
1662 if (paths.length > 0) { | |
1663 if (paths[0].getSegmentCount() is 0) { | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1664 return getRoot(); |
10 | 1665 } |
1666 return paths[0].getLastSegment(); | |
1667 } | |
1668 } | |
1669 if ( auto tcp = cast(ITreeContentProvider) cp ) { | |
1670 return tcp.getParent(elementOrTreePath); | |
1671 } | |
1672 return null; | |
1673 } | |
1674 | |
1675 /** | |
1676 * Returns the widget to be selected for the given element or tree path. | |
1677 * | |
1678 * @param elementOrTreePath | |
1679 * the element or tree path to select | |
1680 * @return the widget to be selected, or <code>null</code> if not found | |
1681 * | |
1682 * @since 3.1 | |
1683 */ | |
1684 protected Widget internalGetWidgetToSelect(Object elementOrTreePath) { | |
1685 if ( auto treePath = cast(TreePath) elementOrTreePath ) { | |
1686 if (treePath.getSegmentCount() is 0) { | |
1687 return getControl(); | |
1688 } | |
1689 Widget[] candidates = findItems(treePath.getLastSegment()); | |
1690 for (int i = 0; i < candidates.length; i++) { | |
1691 Widget candidate = candidates[i]; | |
1692 if (!(cast(Item)candidate )) { | |
1693 continue; | |
1694 } | |
1695 if (treePath.opEquals(getTreePathFromItem(cast(Item) candidate), | |
1696 getComparer())) { | |
1697 return candidate; | |
1698 } | |
1699 } | |
1700 return null; | |
1701 } | |
1702 return findItem(elementOrTreePath); | |
1703 } | |
1704 | |
1705 /** | |
1706 * Recursively expands the subtree rooted at the given widget to the given | |
1707 * level. | |
1708 * <p> | |
1709 * </p> | |
1710 * Note that the default implementation of this method does not call | |
1711 * <code>setRedraw</code>. | |
1712 * | |
1713 * @param widget | |
1714 * the widget | |
1715 * @param level | |
1716 * non-negative level, or <code>ALL_LEVELS</code> to collapse | |
1717 * all levels of the tree | |
1718 */ | |
1719 protected void internalExpandToLevel(Widget widget, int level) { | |
1720 if (level is ALL_LEVELS || level > 0) { | |
1721 if ( cast(Item)widget && widget.getData() !is null | |
1722 && !isExpandable(cast(Item) widget, null, widget.getData())) { | |
1723 return; | |
1724 } | |
1725 createChildren(widget); | |
1726 if ( auto i = cast(Item)widget ) { | |
1727 setExpanded(i, true); | |
1728 } | |
1729 if (level is ALL_LEVELS || level > 1) { | |
1730 Item[] children = getChildren(widget); | |
1731 if (children !is null) { | |
1732 int newLevel = (level is ALL_LEVELS ? ALL_LEVELS | |
1733 : level - 1); | |
1734 for (int i = 0; i < children.length; i++) { | |
1735 internalExpandToLevel(children[i], newLevel); | |
1736 } | |
1737 } | |
1738 } | |
1739 } | |
1740 } | |
1741 | |
1742 /** | |
1743 * Non-recursively tries to find the given element as a child of the given | |
1744 * parent (item or tree). | |
1745 * | |
1746 * @param parent | |
1747 * the parent item | |
1748 * @param element | |
1749 * the element | |
1750 * @return Widget | |
1751 */ | |
1752 private Widget internalFindChild(Widget parent, Object element) { | |
1753 Item[] items = getChildren(parent); | |
1754 for (int i = 0; i < items.length; i++) { | |
1755 Item item = items[i]; | |
1756 Object data = item.getData(); | |
1757 if (data !is null && opEquals(data, element)) { | |
1758 return item; | |
1759 } | |
1760 } | |
1761 return null; | |
1762 } | |
1763 | |
1764 /** | |
1765 * Recursively tries to find the given element. | |
1766 * | |
1767 * @param parent | |
1768 * the parent item | |
1769 * @param element | |
1770 * the element | |
1771 * @return Widget | |
1772 */ | |
1773 private Widget internalFindItem(Item parent, Object element) { | |
1774 | |
1775 // compare with node | |
1776 Object data = parent.getData(); | |
1777 if (data !is null) { | |
1778 if (opEquals(data, element)) { | |
1779 return parent; | |
1780 } | |
1781 } | |
1782 // recurse over children | |
1783 Item[] items = getChildren(parent); | |
1784 for (int i = 0; i < items.length; i++) { | |
1785 Item item = items[i]; | |
1786 Widget o = internalFindItem(item, element); | |
1787 if (o !is null) { | |
1788 return o; | |
1789 } | |
1790 } | |
1791 return null; | |
1792 } | |
1793 | |
1794 /* (non-Javadoc) Method declared on StructuredViewer. */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1795 protected override void internalRefresh(Object element) { |
10 | 1796 internalRefresh(element, true); |
1797 } | |
1798 | |
1799 /* (non-Javadoc) Method declared on StructuredViewer. */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
1800 protected override void internalRefresh(Object element, bool updateLabels) { |
10 | 1801 // If element is null, do a full refresh. |
1802 if (element is null) { | |
1803 internalRefresh(getControl(), getRoot(), true, updateLabels); | |
1804 return; | |
1805 } | |
1806 Widget[] items = findItems(element); | |
1807 if (items.length !is 0) { | |
1808 for (int i = 0; i < items.length; i++) { | |
1809 // pick up structure changes too | |
1810 internalRefresh(items[i], element, true, updateLabels); | |
1811 } | |
1812 } | |
1813 } | |
1814 | |
1815 /** | |
1816 * Refreshes the tree starting at the given widget. | |
1817 * <p> | |
1818 * EXPERIMENTAL. Not to be used except by JDT. This method was added to | |
1819 * support JDT's explorations into grouping by working sets, which requires | |
1820 * viewers to support multiple equal elements. See bug 76482 for more | |
1821 * details. This support will likely be removed in Eclipse 3.2 in favor of | |
1822 * proper support for multiple equal elements. | |
1823 * </p> | |
1824 * | |
1825 * @param widget | |
1826 * the widget | |
1827 * @param element | |
1828 * the element | |
1829 * @param doStruct | |
1830 * <code>true</code> if structural changes are to be picked up, | |
1831 * and <code>false</code> if only label provider changes are of | |
1832 * interest | |
1833 * @param updateLabels | |
1834 * <code>true</code> to update labels for existing elements, | |
1835 * <code>false</code> to only update labels as needed, assuming | |
1836 * that labels for existing elements are unchanged. | |
1837 * @since 3.1 | |
1838 */ | |
1839 protected void internalRefresh(Widget widget, Object element, | |
1840 bool doStruct, bool updateLabels) { | |
1841 | |
1842 if ( auto i = cast(Item)widget ) { | |
1843 if (doStruct) { | |
1844 updatePlus(i, element); | |
1845 } | |
1846 if (updateLabels || !opEquals(element, widget.getData())) { | |
1847 doUpdateItem(widget, element, true); | |
1848 } else { | |
1849 associate(element, cast(Item) widget); | |
1850 } | |
1851 } | |
1852 | |
1853 if (doStruct) { | |
1854 internalRefreshStruct(widget, element, updateLabels); | |
1855 } else { | |
1856 Item[] children = getChildren(widget); | |
1857 if (children !is null) { | |
1858 for (int i = 0; i < children.length; i++) { | |
1859 Widget item = children[i]; | |
1860 Object data = item.getData(); | |
1861 if (data !is null) { | |
1862 internalRefresh(item, data, doStruct, updateLabels); | |
1863 } | |
1864 } | |
1865 } | |
1866 } | |
1867 } | |
1868 | |
1869 /** | |
1870 * Update the structure and recurse. Items are updated in updateChildren, as | |
1871 * needed. | |
1872 * | |
1873 * @param widget | |
1874 * @param element | |
1875 * @param updateLabels | |
1876 */ | |
1877 /* package */void internalRefreshStruct(Widget widget, Object element, | |
1878 bool updateLabels) { | |
1879 updateChildren(widget, element, null, updateLabels); | |
1880 Item[] children = getChildren(widget); | |
1881 if (children !is null) { | |
1882 for (int i = 0; i < children.length; i++) { | |
1883 Widget item = children[i]; | |
1884 Object data = item.getData(); | |
1885 if (data !is null) { | |
1886 internalRefreshStruct(item, data, updateLabels); | |
1887 } | |
1888 } | |
1889 } | |
1890 } | |
1891 | |
1892 /** | |
1893 * Removes the given elements from this viewer. | |
1894 * <p> | |
1895 * EXPERIMENTAL. Not to be used except by JDT. This method was added to | |
1896 * support JDT's explorations into grouping by working sets, which requires | |
1897 * viewers to support multiple equal elements. See bug 76482 for more | |
1898 * details. This support will likely be removed in Eclipse 3.2 in favor of | |
1899 * proper support for multiple equal elements. | |
1900 * </p> | |
1901 * | |
1902 * @param elementsOrPaths | |
1903 * the elements or element paths to remove | |
1904 * @since 3.1 | |
1905 */ | |
1906 protected void internalRemove(Object[] elementsOrPaths) { | |
1907 Object input = getInput(); | |
1908 for (int i = 0; i < elementsOrPaths.length; ++i) { | |
1909 Object element = elementsOrPaths[i]; | |
1910 if (opEquals(element, input)) { | |
1911 setInput(null); | |
1912 return; | |
1913 } | |
1914 Widget[] childItems = internalFindItems(element); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1915 if (childItems.length > 0) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1916 for (int j = 0; j < childItems.length; j++) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1917 Widget childItem = childItems[j]; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1918 if ( auto it = cast(Item)childItem ) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1919 disassociate(it); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1920 childItem.dispose(); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1921 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1922 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1923 } else { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1924 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=210747 |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1925 Object parent = getParentElement(element); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1926 if (parent !is null |
72
5df4896124c7
JFace and its examples do compile
Frank Benoit <benoit@tionex.de>
parents:
71
diff
changeset
|
1927 && !opEquals(parent, getRoot()) |
71 | 1928 && !((null !is cast(TreePath)parent) && (cast(TreePath) parent) |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1929 .getSegmentCount() is 0)) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1930 Widget[] parentItems = internalFindItems(parent); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1931 for (int j = 0; j < parentItems.length; j++) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1932 Widget parentItem = parentItems[j]; |
71 | 1933 if (null !is cast(Item)parentItem ) { |
1934 updatePlus(cast(Item) parentItem, parent); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1935 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1936 } |
10 | 1937 } |
1938 } | |
1939 } | |
1940 } | |
1941 | |
1942 /** | |
1943 * Removes the given elements from this viewer, whenever those elements | |
1944 * appear as children of the given parent. | |
1945 * | |
1946 * @param parent the parent element | |
1947 * @param elements | |
1948 * the elements to remove | |
1949 * @since 3.1 | |
1950 */ | |
1951 protected void internalRemove(Object parent, Object[] elements) { | |
1952 | |
1953 CustomHashtable toRemove = new CustomHashtable(getComparer()); | |
1954 for (int i = 0; i < elements.length; i++) { | |
1955 toRemove.put(elements[i], elements[i]); | |
1956 } | |
1957 | |
1958 // Find each place the parent appears in the tree | |
1959 Widget[] parentItemArray = findItems(parent); | |
1960 for (int i = 0; i < parentItemArray.length; i++) { | |
1961 Widget parentItem = parentItemArray[i]; | |
1962 | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1963 // May happen if parent element is a descendent of of a previously |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1964 // removed element |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1965 if (parentItem.isDisposed()) |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1966 continue; |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1967 |
10 | 1968 // Iterate over the child items and remove each one |
1969 Item[] children = getChildren(parentItem); | |
1970 | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1971 if (children.length is 1 && children[0].getData() is null && |
71 | 1972 (null !is cast(Item)parentItem )) { // dummy node |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1973 // Remove plus if parent element has no children |
71 | 1974 updatePlus(cast(Item) parentItem, parent); |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1975 } else { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1976 for (int j = 0; j < children.length; j++) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1977 Item child = children[j]; |
10 | 1978 |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1979 Object data = child.getData(); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1980 if (data !is null && toRemove.containsKey(data)) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1981 disassociate(child); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1982 child.dispose(); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
1983 } |
10 | 1984 } |
1985 } | |
1986 } | |
1987 } | |
1988 | |
1989 /** | |
1990 * Sets the expanded state of all items to correspond to the given set of | |
1991 * expanded elements. | |
1992 * | |
1993 * @param expandedElements | |
1994 * the set (element type: <code>Object</code>) of elements | |
1995 * which are expanded | |
1996 * @param widget | |
1997 * the widget | |
1998 */ | |
1999 private void internalSetExpanded(CustomHashtable expandedElements, | |
2000 Widget widget) { | |
2001 Item[] items = getChildren(widget); | |
2002 for (int i = 0; i < items.length; i++) { | |
2003 Item item = items[i]; | |
2004 Object data = item.getData(); | |
2005 if (data !is null) { | |
2006 // remove the element to avoid an infinite loop | |
2007 // if the same element appears on a child item | |
2008 bool expanded = expandedElements.remove(data) !is null; | |
2009 if (expanded !is getExpanded(item)) { | |
2010 if (expanded) { | |
2011 createChildren(item); | |
2012 } | |
2013 setExpanded(item, expanded); | |
2014 } | |
2015 } | |
2016 if (expandedElements.size() > 0) { | |
2017 internalSetExpanded(expandedElements, item); | |
2018 } | |
2019 } | |
2020 } | |
2021 | |
2022 /** | |
2023 * Sets the expanded state of all items to correspond to the given set of | |
2024 * expanded tree paths. | |
2025 * | |
2026 * @param expandedTreePaths | |
2027 * the set (element type: <code>TreePath</code>) of elements | |
2028 * which are expanded | |
2029 * @param widget | |
2030 * the widget | |
2031 */ | |
2032 private void internalSetExpandedTreePaths( | |
2033 CustomHashtable expandedTreePaths, Widget widget, | |
2034 TreePath currentPath) { | |
2035 Item[] items = getChildren(widget); | |
2036 for (int i = 0; i < items.length; i++) { | |
2037 Item item = items[i]; | |
2038 Object data = item.getData(); | |
2039 TreePath childPath = data is null ? null : currentPath | |
2040 .createChildPath(data); | |
2041 if (data !is null && childPath !is null) { | |
2042 // remove the element to avoid an infinite loop | |
2043 // if the same element appears on a child item | |
2044 bool expanded = expandedTreePaths.remove(childPath) !is null; | |
2045 if (expanded !is getExpanded(item)) { | |
2046 if (expanded) { | |
2047 createChildren(item); | |
2048 } | |
2049 setExpanded(item, expanded); | |
2050 } | |
2051 } | |
2052 internalSetExpandedTreePaths(expandedTreePaths, item, childPath); | |
2053 } | |
2054 } | |
2055 | |
2056 /** | |
2057 * Return whether the tree node representing the given element or path can | |
2058 * be expanded. Clients should query expandability by path if the viewer's | |
2059 * content provider is an {@link ITreePathContentProvider}. | |
2060 * <p> | |
2061 * The default implementation of this framework method calls | |
2062 * <code>hasChildren</code> on this viewer's content provider. It may be | |
2063 * overridden if necessary. | |
2064 * </p> | |
2065 * | |
2066 * @param elementOrTreePath | |
2067 * the element or path | |
2068 * @return <code>true</code> if the tree node representing the given | |
2069 * element can be expanded, or <code>false</code> if not | |
2070 */ | |
2071 public bool isExpandable(Object elementOrTreePath) { | |
2072 Object element; | |
2073 TreePath path; | |
2074 if (auto p = cast(TreePath)elementOrTreePath) { | |
2075 path = p; | |
2076 element = path.getLastSegment(); | |
2077 } else { | |
2078 element = elementOrTreePath; | |
2079 path = null; | |
2080 } | |
2081 IContentProvider cp = getContentProvider(); | |
2082 if ( auto tpcp = cast(ITreePathContentProvider) cp ) { | |
2083 if (path is null) { | |
2084 // A path was not provided so try and find one | |
2085 Widget w = findItem(element); | |
2086 if ( auto item = cast(Item)w ) { | |
2087 path = getTreePathFromItem(item); | |
2088 } | |
2089 if (path is null) { | |
2090 path = new TreePath([ element ]); | |
2091 } | |
2092 } | |
2093 return tpcp.hasChildren(path); | |
2094 } | |
2095 if (auto tcp = cast(ITreeContentProvider)cp ) { | |
2096 return tcp.hasChildren(element); | |
2097 } | |
2098 return false; | |
2099 } | |
2100 | |
2101 /** | |
2102 * Return whether the given element is expandable. | |
2103 * | |
2104 * @param item | |
2105 * the tree item for the element | |
2106 * @param parentPath | |
2107 * the parent path if it is known or <code>null</code> if it | |
2108 * needs to be determines | |
2109 * @param element | |
2110 * the element | |
2111 * @return whether the given element is expandable | |
2112 */ | |
2113 private bool isExpandable(Item item, TreePath parentPath, Object element) { | |
2114 Object elementOrTreePath = element; | |
2115 if (isTreePathContentProvider()) { | |
2116 if (parentPath !is null) { | |
2117 elementOrTreePath = parentPath.createChildPath(element); | |
2118 } else { | |
2119 elementOrTreePath = getTreePathFromItem(item); | |
2120 } | |
2121 } | |
2122 return isExpandable(elementOrTreePath); | |
2123 } | |
2124 | |
2125 /* (non-Javadoc) Method declared on Viewer. */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
2126 protected override void labelProviderChanged() { |
10 | 2127 // we have to walk the (visible) tree and update every item |
2128 Control tree = getControl(); | |
2129 tree.setRedraw(false); | |
2130 // don't pick up structure changes, but do force label updates | |
2131 internalRefresh(tree, getRoot(), false, true); | |
2132 tree.setRedraw(true); | |
2133 } | |
2134 | |
2135 /** | |
2136 * Creates a new item. | |
2137 * | |
2138 * @param parent | |
2139 * the parent widget | |
2140 * @param style | |
2141 * DWT style bits | |
2142 * @param index | |
2143 * if non-negative, indicates the position to insert the item | |
2144 * into its parent | |
2145 * @return the newly-created item | |
2146 */ | |
2147 protected abstract Item newItem(Widget parent, int style, int index); | |
2148 | |
2149 /** | |
2150 * Removes the given elements from this viewer. The selection is updated if | |
2151 * required. | |
2152 * <p> | |
2153 * This method should be called (by the content provider) when elements have | |
2154 * been removed from the model, in order to cause the viewer to accurately | |
2155 * reflect the model. This method only affects the viewer, not the model. | |
2156 * </p> | |
2157 * | |
2158 * @param elementsOrTreePaths | |
2159 * the elements to remove | |
2160 */ | |
2161 public void remove(Object[] elementsOrTreePaths) { | |
2162 assertElementsNotNull(elementsOrTreePaths); | |
2163 if (elementsOrTreePaths.length is 0) { | |
2164 return; | |
2165 } | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2166 if (checkBusy()) |
10 | 2167 return; |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2168 preservingSelection( dgRunnable( (Object[] elementsOrTreePaths_){ |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2169 internalRemove(elementsOrTreePaths_); |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2170 }, elementsOrTreePaths)); |
10 | 2171 } |
2172 | |
2173 /** | |
2174 * Removes the given elements from this viewer whenever they appear as | |
2175 * children of the given parent element. If the given elements also appear | |
2176 * as children of some other parent, the other parent will remain unchanged. | |
2177 * The selection is updated if required. | |
2178 * <p> | |
2179 * This method should be called (by the content provider) when elements have | |
2180 * been removed from the model, in order to cause the viewer to accurately | |
2181 * reflect the model. This method only affects the viewer, not the model. | |
2182 * </p> | |
2183 * | |
2184 * @param parent | |
2185 * the parent of the elements to remove | |
2186 * @param elements | |
2187 * the elements to remove | |
2188 * | |
2189 * @since 3.2 | |
2190 */ | |
2191 public void remove(Object parent, Object[] elements) { | |
2192 assertElementsNotNull(elements); | |
2193 if (elements.length is 0) { | |
2194 return; | |
2195 } | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2196 if (checkBusy()) |
10 | 2197 return; |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2198 preservingSelection( dgRunnable( (Object parent_,Object[] elements_){ |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2199 internalRemove(parent_, elements_); |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2200 }, parent, elements )); |
10 | 2201 } |
2202 | |
2203 /** | |
2204 * Removes the given element from the viewer. The selection is updated if | |
2205 * necessary. | |
2206 * <p> | |
2207 * This method should be called (by the content provider) when a single | |
2208 * element has been removed from the model, in order to cause the viewer to | |
2209 * accurately reflect the model. This method only affects the viewer, not | |
2210 * the model. Note that there is another method for efficiently processing | |
2211 * the simultaneous removal of multiple elements. | |
2212 * </p> | |
2213 * | |
2214 * @param elementsOrTreePaths | |
2215 * the element | |
2216 */ | |
2217 public void remove(Object elementsOrTreePaths) { | |
2218 remove([ elementsOrTreePaths ]); | |
2219 } | |
2220 | |
2221 /** | |
2222 * Removes all items from the given control. | |
2223 * | |
2224 * @param control | |
2225 * the control | |
2226 */ | |
2227 protected abstract void removeAll(Control control); | |
2228 | |
2229 /** | |
2230 * Removes a listener for expand and collapse events in this viewer. Has no | |
2231 * affect if an identical listener is not registered. | |
2232 * | |
2233 * @param listener | |
2234 * a tree viewer listener | |
2235 */ | |
2236 public void removeTreeListener(ITreeViewerListener listener) { | |
2237 treeListeners.remove(cast(Object)listener); | |
2238 } | |
2239 | |
2240 /** | |
2241 * This implementation of reveal() reveals the given element or tree path. | |
2242 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
2243 public override void reveal(Object elementOrTreePath) { |
10 | 2244 Assert.isNotNull(elementOrTreePath); |
2245 Widget w = internalExpand(elementOrTreePath, true); | |
2246 if ( auto item = cast(Item)w ) { | |
2247 showItem(item); | |
2248 } | |
2249 } | |
2250 | |
2251 /** | |
2252 * Returns the rightmost visible descendent of the given item. Returns the | |
2253 * item itself if it has no children. | |
2254 * | |
2255 * @param item | |
2256 * the item to compute the descendent of | |
2257 * @return the rightmost visible descendent or the item itself if it has no | |
2258 * children | |
2259 */ | |
2260 private Item rightMostVisibleDescendent(Item item) { | |
2261 Item[] children = getItems(item); | |
2262 if (getExpanded(item) && children !is null && children.length > 0) { | |
2263 return rightMostVisibleDescendent(children[children.length - 1]); | |
2264 } | |
2265 return item; | |
2266 } | |
2267 | |
2268 /* (non-Javadoc) Method declared on Viewer. */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
2269 public override Item scrollDown(int x, int y) { |
10 | 2270 Item current = getItem(x, y); |
2271 if (current !is null) { | |
2272 Item next = getNextItem(current, true); | |
2273 showItem(next is null ? current : next); | |
2274 return next; | |
2275 } | |
2276 return null; | |
2277 } | |
2278 | |
2279 /* (non-Javadoc) Method declared on Viewer. */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
2280 public override Item scrollUp(int x, int y) { |
10 | 2281 Item current = getItem(x, y); |
2282 if (current !is null) { | |
2283 Item previous = getPreviousItem(current); | |
2284 showItem(previous is null ? current : previous); | |
2285 return previous; | |
2286 } | |
2287 return null; | |
2288 } | |
2289 | |
2290 /** | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2291 * Sets the auto-expand level to be used when the input of the viewer is set |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2292 * using {@link #setInput(Object)}. The value 0 means that there is no |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2293 * auto-expand; 1 means that the invisible root element is expanded (since |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2294 * most concrete subclasses do not show the root element, there is usually |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2295 * no practical difference between using the values 0 and 1); 2 means that |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2296 * top-level elements are expanded, but not their children; 3 means that |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2297 * top-level elements are expanded, and their children, but not |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2298 * grandchildren; and so on. |
10 | 2299 * <p> |
2300 * The value <code>ALL_LEVELS</code> means that all subtrees should be | |
2301 * expanded. | |
2302 * </p> | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2303 * <p> |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2304 * Note that in previous releases, the Javadoc for this method had an off-by |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2305 * one error. See bug 177669 for details. |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2306 * </p> |
10 | 2307 * |
2308 * @param level | |
2309 * non-negative level, or <code>ALL_LEVELS</code> to expand all | |
2310 * levels of the tree | |
2311 */ | |
2312 public void setAutoExpandLevel(int level) { | |
2313 expandToLevel_ = level; | |
2314 } | |
2315 | |
2316 /** | |
2317 * The <code>AbstractTreeViewer</code> implementation of this method | |
2318 * checks to ensure that the content provider is an | |
2319 * <code>ITreeContentProvider</code>. | |
2320 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
2321 public override void setContentProvider(IContentProvider provider) { |
10 | 2322 // the actual check is in assertContentProviderType |
2323 super.setContentProvider(provider); | |
2324 } | |
2325 | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
2326 protected override void assertContentProviderType(IContentProvider provider) { |
10 | 2327 Assert.isTrue(cast(ITreeContentProvider)provider |
2328 || cast(ITreePathContentProvider)provider ); | |
2329 } | |
2330 | |
2331 /** | |
2332 * Sets the expand state of the given item. | |
2333 * | |
2334 * @param item | |
2335 * the item | |
2336 * @param expand | |
2337 * the expand state of the item | |
2338 */ | |
2339 protected abstract void setExpanded(Item item, bool expand); | |
2340 | |
2341 /** | |
2342 * Sets which nodes are expanded in this viewer's tree. The given list | |
2343 * contains the elements that are to be expanded; all other nodes are to be | |
2344 * collapsed. | |
2345 * <p> | |
2346 * This method is typically used when restoring the interesting state of a | |
2347 * viewer captured by an earlier call to <code>getExpandedElements</code>. | |
2348 * </p> | |
2349 * | |
2350 * @param elements | |
2351 * the array of expanded elements | |
2352 * @see #getExpandedElements | |
2353 */ | |
2354 public void setExpandedElements(Object[] elements) { | |
2355 assertElementsNotNull(elements); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2356 if (checkBusy()) { |
10 | 2357 return; |
2358 } | |
2359 CustomHashtable expandedElements = newHashtable(elements.length * 2 + 1); | |
2360 for (int i = 0; i < elements.length; ++i) { | |
2361 Object element = elements[i]; | |
2362 // Ensure item exists for element. This will materialize items for | |
2363 // each element and their parents, if possible. This is important | |
2364 // to support expanding of inner tree nodes without necessarily | |
2365 // expanding their parents. | |
2366 internalExpand(element, false); | |
2367 expandedElements.put(element, element); | |
2368 } | |
2369 // this will traverse all existing items, and create children for | |
2370 // elements that need to be expanded. If the tree contains multiple | |
2371 // equal elements, and those are in the set of elements to be expanded, | |
2372 // only the first item found for each element will be expanded. | |
2373 internalSetExpanded(expandedElements, getControl()); | |
2374 } | |
2375 | |
2376 /** | |
2377 * Sets which nodes are expanded in this viewer's tree. The given list | |
2378 * contains the tree paths that are to be expanded; all other nodes are to | |
2379 * be collapsed. | |
2380 * <p> | |
2381 * This method is typically used when restoring the interesting state of a | |
2382 * viewer captured by an earlier call to <code>getExpandedTreePaths</code>. | |
2383 * </p> | |
2384 * | |
2385 * @param treePaths | |
2386 * the array of expanded tree paths | |
2387 * @see #getExpandedTreePaths() | |
2388 * | |
2389 * @since 3.2 | |
2390 */ | |
2391 public void setExpandedTreePaths(TreePath[] treePaths) { | |
2392 assertElementsNotNull(treePaths); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2393 if (checkBusy()) |
10 | 2394 return; |
39 | 2395 IElementComparer treePathComparer = new class(getComparer()) IElementComparer { |
10 | 2396 IElementComparer comparer; |
39 | 2397 this(IElementComparer c){ |
2398 comparer = c; | |
10 | 2399 } |
2400 public int opEquals(Object a, Object b) { | |
2401 return (cast(TreePath) a).opEquals((cast(TreePath) b), comparer); | |
2402 } | |
2403 | |
2404 public hash_t toHash(Object element) { | |
2405 return (cast(TreePath) element).toHash(comparer); | |
2406 } | |
2407 }; | |
2408 CustomHashtable expandedTreePaths = new CustomHashtable( | |
2409 treePaths.length * 2 + 1, treePathComparer); | |
2410 for (int i = 0; i < treePaths.length; ++i) { | |
2411 TreePath treePath = treePaths[i]; | |
2412 // Ensure item exists for element. This will materialize items for | |
2413 // each element and their parents, if possible. This is important | |
2414 // to support expanding of inner tree nodes without necessarily | |
2415 // expanding their parents. | |
2416 internalExpand(treePath, false); | |
2417 expandedTreePaths.put(treePath, treePath); | |
2418 } | |
2419 // this will traverse all existing items, and create children for | |
2420 // elements that need to be expanded. If the tree contains multiple | |
2421 // equal elements, and those are in the set of elements to be expanded, | |
2422 // only the first item found for each element will be expanded. | |
2423 internalSetExpandedTreePaths(expandedTreePaths, getControl(), | |
2424 new TreePath(new Object[0])); | |
2425 } | |
2426 | |
2427 /** | |
2428 * Sets whether the node corresponding to the given element or tree path is | |
2429 * expanded or collapsed. | |
2430 * | |
2431 * @param elementOrTreePath | |
2432 * the element | |
2433 * @param expanded | |
2434 * <code>true</code> if the node is expanded, and | |
2435 * <code>false</code> if collapsed | |
2436 */ | |
2437 public void setExpandedState(Object elementOrTreePath, bool expanded) { | |
2438 Assert.isNotNull(elementOrTreePath); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2439 if (checkBusy()) |
10 | 2440 return; |
2441 Widget item = internalExpand(elementOrTreePath, false); | |
2442 if ( cast(Item)item ) { | |
2443 if (expanded) { | |
2444 createChildren(item); | |
2445 } | |
2446 setExpanded(cast(Item) item, expanded); | |
2447 } | |
2448 } | |
2449 | |
2450 /** | |
2451 * Sets the selection to the given list of items. | |
2452 * | |
2453 * @param items | |
2454 * list of items (element type: | |
2455 * <code>dwt.widgets.Item</code>) | |
2456 */ | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2457 protected abstract void setSelection(List items); |
10 | 2458 |
2459 /** | |
2460 * This implementation of setSelectionToWidget accepts a list of elements or | |
2461 * a list of tree paths. | |
2462 */ | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2463 protected override void setSelectionToWidget(List v, bool reveal) { |
10 | 2464 if (v is null) { |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2465 setSelection(new ArrayList(0)); |
10 | 2466 return; |
2467 } | |
2468 int size = v.size(); | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2469 List newSelection = new ArrayList(size); |
10 | 2470 for (int i = 0; i < size; ++i) { |
2471 Object elementOrTreePath = v.get(i); | |
2472 // Use internalExpand since item may not yet be created. See | |
2473 // 1G6B1AR. | |
2474 Widget w = internalExpand(elementOrTreePath, false); | |
2475 if ( auto it = cast(Item)w ) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2476 newSelection.add(it); |
10 | 2477 } else if (w is null && null !is cast(TreePath)elementOrTreePath ) { |
2478 TreePath treePath = cast(TreePath) elementOrTreePath; | |
2479 Object element = treePath.getLastSegment(); | |
2480 if (element !is null) { | |
2481 w = internalExpand(element, false); | |
2482 if ( auto it = cast(Item)w ) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2483 newSelection.add(it); |
10 | 2484 } |
2485 } | |
2486 } | |
2487 } | |
2488 setSelection(newSelection); | |
2489 | |
2490 // Although setting the selection in the control should reveal it, | |
2491 // setSelection may be a no-op if the selection is unchanged, | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2492 // so explicitly reveal items in the selection here. |
10 | 2493 // See bug 100565 for more details. |
2494 if (reveal && newSelection.size() > 0) { | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2495 // Iterate backwards so the first item in the list |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2496 // is the one guaranteed to be visible |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2497 for (int i = (newSelection.size()-1); i >= 0; i--) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2498 showItem(cast(Item) newSelection.get(i)); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2499 } |
10 | 2500 } |
2501 } | |
2502 | |
2503 /** | |
2504 * Shows the given item. | |
2505 * | |
2506 * @param item | |
2507 * the item | |
2508 */ | |
2509 protected abstract void showItem(Item item); | |
2510 | |
2511 /** | |
2512 * Updates the tree items to correspond to the child elements of the given | |
2513 * parent element. If null is passed for the children, this method obtains | |
2514 * them (only if needed). | |
2515 * | |
2516 * @param widget | |
2517 * the widget | |
2518 * @param parent | |
2519 * the parent element | |
2520 * @param elementChildren | |
2521 * the child elements, or null | |
2522 * @deprecated this is no longer called by the framework | |
2523 */ | |
2524 protected void updateChildren(Widget widget, Object parent, | |
2525 Object[] elementChildren) { | |
2526 updateChildren(widget, parent, elementChildren, true); | |
2527 } | |
2528 | |
2529 /** | |
2530 * Updates the tree items to correspond to the child elements of the given | |
2531 * parent element. If null is passed for the children, this method obtains | |
2532 * them (only if needed). | |
2533 * | |
2534 * @param widget | |
2535 * the widget | |
2536 * @param parent | |
2537 * the parent element | |
2538 * @param elementChildren | |
2539 * the child elements, or null | |
2540 * @param updateLabels | |
2541 * <code>true</code> to update labels for existing elements, | |
2542 * <code>false</code> to only update labels as needed, assuming | |
2543 * that labels for existing elements are unchanged. | |
2544 * @since 2.1 | |
2545 */ | |
2546 private void updateChildren(Widget widget, Object parent, | |
2547 Object[] elementChildren, bool updateLabels) { | |
2548 // optimization! prune collapsed subtrees | |
2549 if (auto ti = cast(Item)widget ) { | |
2550 if (!getExpanded(ti)) { | |
2551 // need a dummy node if element is expandable; | |
2552 // but try to avoid recreating the dummy node | |
2553 bool needDummy = isExpandable(ti, null, parent); | |
2554 bool haveDummy = false; | |
2555 // remove all children | |
2556 Item[] items = getItems(ti); | |
2557 for (int i = 0; i < items.length; i++) { | |
2558 if (items[i].getData() !is null) { | |
2559 disassociate(items[i]); | |
2560 items[i].dispose(); | |
2561 } else { | |
2562 if (needDummy && !haveDummy) { | |
2563 haveDummy = true; | |
2564 } else { | |
2565 items[i].dispose(); | |
2566 } | |
2567 } | |
2568 } | |
2569 if (needDummy && !haveDummy) { | |
2570 newItem(ti, DWT.NULL, -1); | |
2571 } | |
2572 | |
2573 return; | |
2574 } | |
2575 } | |
2576 | |
2577 // If the children weren't passed in, get them now since they're needed | |
2578 // below. | |
2579 if (elementChildren is null) { | |
2580 if (isTreePathContentProvider() && null !is cast(Item) widget ) { | |
2581 TreePath path = getTreePathFromItem(cast(Item) widget); | |
2582 elementChildren = getSortedChildren(path); | |
2583 } else { | |
2584 elementChildren = getSortedChildren(parent); | |
2585 } | |
2586 } | |
2587 | |
2588 Control tree = getControl(); | |
2589 | |
2590 // WORKAROUND | |
2591 int oldCnt = -1; | |
2592 if (widget is tree) { | |
2593 oldCnt = getItemCount(tree); | |
2594 } | |
2595 | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2596 Item[] items = getChildren(widget,elementChildren); |
71 | 2597 |
10 | 2598 // save the expanded elements |
2599 CustomHashtable expanded = newHashtable(CustomHashtable.DEFAULT_CAPACITY); // assume | |
2600 // num | |
2601 // expanded | |
2602 // is | |
2603 // small | |
2604 for (int i = 0; i < items.length; ++i) { | |
2605 if (getExpanded(items[i])) { | |
2606 Object element = items[i].getData(); | |
2607 if (element !is null) { | |
2608 expanded.put(element, element); | |
2609 } | |
2610 } | |
2611 } | |
2612 | |
2613 int min = Math.min(elementChildren.length, items.length); | |
2614 | |
2615 // dispose of surplus items, optimizing for the case where elements have | |
2616 // been deleted but not reordered, or all elements have been removed. | |
2617 int numItemsToDispose = items.length - min; | |
2618 if (numItemsToDispose > 0) { | |
2619 CustomHashtable children = newHashtable(elementChildren.length * 2); | |
2620 for (int i = 0; i < elementChildren.length; i++) { | |
2621 Object elementChild = elementChildren[i]; | |
2622 children.put(elementChild, elementChild); | |
2623 } | |
2624 int i = 0; | |
2625 while (numItemsToDispose > 0 && i < items.length) { | |
2626 Object data = items[i].getData(); | |
2627 if (data is null || items.length - i <= numItemsToDispose || !children.containsKey(data)) { | |
2628 if (data !is null) { | |
2629 disassociate(items[i]); | |
2630 } | |
2631 items[i].dispose(); | |
2632 if (i + 1 < items.length) { | |
2633 // The components at positions i+1 through | |
2634 // items.length-1 in the source array are copied into | |
2635 // positions i through items.length-2 | |
2636 System.arraycopy(items, i + 1, items, i, items.length - (i+1)); | |
2637 } | |
2638 numItemsToDispose--; | |
2639 } else { | |
2640 i++; | |
2641 } | |
2642 } | |
2643 } | |
2644 | |
2645 // compare first min items, and update item if necessary | |
2646 // need to do it in two passes: | |
2647 // 1: disassociate old items | |
2648 // 2: associate new items | |
2649 // because otherwise a later disassociate can remove a mapping made for | |
2650 // a previous associate, | |
2651 // making the map inconsistent | |
2652 for (int i = 0; i < min; ++i) { | |
2653 Item item = items[i]; | |
2654 Object oldElement = item.getData(); | |
2655 if (oldElement !is null) { | |
2656 Object newElement = elementChildren[i]; | |
2657 if (newElement !is oldElement) { | |
2658 if (opEquals(newElement, oldElement)) { | |
2659 // update the data to be the new element, since | |
2660 // although the elements | |
2661 // may be equal, they may still have different labels | |
2662 // or children | |
2663 Object data = item.getData(); | |
2664 if (data !is null) { | |
2665 unmapElement(data, item); | |
2666 } | |
2667 item.setData(newElement); | |
2668 mapElement(newElement, item); | |
2669 } else { | |
2670 disassociate(item); | |
2671 // Clear the text and image to force a label update | |
2672 item.setImage(null); | |
2673 item.setText("");//$NON-NLS-1$ | |
2674 | |
2675 } | |
2676 } | |
2677 } | |
2678 } | |
2679 | |
2680 for (int i = 0; i < min; ++i) { | |
2681 Item item = items[i]; | |
2682 Object newElement = elementChildren[i]; | |
2683 if (item.getData() is null) { | |
2684 // old and new elements are not equal | |
2685 associate(newElement, item); | |
2686 updatePlus(item, newElement); | |
2687 updateItem(item, newElement); | |
2688 } else { | |
2689 // old and new elements are equal | |
2690 updatePlus(item, newElement); | |
2691 if (updateLabels) { | |
2692 updateItem(item, newElement); | |
2693 } | |
2694 } | |
2695 } | |
2696 | |
2697 // Restore expanded state for items that changed position. | |
2698 // Make sure setExpanded is called after updatePlus, since | |
2699 // setExpanded(false) fails if item has no children. | |
2700 // Need to call setExpanded for both expanded and unexpanded | |
2701 // cases since the expanded state can change either way. | |
2702 // This needs to be done in a second loop, see bug 148025. | |
2703 for (int i = 0; i < min; ++i) { | |
2704 Item item = items[i]; | |
2705 Object newElement = elementChildren[i]; | |
2706 setExpanded(item, expanded.containsKey(newElement)); | |
2707 } | |
2708 | |
2709 // add any remaining elements | |
2710 if (min < elementChildren.length) { | |
2711 for (int i = min; i < elementChildren.length; ++i) { | |
2712 createTreeItem(widget, elementChildren[i], i); | |
2713 } | |
2714 | |
2715 // Need to restore expanded state in a separate pass | |
2716 // because createTreeItem does not return the new item. | |
2717 // Avoid doing this unless needed. | |
2718 if (expanded.size() > 0) { | |
2719 // get the items again, to include the new items | |
2720 items = getChildren(widget); | |
2721 for (int i = min; i < elementChildren.length; ++i) { | |
2722 // Restore expanded state for items that changed position. | |
2723 // Make sure setExpanded is called after updatePlus (called | |
2724 // in createTreeItem), since | |
2725 // setExpanded(false) fails if item has no children. | |
2726 // Only need to call setExpanded if element was expanded | |
2727 // since new items are initially unexpanded. | |
2728 if (expanded.containsKey(elementChildren[i])) { | |
2729 setExpanded(items[i], true); | |
2730 } | |
2731 } | |
2732 } | |
2733 } | |
2734 | |
2735 // WORKAROUND | |
2736 if (widget is tree && oldCnt is 0 && getItemCount(tree) !is 0) { | |
2737 // System.out.println("WORKAROUND setRedraw"); | |
2738 tree.setRedraw(false); | |
2739 tree.setRedraw(true); | |
2740 } | |
2741 } | |
2742 | |
2743 /** | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2744 * Return the items to be refreshed as part of an update. elementChildren are the |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2745 * new elements. |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2746 * @param widget |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2747 * @param elementChildren |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2748 * @since 3.4 |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2749 * @return Item[] |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2750 * <strong>NOTE:</strong> This API is experimental and may be deleted |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2751 * before 3.4 is released. |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2752 */ |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2753 public Item[] getChildren(Widget widget, Object[] elementChildren) { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2754 return getChildren(widget); |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2755 } |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2756 |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2757 /** |
10 | 2758 * Updates the "+"/"-" icon of the tree node from the given element. It |
2759 * calls <code>isExpandable</code> to determine whether an element is | |
2760 * expandable. | |
2761 * | |
2762 * @param item | |
2763 * the item | |
2764 * @param element | |
2765 * the element | |
2766 */ | |
2767 protected void updatePlus(Item item, Object element) { | |
2768 bool hasPlus = getItemCount(item) > 0; | |
2769 bool needsPlus = isExpandable(item, null, element); | |
2770 bool removeAll = false; | |
2771 bool addDummy = false; | |
2772 Object data = item.getData(); | |
2773 if (data !is null && opEquals(element, data)) { | |
2774 // item shows same element | |
2775 if (hasPlus !is needsPlus) { | |
2776 if (needsPlus) { | |
2777 addDummy = true; | |
2778 } else { | |
2779 removeAll = true; | |
2780 } | |
2781 } | |
2782 } else { | |
2783 // item shows different element | |
2784 removeAll = true; | |
2785 addDummy = needsPlus; | |
2786 | |
2787 // we cannot maintain expand state so collapse it | |
2788 setExpanded(item, false); | |
2789 } | |
2790 if (removeAll) { | |
2791 // remove all children | |
2792 Item[] items = getItems(item); | |
2793 for (int i = 0; i < items.length; i++) { | |
2794 if (items[i].getData() !is null) { | |
2795 disassociate(items[i]); | |
2796 } | |
2797 items[i].dispose(); | |
2798 } | |
2799 } | |
2800 if (addDummy) { | |
2801 newItem(item, DWT.NULL, -1); // append a dummy | |
2802 } | |
2803 } | |
2804 | |
2805 /** | |
2806 * Gets the expanded elements that are visible to the user. An expanded | |
2807 * element is only visible if the parent is expanded. | |
2808 * | |
2809 * @return the visible expanded elements | |
2810 * @since 2.0 | |
2811 */ | |
2812 public Object[] getVisibleExpandedElements() { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2813 ArrayList v = new ArrayList(); |
10 | 2814 internalCollectVisibleExpanded(v, getControl()); |
2815 return v.toArray(); | |
2816 } | |
2817 | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2818 private void internalCollectVisibleExpanded(ArrayList result, Widget widget) { |
10 | 2819 Item[] items = getChildren(widget); |
2820 for (int i = 0; i < items.length; i++) { | |
2821 Item item = items[i]; | |
2822 if (getExpanded(item)) { | |
2823 Object data = item.getData(); | |
2824 if (data !is null) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2825 result.add(data); |
10 | 2826 } |
2827 // Only recurse if it is expanded - if | |
2828 // not then the children aren't visible | |
2829 internalCollectVisibleExpanded(result, item); | |
2830 } | |
2831 } | |
2832 } | |
2833 | |
2834 /** | |
2835 * Returns the tree path for the given item. | |
2836 * @param item | |
2837 * @return {@link TreePath} | |
2838 * | |
2839 * @since 3.2 | |
2840 */ | |
2841 protected TreePath getTreePathFromItem(Item item) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2842 LinkedList segments = new LinkedList(); |
10 | 2843 while (item !is null) { |
2844 Object segment = item.getData(); | |
2845 Assert.isNotNull(segment); | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2846 segments.addFirst(segment); |
10 | 2847 item = getParentItem(item); |
2848 } | |
2849 return new TreePath(segments.toArray()); | |
2850 } | |
2851 package TreePath getTreePathFromItem_package(Item item) { | |
2852 return getTreePathFromItem_package(item); | |
2853 } | |
2854 | |
2855 /** | |
2856 * This implementation of getSelection() returns an instance of | |
2857 * ITreeSelection. | |
2858 * | |
2859 * @since 3.2 | |
2860 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
2861 public override ISelection getSelection() { |
10 | 2862 Control control = getControl(); |
2863 if (control is null || control.isDisposed()) { | |
2864 return TreeSelection.EMPTY; | |
2865 } | |
2866 Widget[] items = getSelection(getControl()); | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2867 ArrayList list = new ArrayList(items.length); |
10 | 2868 for (int i = 0; i < items.length; i++) { |
2869 Widget item = items[i]; | |
2870 if (item.getData() !is null) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2871 list.add(getTreePathFromItem(cast(Item) item)); |
10 | 2872 } |
2873 } | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2874 return new TreeSelection( arraycast!(TreePath)(list.toArray()), getComparer()); |
10 | 2875 } |
2876 | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
2877 protected override void setSelectionToWidget(ISelection selection, bool reveal) { |
10 | 2878 if ( auto treeSelection = cast(ITreeSelection)selection ) { |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2879 setSelectionToWidget(Arrays.asList(treeSelection.getPaths()), |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2880 reveal); |
10 | 2881 } else { |
2882 super.setSelectionToWidget(selection, reveal); | |
2883 } | |
2884 } | |
2885 | |
2886 /** | |
2887 * Returns a list of tree paths corresponding to expanded nodes in this | |
2888 * viewer's tree, including currently hidden ones that are marked as | |
2889 * expanded but are under a collapsed ancestor. | |
2890 * <p> | |
2891 * This method is typically used when preserving the interesting state of a | |
2892 * viewer; <code>setExpandedElements</code> is used during the restore. | |
2893 * </p> | |
2894 * | |
2895 * @return the array of expanded tree paths | |
2896 * @see #setExpandedElements | |
2897 * | |
2898 * @since 3.2 | |
2899 */ | |
2900 public TreePath[] getExpandedTreePaths() { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2901 ArrayList items = new ArrayList(); |
10 | 2902 internalCollectExpandedItems(items, getControl()); |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2903 ArrayList result = new ArrayList(items.size()); |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2904 for (Iterator it = items.iterator(); it.hasNext();) { |
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2905 Item item = cast(Item) it.next(); |
10 | 2906 TreePath treePath = getTreePathFromItem(item); |
2907 if (treePath !is null) { | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2908 result.add(treePath); |
10 | 2909 } |
2910 } | |
104
04b47443bb01
Reworked the collection uses to make use of a wrapper collection that is compatible to the Java Collections.
Frank Benoit <benoit@tionex.de>
parents:
72
diff
changeset
|
2911 return arraycast!(TreePath)(result.toArray()); |
10 | 2912 } |
2913 | |
2914 private bool isTreePathContentProvider() { | |
2915 return null !is cast(ITreePathContentProvider)getContentProvider() ; | |
2916 } | |
2917 | |
2918 /** | |
2919 * Inserts the given element as a new child element of the given parent | |
2920 * element at the given position. If this viewer has a sorter, the position | |
2921 * is ignored and the element is inserted at the correct position in the | |
2922 * sort order. | |
2923 * <p> | |
2924 * This method should be called (by the content provider) when elements have | |
2925 * been added to the model, in order to cause the viewer to accurately | |
2926 * reflect the model. This method only affects the viewer, not the model. | |
2927 * </p> | |
2928 * | |
2929 * @param parentElementOrTreePath | |
2930 * the parent element, or the tree path to the parent | |
2931 * @param element | |
2932 * the element | |
2933 * @param position | |
2934 * a 0-based position relative to the model, or -1 to indicate | |
2935 * the last position | |
2936 * | |
2937 * @since 3.2 | |
2938 */ | |
2939 public void insert(Object parentElementOrTreePath, Object element, | |
2940 int position) { | |
2941 Assert.isNotNull(parentElementOrTreePath); | |
2942 Assert.isNotNull(element); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2943 if (checkBusy()) |
10 | 2944 return; |
2945 if (getComparator() !is null || hasFilters()) { | |
2946 add(parentElementOrTreePath, [ element ]); | |
2947 return; | |
2948 } | |
2949 Widget[] items; | |
2950 if (internalIsInputOrEmptyPath(parentElementOrTreePath)) { | |
2951 items = [ getControl() ]; | |
2952 } else { | |
2953 items = internalFindItems(parentElementOrTreePath); | |
2954 } | |
2955 | |
2956 for (int i = 0; i < items.length; i++) { | |
2957 Widget widget = items[i]; | |
2958 if (auto item = cast(Item)widget ) { | |
2959 | |
2960 Item[] childItems = getChildren(item); | |
2961 if (getExpanded(item) | |
2962 || (childItems.length > 0 && childItems[0].getData() !is null)) { | |
2963 // item has real children, go ahead and add | |
2964 int insertionPosition = position; | |
2965 if (insertionPosition is -1) { | |
2966 insertionPosition = getItemCount(item); | |
2967 } | |
2968 | |
2969 createTreeItem(item, element, insertionPosition); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2970 } else { |
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2971 Object parentElement = parentElementOrTreePath; |
71 | 2972 if (null !is cast(TreePath)element ) |
2973 parentElement = (cast(TreePath) parentElement).getLastSegment(); | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
2974 updatePlus(item, parentElement); |
10 | 2975 } |
2976 } else { | |
2977 int insertionPosition = position; | |
2978 if (insertionPosition is -1) { | |
2979 insertionPosition = getItemCount(cast(Control) widget); | |
2980 } | |
2981 | |
2982 createTreeItem(widget, element, insertionPosition); | |
2983 } | |
2984 } | |
2985 } | |
2986 | |
2987 /* | |
2988 * (non-Javadoc) | |
2989 * | |
2990 * @see dwtx.jface.viewers.ColumnViewer#getColumnViewerOwner(int) | |
2991 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
2992 protected override Widget getColumnViewerOwner(int columnIndex) { |
10 | 2993 // Return null by default |
2994 return null; | |
2995 } | |
2996 | |
2997 /** | |
2998 * This implementation of {@link #getItemAt(Point)} returns null to ensure | |
2999 * API backwards compatibility. Subclasses should override. | |
3000 * | |
3001 * @since 3.3 | |
3002 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
3003 protected override Item getItemAt(Point point) { |
10 | 3004 return null; |
3005 } | |
3006 | |
3007 /** | |
3008 * This implementation of {@link #createViewerEditor()} returns null to ensure | |
3009 * API backwards compatibility. Subclasses should override. | |
3010 * | |
3011 * @since 3.3 | |
3012 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
3013 protected override ColumnViewerEditor createViewerEditor() { |
10 | 3014 return null; |
3015 } | |
3016 | |
3017 /** | |
3018 * Returns the number of columns of this viewer. | |
3019 * <p><b>Subclasses should overwrite this method, which has a default | |
3020 * implementation (returning 0) for API backwards compatility reasons</b></p> | |
3021 * | |
3022 * @return the number of columns | |
3023 * | |
3024 * @since 3.3 | |
3025 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
3026 protected override int doGetColumnCount() { |
10 | 3027 return 0; |
3028 } | |
3029 | |
3030 | |
3031 /** | |
3032 * This implementation of buildLabel handles tree paths as well as elements. | |
3033 * | |
3034 * @param updateLabel | |
3035 * the ViewerLabel to collect the result in | |
3036 * @param elementOrPath | |
3037 * the element or tree path for which a label should be built | |
3038 * | |
3039 * @see dwtx.jface.viewers.StructuredViewer#buildLabel(dwtx.jface.viewers.ViewerLabel, | |
3040 * java.lang.Object) | |
3041 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
3042 protected override void buildLabel(ViewerLabel updateLabel, Object elementOrPath) { |
10 | 3043 Object element; |
3044 if (auto path = cast(TreePath)elementOrPath ) { | |
3045 IBaseLabelProvider provider = getLabelProvider(); | |
3046 if ( auto pprov = cast(ITreePathLabelProvider) provider ) { | |
3047 buildLabel(updateLabel, path, pprov); | |
3048 return; | |
3049 } | |
3050 element = path.getLastSegment(); | |
3051 } else { | |
3052 element = elementOrPath; | |
3053 } | |
3054 super.buildLabel(updateLabel, element); | |
3055 } | |
3056 | |
3057 /** | |
3058 * Returns true if the given object is either the input or an empty tree path. | |
3059 * | |
3060 * @param elementOrTreePath an element which could either be the viewer's input, or a tree path | |
3061 * | |
3062 * @return <code>true</code> if the given object is either the input or an empty tree path, | |
3063 * <code>false</code> otherwise. | |
3064 * @since 3.3 | |
3065 */ | |
3066 final protected bool internalIsInputOrEmptyPath(Object elementOrTreePath) { | |
70
46a6e0e6ccd4
Merge with d-fied sources of 3.4M7
Frank Benoit <benoit@tionex.de>
parents:
54
diff
changeset
|
3067 if (elementOrTreePath.opEquals(getRoot())) |
10 | 3068 return true; |
3069 if (!(cast(TreePath)elementOrTreePath )) | |
3070 return false; | |
3071 return (cast(TreePath) elementOrTreePath).getSegmentCount() is 0; | |
3072 } | |
3073 | |
3074 /* | |
3075 * Subclasses should implement | |
3076 */ | |
43
ea8ff534f622
Fix override and super aliases
Frank Benoit <benoit@tionex.de>
parents:
40
diff
changeset
|
3077 protected override ViewerRow getViewerRowFromItem(Widget item) { |
10 | 3078 return null; |
3079 } | |
3080 } |