View | Details | Raw Unified | Return to bug 126459
Collapse All | Expand All

(-)src/org/eclipse/ui/navigator/internal/DelegateTreeViewerSorter.java (-67 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.ui.navigator.internal;
13
14
import java.text.Collator;
15
16
import org.eclipse.core.runtime.Assert;
17
import org.eclipse.jface.viewers.Viewer;
18
import org.eclipse.jface.viewers.ViewerSorter;
19
import org.eclipse.ui.navigator.TreeViewerSorter;
20
21
/**
22
 * @since 3.2
23
 *
24
 */
25
public class DelegateTreeViewerSorter extends TreeViewerSorter {
26
 
27
	private ViewerSorter delegateSorter;
28
29
	public DelegateTreeViewerSorter(ViewerSorter aSorter) {
30
		super();
31
		Assert.isNotNull(aSorter);
32
		delegateSorter = aSorter;
33
	}
34
35
	public int category(Object element) {
36
		return delegateSorter.category(element);
37
	}
38
39
	public int compare(Viewer viewer, Object e1, Object e2) {
40
		return delegateSorter.compare(viewer, e1, e2);
41
	}
42
43
	public boolean equals(Object obj) {
44
		return delegateSorter.equals(obj);
45
	}
46
47
	public Collator getCollator() {
48
		return delegateSorter.getCollator();
49
	}
50
51
	public int hashCode() {
52
		return delegateSorter.hashCode();
53
	}
54
55
	public boolean isSorterProperty(Object element, String property) {
56
		return delegateSorter.isSorterProperty(element, property);
57
	}
58
59
	public void sort(Viewer viewer, Object[] elements) {
60
		delegateSorter.sort(viewer, elements);
61
	}
62
63
	public String toString() {
64
		return delegateSorter.toString();
65
	}
66
67
}
(-)src/org/eclipse/ui/navigator/CommonViewerSorter.java (-17 / +11 lines)
Lines 11-22 Link Here
11
11
12
package org.eclipse.ui.navigator;
12
package org.eclipse.ui.navigator;
13
13
14
import java.util.Arrays;
14
import java.util.*;
15
import java.util.Comparator;
16
import java.util.Set;
17
15
18
import org.eclipse.jface.viewers.Viewer;
16
import org.eclipse.jface.viewers.*;
19
import org.eclipse.jface.viewers.ViewerSorter;
20
import org.eclipse.ui.navigator.internal.NavigatorContentService;
17
import org.eclipse.ui.navigator.internal.NavigatorContentService;
21
import org.eclipse.ui.navigator.internal.extensions.NavigatorContentDescriptor;
18
import org.eclipse.ui.navigator.internal.extensions.NavigatorContentDescriptor;
22
19
Lines 52-58 Link Here
52
 * @since 3.2
49
 * @since 3.2
53
 * 
50
 * 
54
 */
51
 */
55
public final class CommonViewerSorter extends TreeViewerSorter {
52
public final class CommonViewerSorter extends TreePathViewerSorter {
56
53
57
	private NavigatorContentService contentService;
54
	private NavigatorContentService contentService;
58
55
Lines 83-103 Link Here
83
				: Priority.LOW_PRIORITY_VALUE;
80
				: Priority.LOW_PRIORITY_VALUE;
84
	}
81
	}
85
82
86
	public void sort(final Viewer viewer, final Object parent, Object[] elements) {
83
	public int compare(Viewer viewer, TreePath parentPath, Object e1, Object e2) {
87
88
		Arrays.sort(elements, new Comparator() {
89
			public int compare(Object a, Object b) {
90
				return CommonViewerSorter.this.compare(viewer, parent, a, b);
91
			}
92
		});
93
	}
94
95
	public int compare(Viewer viewer, Object parent, Object e1, Object e2) {
96
		INavigatorContentDescriptor sourceOfLvalue = getSource(e1);
84
		INavigatorContentDescriptor sourceOfLvalue = getSource(e1);
97
		INavigatorContentDescriptor sourceOfRvalue = getSource(e2);
85
		INavigatorContentDescriptor sourceOfRvalue = getSource(e2);
98
86
99
		// identity comparison
87
		// identity comparison
100
		if (sourceOfLvalue != null && sourceOfLvalue == sourceOfRvalue) {
88
		if (sourceOfLvalue != null && sourceOfLvalue == sourceOfRvalue) {
89
			Object parent;
90
			if (parentPath == null) {
91
				parent = viewer.getInput();
92
			} else {
93
				parent = parentPath.getLastSegment();
94
			}
101
			ViewerSorter sorter = sorterService.findSorter(sourceOfLvalue, parent, e1, e2);
95
			ViewerSorter sorter = sorterService.findSorter(sourceOfLvalue, parent, e1, e2);
102
			if(sorter != null)
96
			if(sorter != null)
103
				return sorter.compare(viewer, e1, e2);
97
				return sorter.compare(viewer, e1, e2);
Lines 106-112 Link Here
106
		if (categoryDelta == 0) {
100
		if (categoryDelta == 0) {
107
			super.compare(viewer, e1, e2);
101
			super.compare(viewer, e1, e2);
108
		}
102
		}
109
		return categoryDelta;
103
		return -1 * categoryDelta;
110
	} 
104
	} 
111
105
112
	private INavigatorContentDescriptor getSource(Object o) {
106
	private INavigatorContentDescriptor getSource(Object o) {
(-)src/org/eclipse/ui/navigator/CommonViewer.java (-240 / +5 lines)
Lines 13-34 Link Here
13
import java.util.ArrayList;
13
import java.util.ArrayList;
14
import java.util.List;
14
import java.util.List;
15
15
16
import org.eclipse.jface.viewers.DecoratingLabelProvider;
16
import org.eclipse.jface.viewers.*;
17
import org.eclipse.jface.viewers.IBaseLabelProvider;
17
import org.eclipse.swt.dnd.*;
18
import org.eclipse.jface.viewers.ITreeContentProvider;
19
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
20
import org.eclipse.jface.viewers.TreeViewer;
21
import org.eclipse.jface.viewers.ViewerSorter;
22
import org.eclipse.swt.SWT;
23
import org.eclipse.swt.dnd.DND;
24
import org.eclipse.swt.dnd.FileTransfer;
25
import org.eclipse.swt.dnd.Transfer;
26
import org.eclipse.swt.events.DisposeEvent;
18
import org.eclipse.swt.events.DisposeEvent;
27
import org.eclipse.swt.widgets.Composite;
19
import org.eclipse.swt.widgets.*;
28
import org.eclipse.swt.widgets.Item;
29
import org.eclipse.swt.widgets.Widget;
30
import org.eclipse.ui.PlatformUI;
20
import org.eclipse.ui.PlatformUI;
31
import org.eclipse.ui.navigator.internal.DelegateTreeViewerSorter;
32
import org.eclipse.ui.navigator.internal.NavigatorContentService;
21
import org.eclipse.ui.navigator.internal.NavigatorContentService;
33
import org.eclipse.ui.navigator.internal.dnd.CommonNavigatorDragAdapter;
22
import org.eclipse.ui.navigator.internal.dnd.CommonNavigatorDragAdapter;
34
import org.eclipse.ui.navigator.internal.dnd.CommonNavigatorDropAdapter;
23
import org.eclipse.ui.navigator.internal.dnd.CommonNavigatorDropAdapter;
Lines 151-178 Link Here
151
	}
140
	}
152
141
153
	/**
142
	/**
154
	 * Returns the sorted and filtered set of children of the given element. The
155
	 * resulting array must not be modified, as it may come directly from the
156
	 * model's internal state.
157
	 * 
158
	 * @param parent
159
	 *            the parent element
160
	 * @return a sorted and filtered array of child elements
161
	 */
162
	protected Object[] getSortedChildren(Object parent) {
163
		Object[] result = getFilteredChildren(parent);
164
		ViewerSorter sorter = getSorter();
165
		if (sorter != null) {
166
			// be sure we're not modifying the original array from the model
167
			result = (Object[]) result.clone();
168
			// safe caste due to setSorter();
169
			((TreeViewerSorter) sorter).sort(this, parent, result);
170
171
		}
172
		return result;
173
	}
174
175
	/**
176
	 * Sets this viewer's sorter and triggers refiltering and resorting of this
143
	 * Sets this viewer's sorter and triggers refiltering and resorting of this
177
	 * viewer's element. Passing <code>null</code> turns sorting off.
144
	 * viewer's element. Passing <code>null</code> turns sorting off.
178
	 * 
145
	 * 
Lines 182-392 Link Here
182
	public void setSorter(ViewerSorter sorter) {
149
	public void setSorter(ViewerSorter sorter) {
183
		if (sorter != null && sorter instanceof CommonViewerSorter)
150
		if (sorter != null && sorter instanceof CommonViewerSorter)
184
			((CommonViewerSorter) sorter).setContentService(contentService);
151
			((CommonViewerSorter) sorter).setContentService(contentService);
185
152
		super.setSorter(sorter);
186
		if (sorter == null || sorter instanceof TreeViewerSorter)
187
			super.setSorter(sorter);
188
		else /* we wrap the sorter for convenience (now we can always cast to TreeViewerSorter) */
189
			super.setSorter(new DelegateTreeViewerSorter(sorter));
190
	}
153
	}
191
154
	
192
	// Had to pull down the following code to tap into the sorting
193
194
	/**
195
	 * Adds the given child elements to this viewer as children of the given
196
	 * parent element.
197
	 * <p>
198
	 * EXPERIMENTAL. Not to be used except by JDT. This method was added to
199
	 * support JDT's explorations into grouping by working sets, which requires
200
	 * viewers to support multiple equal elements. See bug 76482 for more
201
	 * details. This support will likely be removed in Eclipse 3.2 in favour of
202
	 * proper support for multiple equal elements.
203
	 * </p>
204
	 * 
205
	 * @param widget
206
	 *            the widget for the parent element
207
	 * @param parentElement
208
	 *            the parent element
209
	 * @param childElements
210
	 *            the child elements to add
211
	 * @since 3.1
212
	 */
213
	protected void internalAdd(Widget widget, Object parentElement,
214
			Object[] childElements) {
215
216
		// optimization!
217
		// if the widget is not expanded we just invalidate the subtree
218
		if (widget instanceof Item) {
219
			Item ti = (Item) widget;
220
			if (!getExpanded(ti)) {
221
				boolean needDummy = isExpandable(parentElement);
222
				boolean haveDummy = false;
223
				// remove all children
224
				Item[] items = getItems(ti);
225
				for (int i = 0; i < items.length; i++) {
226
					if (items[i].getData() != null) {
227
						disassociate(items[i]);
228
						items[i].dispose();
229
					} else {
230
						if (needDummy && !haveDummy) {
231
							haveDummy = true;
232
						} else {
233
							items[i].dispose();
234
						}
235
					}
236
				}
237
				// append a dummy if necessary
238
				if (needDummy && !haveDummy)
239
					newItem(ti, SWT.NULL, -1);
240
				return;
241
			}
242
		}
243
244
		if (childElements.length > 0) {
245
			Object[] filtered = filter(childElements);
246
			if (getSorter() != null)
247
				((TreeViewerSorter) getSorter()).sort(this, parentElement,
248
						filtered);
249
			createAddedElements(widget, parentElement, filtered);
250
		}
251
	}
252
253
	/**
254
	 * See if element is the data of one of the elements in items.
255
	 * 
256
	 * @param items
257
	 * @param element
258
	 * @return <code>true</code> if the element matches.
259
	 */
260
	private boolean itemExists(Item[] items, Object element) {
261
		if (usingElementMap())// if we can do a constant time lookup find it
262
			return findItem(element) != null;
263
		for (int i = 0; i < items.length; i++) {
264
			if (items[i].getData().equals(element))
265
				return true;
266
		}
267
		return false;
268
	}
269
270
	/**
271
	 * Create the new elements in the parent widget. If the child already exists
272
	 * do nothing.
273
	 * 
274
	 * @param widget
275
	 * @param elements
276
	 *            Sorted list of elements to add.
277
	 */
278
	private void createAddedElements(Widget widget, Object parent,
279
			Object[] elements) {
280
281
		if (elements.length == 1) {
282
			if (equals(elements[0], widget.getData()))
283
				return;
284
		}
285
286
		// safe caste due to setSorter();
287
		TreeViewerSorter sorter = (TreeViewerSorter) getSorter();
288
		Item[] items = getChildren(widget);
289
290
		// As the items are sorted already we optimize for a
291
		// start position
292
		int lastInsertion = 0;
293
294
		// Optimize for the empty case
295
		if (items.length == 0) {
296
			for (int i = 0; i < elements.length; i++) {
297
				createTreeItem(widget, elements[i], -1);
298
			}
299
			return;
300
		}
301
302
		for (int i = 0; i < elements.length; i++) {
303
			boolean newItem = true;
304
			Object element = elements[i];
305
			int index;
306
			if (getSorter() == null) {
307
				if (itemExists(items, element)) {
308
					refresh(element);
309
					newItem = false;
310
				}
311
				index = -1;
312
			} else {
313
				lastInsertion = insertionPosition(items, lastInsertion, sorter,
314
						parent, element);
315
				// As we are only searching the original array we keep track of
316
				// those positions only
317
				if (lastInsertion == items.length)
318
					index = -1;
319
				else {// See if we should just refresh
320
					while (lastInsertion < items.length
321
							&& sorter.compare(this, parent, element,
322
									items[lastInsertion].getData()) == 0) {
323
						// As we cannot assume the sorter is consistent with
324
						// equals() - therefore we can
325
						// just check against the item prior to this index (if
326
						// any)
327
						if (items[lastInsertion].getData().equals(element)) {
328
							// refresh the element in case it has new children
329
							refresh(element);
330
							newItem = false;
331
						}
332
						lastInsertion++;// We had an insertion so increment
333
					}
334
					// Did we get to the end?
335
					if (lastInsertion == items.length)
336
						index = -1;
337
					else
338
						index = lastInsertion + i; // Add the index as the
339
					// array is growing
340
				}
341
			}
342
			if (newItem)
343
				createTreeItem(widget, element, index);
344
		}
345
	}
346
347
	/**
348
	 * Returns the index where the item should be inserted. It uses sorter to
349
	 * determine the correct position, if sorter is not assigned, returns the
350
	 * index of the element after the last.
351
	 * 
352
	 * @param items
353
	 *            the items to search
354
	 * @param lastInsertion
355
	 *            the start index to start search for position from this allows
356
	 *            optimising search for multiple elements that are sorted
357
	 *            themself.
358
	 * @param element
359
	 *            element to find position for.
360
	 * @return the index to use when inserting the element.
361
	 * 
362
	 */
363
364
	private int insertionPosition(Item[] items, int lastInsertion,
365
			TreeViewerSorter sorter, Object parent, Object element) {
366
367
		int size = items.length;
368
		if (getSorter() == null)
369
			return size;
370
		int min = lastInsertion, max = size - 1;
371
372
		while (min <= max) {
373
			int mid = (min + max) / 2;
374
			Object data = items[mid].getData();
375
			int compare = sorter.compare(this, parent, data, element);
376
			if (compare == 0) {
377
				return mid;// Return if we already match
378
			}
379
			if (compare < 0)
380
				min = mid + 1;
381
			else
382
				max = mid - 1;
383
		}
384
		return min;
385
386
	}
387
388
	// End of pulled down code
389
390
	/**
155
	/**
391
	 * <p>
156
	 * <p>
392
	 * Adds DND support to the Navigator. Uses hooks into the extensible
157
	 * Adds DND support to the Navigator. Uses hooks into the extensible
(-)src/org/eclipse/ui/navigator/TreeViewerSorter.java (-93 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.ui.navigator;
13
14
import org.eclipse.jface.viewers.Viewer;
15
import org.eclipse.jface.viewers.ViewerSorter;
16
17
/**
18
 * 
19
 * Provides context sensitive sorting of elements based on their parent in the
20
 * tree.
21
 * 
22
 * <p>
23
 * Clients may extend this class.
24
 * </p>
25
 * 
26
 * <p>
27
 * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
28
 * part of a work in progress. There is a guarantee neither that this API will
29
 * work nor that it will remain the same. Please do not use this API without
30
 * consulting with the Platform/UI team.
31
 * </p>
32
 * 
33
 * @since 3.2
34
 * 
35
 */
36
public class TreeViewerSorter extends ViewerSorter {
37
38
	/**
39
	 * Sorts the given elements in-place taking into account the parent of the
40
	 * elements, modifying the given array.
41
	 * <p>
42
	 * The default implementation of this method uses the java.util.Arrays#sort
43
	 * algorithm on the given array, calling <code>compare</code> to compare
44
	 * elements, and the parent does not affect sorting algorithm.
45
	 * </p>
46
	 * <p>
47
	 * Subclasses may reimplement this method to provide a more optimized
48
	 * implementation.
49
	 * </p>
50
	 * <p>
51
	 * 
52
	 * 
53
	 * @param viewer
54
	 *            the viewer
55
	 * @param parent
56
	 *            The parent element in the tree of both children.
57
	 * @param elements
58
	 *            the elements to sort
59
	 */
60
	public void sort(final Viewer viewer, final Object parent, Object[] elements) {
61
		super.sort(viewer, elements);
62
	}
63
64
	/**
65
	 * Returns a negative, zero, or positive number depending on whether the
66
	 * first element is less than, equal to, or greater than the second element.
67
	 * <p>
68
	 * The default implementation of this method is based on comparing the
69
	 * elements' categories as computed by the <code>category</code> framework
70
	 * method. Elements within the same category are further subjected to a case
71
	 * insensitive compare of their label strings, either as computed by the
72
	 * content viewer's label provider, or their <code>toString</code> values
73
	 * in other cases. Subclasses may override.
74
	 * </p>
75
	 * 
76
	 * @param viewer
77
	 *            the viewer
78
	 * @param parent
79
	 *            The parent element in the tree of both children.
80
	 * @param e1
81
	 *            the first element
82
	 * @param e2
83
	 *            the second element
84
	 * @return a negative number if the first element is less than the second
85
	 *         element; the value <code>0</code> if the first element is equal
86
	 *         to the second element; and a positive number if the first element
87
	 *         is greater than the second element
88
	 */
89
	public int compare(Viewer viewer, Object parent, Object e1, Object e2) {
90
		return super.compare(viewer, e1, e2);
91
	}
92
93
}
(-)src/org/eclipse/jface/viewers/AbstractTreeViewer.java (-11 / +116 lines)
Lines 201-206 Link Here
201
		}
201
		}
202
		
202
		
203
		ViewerSorter sorter = getSorter ();
203
		ViewerSorter sorter = getSorter ();
204
		TreePath parentPath = internalGetSorterParentPath(widget, sorter);
204
		Item[] items = getChildren(widget);
205
		Item[] items = getChildren(widget);
205
		
206
		
206
		//As the items are sorted already we optimize for a 
207
		//As the items are sorted already we optimize for a 
Lines 227-238 Link Here
227
				index = -1;
228
				index = -1;
228
			}
229
			}
229
			else{
230
			else{
230
				lastInsertion = insertionPosition(items,sorter,lastInsertion, element);
231
				lastInsertion = insertionPosition(items,sorter,lastInsertion, element, parentPath);
231
				//As we are only searching the original array we keep track of those positions only
232
				//As we are only searching the original array we keep track of those positions only
232
				if(lastInsertion == items.length)
233
				if(lastInsertion == items.length)
233
					index = -1;
234
					index = -1;
234
				else{//See if we should just refresh
235
				else{//See if we should just refresh
235
					while(lastInsertion < items.length && sorter.compare(this,element,items[lastInsertion].getData()) == 0){
236
					while(lastInsertion < items.length && internalCompare(sorter,parentPath,element,items[lastInsertion].getData()) == 0){
236
						//As we cannot assume the sorter is consistent with equals() - therefore we can
237
						//As we cannot assume the sorter is consistent with equals() - therefore we can
237
						// just check against the item prior to this index (if any)
238
						// just check against the item prior to this index (if any)
238
						if (items[lastInsertion].getData().equals(element)) {
239
						if (items[lastInsertion].getData().equals(element)) {
Lines 285-296 Link Here
285
     *            themself.
286
     *            themself.
286
     * @param element
287
     * @param element
287
     *            element to find position for.
288
     *            element to find position for.
289
     * @param parentPath the tree path for the element's parent or <code>null</code>
290
     * if the element is a root element or the sorter is not a {@link TreePathViewerSorter}
288
     * @return the index to use when inserting the element.
291
     * @return the index to use when inserting the element.
289
     * 
292
     * 
290
     */
293
     */
291
	
294
	
292
	private int insertionPosition(Item[] items,  ViewerSorter sorter, int lastInsertion, Object element) {
295
	private int insertionPosition(Item[] items,  ViewerSorter sorter, int lastInsertion, Object element, TreePath parentPath) {
293
	    
296
		
294
		int size = items.length;
297
		int size = items.length;
295
		if (sorter == null)
298
		if (sorter == null)
296
			return size;
299
			return size;
Lines 299-305 Link Here
299
		while (min <= max) {
302
		while (min <= max) {
300
            int mid = (min + max) / 2;
303
            int mid = (min + max) / 2;
301
            Object data = items[mid].getData();
304
            Object data = items[mid].getData();
302
            int compare = sorter.compare(this, data, element);
305
            int compare = internalCompare(sorter, parentPath, data, element);
303
            if (compare == 0) {
306
            if (compare == 0) {
304
                return mid;//Return if we already match
307
                return mid;//Return if we already match
305
            }
308
            }
Lines 343-349 Link Here
343
     */
346
     */
344
    protected int indexForElement(Widget parent, Object element) {
347
    protected int indexForElement(Widget parent, Object element) {
345
        ViewerSorter sorter = getSorter();
348
        ViewerSorter sorter = getSorter();
346
		
349
        TreePath parentPath = internalGetSorterParentPath(parent, sorter);
347
		
350
		
348
		Item[] items = getChildren(parent);
351
		Item[] items = getChildren(parent);
349
		int count = items.length;
352
		int count = items.length;
Lines 355-361 Link Here
355
        while (min <= max) {
358
        while (min <= max) {
356
            int mid = (min + max) / 2;
359
            int mid = (min + max) / 2;
357
            Object data = items[mid].getData();
360
            Object data = items[mid].getData();
358
            int compare = sorter.compare(this, data, element);
361
            int compare = internalCompare(sorter, parentPath, data, element);
359
            if (compare == 0) {
362
            if (compare == 0) {
360
                // find first item > element
363
                // find first item > element
361
                while (compare == 0) {
364
                while (compare == 0) {
Lines 364-370 Link Here
364
                        break;
367
                        break;
365
                    }
368
                    }
366
                    data = items[mid].getData();
369
                    data = items[mid].getData();
367
                    compare = sorter.compare(this, data, element);
370
                    compare = internalCompare(sorter, parentPath, data, element);
368
                }
371
                }
369
                return mid;
372
                return mid;
370
            }
373
            }
Lines 377-382 Link Here
377
    }
380
    }
378
381
379
    /**
382
    /**
383
     * Return the tree path that should be used as the parent path for the
384
     * given widget and sorter. A <code>null</code> is returned if either
385
     * the sorter is not a {@link TreePathViewerSorter} or if the parent
386
     * widget is not an {@link Item} (i.e. is the root of the tree).
387
     * 
388
     * @param parent the parent widget
389
     * @param sorter the sorter
390
     * @return the tree path that should be used as the parent path for the
391
     * given widget and sorter
392
     */
393
	private TreePath internalGetSorterParentPath(Widget parent, ViewerSorter sorter) {
394
		TreePath path;
395
		if (sorter instanceof TreePathViewerSorter && parent instanceof Item) {
396
			Item item = (Item) parent;
397
			path = getTreePathFromItem(item);
398
		} else {
399
			path = null;
400
		}
401
		return path;
402
	}
403
404
	/**
405
	 * Compare the two elements using the given sorter. If the
406
	 * sorter is a {@link TreePathViewerSorter}, the provided
407
	 * tree path will be used. If the tree path is null and the
408
	 * sorter is a tree path sorter, then the elements are root elements
409
	 * @param sorter the sorter
410
	 * @param parentPath the path of the elements' parent
411
	 * @param e1 the first element
412
	 * @param e2 the seocnd element
413
	 * @return the result of comparing the two elements
414
	 */
415
	private int internalCompare(ViewerSorter sorter, TreePath parentPath, Object e1, Object e2) {
416
		if (sorter instanceof TreePathViewerSorter) {
417
			TreePathViewerSorter tpvs = (TreePathViewerSorter) sorter;
418
			return tpvs.compare(this, parentPath, e1, e2);
419
		}
420
		return sorter.compare(this, e1, e2);
421
	}
422
	
423
	/**
424
	 * Return the sorted children for the given tree path. The 
425
	 * path is relative to the viewer input.
426
	 * A path of <code>null</code> indicates that the children for
427
	 * the input of the viewer are desired.
428
	 * @param parentPath the parent path
429
	 * @return the sorted children
430
	 * @since 3.2
431
	 */
432
	protected Object[] getSortedChildren(TreePath parentPath) {
433
		ViewerSorter sorter = getSorter();
434
		Object parent;
435
		if (parentPath == null) {
436
			parent = getInput();
437
		} else {
438
			parent = parentPath.getLastSegment();
439
		}
440
		if (sorter instanceof TreePathViewerSorter) {
441
			TreePathViewerSorter tpvs = (TreePathViewerSorter) sorter;
442
			Object[] result = getFilteredChildren(parent);
443
			// be sure we're not modifying the original array from the model
444
			result = (Object[]) result.clone();
445
			tpvs.sort(this, parentPath, result);
446
			return result;
447
		}
448
		return super.getSortedChildren(parent);
449
	}
450
	
451
	/* (non-Javadoc)
452
	 * @see org.eclipse.jface.viewers.StructuredViewer#getSortedChildren(java.lang.Object)
453
	 */
454
	protected Object[] getSortedChildren(Object parent) {
455
		ViewerSorter sorter = getSorter();
456
		if (sorter instanceof TreePathViewerSorter) {
457
			Widget w = internalGetWidgetToSelect(parent);
458
			if (w != null)
459
				return getSortedChildren(w, parent);
460
		}
461
		return super.getSortedChildren(parent);
462
	}
463
	
464
    /**
465
	 * Get the sorted children for the parent using a
466
	 * {@link TreePathViewerSorter} if there is one and
467
	 * {@link StructuredViewer#getSortedChildren(Object)} if there isn't.
468
	 * 
469
	 * @param widget
470
	 *            the widget for the parent
471
	 * @param parent
472
	 *            the parent element
473
	 * @return the sorted children
474
	 */
475
	private Object[] getSortedChildren(Widget widget, Object parent) {
476
		ViewerSorter sorter = getSorter();
477
		TreePath parentPath = internalGetSorterParentPath(widget, sorter);
478
		if (sorter instanceof TreePathViewerSorter) {
479
			return getSortedChildren(parentPath);
480
		}
481
		return super.getSortedChildren(parent);
482
	}
483
	
484
    /**
380
     * Adds the given child element to this viewer as a child of the given
485
     * Adds the given child element to this viewer as a child of the given
381
     * parent element. If this viewer does not have a sorter, the element is
486
     * parent element. If this viewer does not have a sorter, the element is
382
     * added at the end of the parent's list of children; otherwise, the
487
     * added at the end of the parent's list of children; otherwise, the
Lines 514-520 Link Here
514
                Object d = widget.getData();
619
                Object d = widget.getData();
515
                if (d != null) {
620
                if (d != null) {
516
                    Object parentElement = d;
621
                    Object parentElement = d;
517
                    Object[] children = getSortedChildren(parentElement);
622
                    Object[] children = getSortedChildren(widget, parentElement);
518
                    for (int i = 0; i < children.length; i++) {
623
                    for (int i = 0; i < children.length; i++) {
519
                        createTreeItem(widget, children[i], -1);
624
                        createTreeItem(widget, children[i], -1);
520
                    }
625
                    }
Lines 1953-1959 Link Here
1953
        // If the children weren't passed in, get them now since they're needed
2058
        // If the children weren't passed in, get them now since they're needed
1954
        // below.
2059
        // below.
1955
        if (elementChildren == null) {
2060
        if (elementChildren == null) {
1956
            elementChildren = getSortedChildren(parent);
2061
            elementChildren = getSortedChildren(widget, parent);
1957
        }
2062
        }
1958
2063
1959
        Control tree = getControl();
2064
        Control tree = getControl();
Lines 2083-2089 Link Here
2083
        }
2188
        }
2084
    }
2189
    }
2085
2190
2086
    /**
2191
	/**
2087
     * Updates the "+"/"-" icon of the tree node from the given element. It
2192
     * Updates the "+"/"-" icon of the tree node from the given element. It
2088
     * calls <code>isExpandable</code> to determine whether an element is
2193
     * calls <code>isExpandable</code> to determine whether an element is
2089
     * expandable.
2194
     * expandable.
(-)src/org/eclipse/jface/viewers/TreePathViewerSorter.java (+109 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.jface.viewers;
13
14
import java.util.Arrays;
15
import java.util.Comparator;
16
17
/**
18
 * A viewer sorter that is provded extra context in the form of the path of the
19
 * parent element of the elements being sorted.
20
 * 
21
 * @since 3.2
22
 */
23
public class TreePathViewerSorter extends ViewerSorter {
24
25
	/**
26
	 * Provide a category for the given element that will have the given parent
27
	 * path when it is added to the viewer. The provided path is
28
	 * relative to the viewer input. The parent path will
29
	 * be <code>null</code> when the elements are root elements.
30
	 * <p>
31
	 * By default, the this method calls
32
	 * {@link ViewerSorter#category(Object)}. Subclasses may override.
33
	 * 
34
	 * @param parentPath
35
	 *            the parent path for the element
36
	 * @param element
37
	 *            the element
38
	 * @return the category of the element
39
	 */
40
	public int category(TreePath parentPath, Object element) {
41
		return category(element);
42
	}
43
	
44
	/**
45
	 * Compare the givcen elements that will have the given parent
46
	 * path when they are added to the viewer. The provided path is
47
	 * relative to the viewer input. The parent path will
48
	 * be <code>null</code> when the elements are root elements.
49
	 * <p>
50
	 * By default, the this method calls
51
	 * {@link ViewerSorter#sort(Viewer, Object[])}. Subclasses may override.
52
	 * @param viewer the viewer
53
	 * @param parentPath the parent path for the two elements
54
     * @param e1 the first element
55
     * @param e2 the second element
56
     * @return a negative number if the first element is less  than the 
57
     *  second element; the value <code>0</code> if the first element is
58
     *  equal to the second element; and a positive
59
	 */
60
	public int compare(Viewer viewer, TreePath parentPath, Object e1, Object e2) {
61
		return compare(viewer, e1, e2);
62
	}
63
	
64
	/**
65
     * Returns whether this viewer sorter would be affected 
66
     * by a change to the given property of the given element.
67
     * The provided path is
68
	 * relative to the viewer input. The parent path will
69
	 * be <code>null</code> when the elements are root elements.
70
     * <p>
71
     * The default implementation of this method calls
72
     * {@link ViewerSorter#isSorterProperty(Object, String)}.
73
     * Subclasses may reimplement.
74
	 * @param parentPath the parent path of the element
75
     * @param element the element
76
     * @param property the property
77
     * @return <code>true</code> if the sorting would be affected,
78
     *    and <code>false</code> if it would be unaffected
79
	 */
80
    public boolean isSorterProperty(TreePath parentPath, Object element, String property) {
81
        return isSorterProperty(element, property);
82
    }
83
    
84
    /**
85
     * Sorts the given elements in-place, modifying the given array.
86
     * The provided path is
87
	 * relative to the viewer input. The parent path will
88
	 * be <code>null</code> when the elements are root elements.
89
     * <p>
90
     * The default implementation of this method uses the 
91
     * java.util.Arrays#sort algorithm on the given array, 
92
     * calling {@link #compare(Viewer, TreePath, Object, Object)} to compare elements.
93
     * </p>
94
     * <p>
95
     * Subclasses may reimplement this method to provide a more optimized implementation.
96
     * </p>
97
     *
98
     * @param viewer the viewer
99
     * @param parentPath the parent path of the given elements
100
     * @param elements the elements to sort
101
     */
102
    public void sort(final Viewer viewer, final TreePath parentPath, Object[] elements) {
103
        Arrays.sort(elements, new Comparator() {
104
            public int compare(Object a, Object b) {
105
                return TreePathViewerSorter.this.compare(viewer, parentPath, a, b);
106
            }
107
        });
108
    }
109
}

Return to bug 126459