Mercurial > projects > dwt2
comparison org.eclipse.jface/src/org/eclipse/jface/viewers/AbstractListViewer.d @ 12:bc29606a740c
Added dwt-addons in original directory structure of eclipse.org
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 14 Mar 2009 18:23:29 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
11:43904fec5dca | 12:bc29606a740c |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2004, 2007 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Chris Longfield <clongfield@internap.com> - Fix for Bug 70856 | |
11 * Tom Schindl - fix for bug 157309 | |
12 * Brad Reynolds - bug 141435 | |
13 * Port to the D programming language: | |
14 * Frank Benoit <benoit@tionex.de> | |
15 *******************************************************************************/ | |
16 | |
17 module org.eclipse.jface.viewers.AbstractListViewer; | |
18 | |
19 import org.eclipse.jface.viewers.StructuredViewer; | |
20 import org.eclipse.jface.viewers.ILabelProvider; | |
21 import org.eclipse.jface.viewers.IBaseLabelProvider; | |
22 import org.eclipse.jface.viewers.ViewerComparator; | |
23 import org.eclipse.jface.viewers.IElementComparer; | |
24 | |
25 | |
26 import org.eclipse.swt.widgets.Control; | |
27 import org.eclipse.swt.widgets.Widget; | |
28 import org.eclipse.core.runtime.Assert; | |
29 | |
30 import java.lang.all; | |
31 import java.util.Collection; | |
32 import java.util.List; | |
33 import java.util.ArrayList; | |
34 import java.util.Set; | |
35 | |
36 /** | |
37 * Abstract base class for viewers that contain lists of items (such as a combo or list). | |
38 * Most of the viewer implementation is in this base class, except for the minimal code that | |
39 * actually communicates with the underlying widget. | |
40 * | |
41 * @see org.eclipse.jface.viewers.ListViewer | |
42 * @see org.eclipse.jface.viewers.ComboViewer | |
43 * | |
44 * @since 3.0 | |
45 */ | |
46 public abstract class AbstractListViewer : StructuredViewer { | |
47 alias StructuredViewer.internalRefresh internalRefresh; | |
48 alias StructuredViewer.setSelectionToWidget setSelectionToWidget; | |
49 | |
50 /** | |
51 * A list of viewer elements (element type: <code>Object</code>). | |
52 */ | |
53 private List listMap; | |
54 | |
55 /** | |
56 * Adds the given string to the underlying widget at the given index | |
57 * | |
58 * @param string the string to add | |
59 * @param index position to insert the string into | |
60 */ | |
61 protected abstract void listAdd(String string, int index); | |
62 | |
63 /** | |
64 * Sets the text of the item at the given index in the underlying widget. | |
65 * | |
66 * @param index index to modify | |
67 * @param string new text | |
68 */ | |
69 protected abstract void listSetItem(int index, String string); | |
70 | |
71 /** | |
72 * Returns the zero-relative indices of the items which are currently | |
73 * selected in the underlying widget. The array is empty if no items are selected. | |
74 * <p> | |
75 * Note: This is not the actual structure used by the receiver | |
76 * to maintain its selection, so modifying the array will | |
77 * not affect the receiver. | |
78 * </p> | |
79 * @return the array of indices of the selected items | |
80 */ | |
81 protected abstract int[] listGetSelectionIndices(); | |
82 | |
83 /** | |
84 * Returns the number of items contained in the underlying widget. | |
85 * | |
86 * @return the number of items | |
87 */ | |
88 protected abstract int listGetItemCount(); | |
89 | |
90 /** | |
91 * Sets the underlying widget's items to be the given array of items. | |
92 * | |
93 * @param labels the array of label text | |
94 */ | |
95 protected abstract void listSetItems(String[] labels); | |
96 | |
97 /** | |
98 * Removes all of the items from the underlying widget. | |
99 */ | |
100 protected abstract void listRemoveAll(); | |
101 | |
102 /** | |
103 * Removes the item from the underlying widget at the given | |
104 * zero-relative index. | |
105 * | |
106 * @param index the index for the item | |
107 */ | |
108 protected abstract void listRemove(int index); | |
109 | |
110 /** | |
111 * Selects the items at the given zero-relative indices in the underlying widget. | |
112 * The current selection is cleared before the new items are selected. | |
113 * <p> | |
114 * Indices that are out of range and duplicate indices are ignored. | |
115 * If the receiver is single-select and multiple indices are specified, | |
116 * then all indices are ignored. | |
117 * | |
118 * @param ixs the indices of the items to select | |
119 */ | |
120 protected abstract void listSetSelection(int[] ixs); | |
121 | |
122 /** | |
123 * Shows the selection. If the selection is already showing in the receiver, | |
124 * this method simply returns. Otherwise, the items are scrolled until | |
125 * the selection is visible. | |
126 */ | |
127 protected abstract void listShowSelection(); | |
128 | |
129 /** | |
130 * Deselects all selected items in the underlying widget. | |
131 */ | |
132 protected abstract void listDeselectAll(); | |
133 | |
134 public this(){ | |
135 listMap = new ArrayList(); | |
136 } | |
137 | |
138 /** | |
139 * Adds the given elements to this list viewer. | |
140 * If this viewer does not have a sorter, the elements are added at the end | |
141 * in the order given; otherwise the elements are inserted at appropriate positions. | |
142 * <p> | |
143 * This method should be called (by the content provider) when elements | |
144 * have been added to the model, in order to cause the viewer to accurately | |
145 * reflect the model. This method only affects the viewer, not the model. | |
146 * </p> | |
147 * | |
148 * @param elements the elements to add | |
149 */ | |
150 public void add(Object[] elements) { | |
151 assertElementsNotNull(elements); | |
152 Object[] filtered = filter(elements); | |
153 ILabelProvider labelProvider = cast(ILabelProvider) getLabelProvider(); | |
154 for (int i = 0; i < filtered.length; i++) { | |
155 Object element = filtered[i]; | |
156 int ix = indexForElement(element); | |
157 insertItem(labelProvider, element, ix); | |
158 } | |
159 } | |
160 | |
161 private void insertItem(ILabelProvider labelProvider, Object element, int index) { | |
162 listAdd(getLabelProviderText(labelProvider, element), index); | |
163 listMap.add(index, element); | |
164 mapElement(element, getControl()); // must map it, since findItem only looks in map, if enabled | |
165 } | |
166 | |
167 /** | |
168 * Inserts the given element into this list viewer at the given position. | |
169 * If this viewer has a sorter, the position is ignored and the element is | |
170 * inserted at the correct position in the sort order. | |
171 * <p> | |
172 * This method should be called (by the content provider) when elements have | |
173 * been added to the model, in order to cause the viewer to accurately | |
174 * reflect the model. This method only affects the viewer, not the model. | |
175 * </p> | |
176 * | |
177 * @param element | |
178 * the element | |
179 * @param position | |
180 * a 0-based position relative to the model, or -1 to indicate | |
181 * the last position | |
182 * @since 3.3 | |
183 */ | |
184 public void insert(Object element, int position) { | |
185 if (getComparator() !is null || hasFilters()) { | |
186 add(element); | |
187 return; | |
188 } | |
189 | |
190 insertItem(cast(ILabelProvider) getLabelProvider(), element, position); | |
191 } | |
192 | |
193 | |
194 /** | |
195 * Return the text for the element from the labelProvider. | |
196 * If it is null then return the empty String. | |
197 * @param labelProvider ILabelProvider | |
198 * @param element | |
199 * @return String. Return the emptyString if the labelProvider | |
200 * returns null for the text. | |
201 * | |
202 * @since 3.1 | |
203 */ | |
204 private String getLabelProviderText(ILabelProvider labelProvider, Object element){ | |
205 String text = labelProvider.getText(element); | |
206 if(text is null) { | |
207 return "";//$NON-NLS-1$ | |
208 } | |
209 return text; | |
210 } | |
211 | |
212 /** | |
213 * Adds the given element to this list viewer. | |
214 * If this viewer does not have a sorter, the element is added at the end; | |
215 * otherwise the element is inserted at the appropriate position. | |
216 * <p> | |
217 * This method should be called (by the content provider) when a single element | |
218 * has been added to the model, in order to cause the viewer to accurately | |
219 * reflect the model. This method only affects the viewer, not the model. | |
220 * Note that there is another method for efficiently processing the simultaneous | |
221 * addition of multiple elements. | |
222 * </p> | |
223 * | |
224 * @param element the element | |
225 */ | |
226 public void add(Object element) { | |
227 add([ element ]); | |
228 } | |
229 | |
230 /* (non-Javadoc) | |
231 * Method declared on StructuredViewer. | |
232 * Since SWT.List doesn't use items we always return the List itself. | |
233 */ | |
234 protected override Widget doFindInputItem(Object element) { | |
235 if (element !is null && opEquals(element, getRoot())) { | |
236 return getControl(); | |
237 } | |
238 return null; | |
239 } | |
240 | |
241 /* (non-Javadoc) | |
242 * Method declared on StructuredViewer. | |
243 * Since SWT.List doesn't use items we always return the List itself. | |
244 */ | |
245 protected override Widget doFindItem(Object element) { | |
246 if (element !is null) { | |
247 if (listMapContains(element)) { | |
248 return getControl(); | |
249 } | |
250 } | |
251 return null; | |
252 } | |
253 | |
254 /* (non-Javadoc) | |
255 * Method declared on StructuredViewer. | |
256 */ | |
257 protected override void doUpdateItem(Widget data, Object element, bool fullMap) { | |
258 if (element !is null) { | |
259 int ix = getElementIndex(element); | |
260 if (ix >= 0) { | |
261 ILabelProvider labelProvider = cast(ILabelProvider) getLabelProvider(); | |
262 listSetItem(ix, getLabelProviderText(labelProvider,element)); | |
263 } | |
264 } | |
265 } | |
266 | |
267 /** | |
268 * Returns the element with the given index from this list viewer. | |
269 * Returns <code>null</code> if the index is out of range. | |
270 * | |
271 * @param index the zero-based index | |
272 * @return the element at the given index, or <code>null</code> if the | |
273 * index is out of range | |
274 */ | |
275 public Object getElementAt(int index) { | |
276 if (index >= 0 && index < listMap.size()) { | |
277 return listMap.get(index); | |
278 } | |
279 return null; | |
280 } | |
281 | |
282 /** | |
283 * The list viewer implementation of this <code>Viewer</code> framework | |
284 * method returns the label provider, which in the case of list | |
285 * viewers will be an instance of <code>ILabelProvider</code>. | |
286 */ | |
287 public override IBaseLabelProvider getLabelProvider() { | |
288 return super.getLabelProvider(); | |
289 } | |
290 | |
291 /* (non-Javadoc) | |
292 * Method declared on Viewer. | |
293 */ | |
294 /* (non-Javadoc) | |
295 * Method declared on StructuredViewer. | |
296 */ | |
297 protected override List getSelectionFromWidget() { | |
298 int[] ixs = listGetSelectionIndices(); | |
299 ArrayList list = new ArrayList(ixs.length); | |
300 for (int i = 0; i < ixs.length; i++) { | |
301 Object e = getElementAt(ixs[i]); | |
302 if (e !is null) { | |
303 list.add(e); | |
304 } | |
305 } | |
306 return list; | |
307 } | |
308 | |
309 /** | |
310 * @param element the element to insert | |
311 * @return the index where the item should be inserted. | |
312 */ | |
313 protected int indexForElement(Object element) { | |
314 ViewerComparator comparator = getComparator(); | |
315 if (comparator is null) { | |
316 return listGetItemCount(); | |
317 } | |
318 int count = listGetItemCount(); | |
319 int min = 0, max = count - 1; | |
320 while (min <= max) { | |
321 int mid = (min + max) / 2; | |
322 Object data = listMap.get(mid); | |
323 int compare = comparator.compare(this, data, element); | |
324 if (compare is 0) { | |
325 // find first item > element | |
326 while (compare is 0) { | |
327 ++mid; | |
328 if (mid >= count) { | |
329 break; | |
330 } | |
331 data = listMap.get(mid); | |
332 compare = comparator.compare(this, data, element); | |
333 } | |
334 return mid; | |
335 } | |
336 if (compare < 0) { | |
337 min = mid + 1; | |
338 } else { | |
339 max = mid - 1; | |
340 } | |
341 } | |
342 return min; | |
343 } | |
344 | |
345 /* (non-Javadoc) | |
346 * Method declared on Viewer. | |
347 */ | |
348 protected override void inputChanged(Object input, Object oldInput) { | |
349 listMap.clear(); | |
350 Object[] children = getSortedChildren(getRoot()); | |
351 int size = children.length; | |
352 | |
353 listRemoveAll(); | |
354 String[] labels = new String[size]; | |
355 for (int i = 0; i < size; i++) { | |
356 Object el = children[i]; | |
357 labels[i] = getLabelProviderText(cast(ILabelProvider) getLabelProvider(),el); | |
358 listMap.add(el); | |
359 mapElement(el, getControl()); // must map it, since findItem only looks in map, if enabled | |
360 } | |
361 listSetItems(labels); | |
362 } | |
363 | |
364 /* (non-Javadoc) | |
365 * Method declared on StructuredViewer. | |
366 */ | |
367 protected override void internalRefresh(Object element) { | |
368 Control list = getControl(); | |
369 if (element is null || opEquals(element, getRoot())) { | |
370 // the parent | |
371 if (listMap !is null) { | |
372 listMap.clear(); | |
373 } | |
374 unmapAllElements(); | |
375 List selection = getSelectionFromWidget(); | |
376 | |
377 int topIndex = -1; | |
378 if (selection is null || selection.isEmpty()) { | |
379 topIndex = listGetTopIndex(); | |
380 } | |
381 | |
382 Object[] children = null; | |
383 list.setRedraw(false); | |
384 try { | |
385 listRemoveAll(); | |
386 | |
387 children = getSortedChildren(getRoot()); | |
388 String[] items = new String[children.length]; | |
389 | |
390 ILabelProvider labelProvider = cast(ILabelProvider) getLabelProvider(); | |
391 | |
392 for (int i = 0; i < items.length; i++) { | |
393 Object el = children[i]; | |
394 items[i] = getLabelProviderText(labelProvider, el); | |
395 listMap.add(el); | |
396 mapElement(el, list); // must map it, since findItem only looks in map, if enabled | |
397 } | |
398 | |
399 listSetItems(items); | |
400 } finally { | |
401 list.setRedraw(true); | |
402 } | |
403 | |
404 if (topIndex is -1) { | |
405 setSelectionToWidget(selection, false); | |
406 } else { | |
407 listSetTopIndex(Math.min(topIndex, children.length)); | |
408 } | |
409 } else { | |
410 doUpdateItem(list, element, true); | |
411 } | |
412 } | |
413 | |
414 /** | |
415 * Returns the index of the item currently at the top of the viewable area. | |
416 * <p> | |
417 * Default implementation returns -1. | |
418 * </p> | |
419 * @return index, -1 for none | |
420 * @since 3.3 | |
421 */ | |
422 protected int listGetTopIndex(){ | |
423 return -1; | |
424 } | |
425 | |
426 /** | |
427 * Sets the index of the item to be at the top of the viewable area. | |
428 * <p> | |
429 * Default implementation does nothing. | |
430 * </p> | |
431 * @param index the given index. -1 for none. index will always refer to a valid index. | |
432 * @since 3.3 | |
433 */ | |
434 protected void listSetTopIndex(int index) { | |
435 } | |
436 | |
437 /** | |
438 * Removes the given elements from this list viewer. | |
439 * | |
440 * @param elements the elements to remove | |
441 */ | |
442 private void internalRemove(Object[] elements) { | |
443 Object input = getInput(); | |
444 for (int i = 0; i < elements.length; ++i) { | |
445 if ( opEquals(elements[i], input)) { | |
446 setInput(null); | |
447 return; | |
448 } | |
449 int ix = getElementIndex(elements[i]); | |
450 if (ix >= 0) { | |
451 listRemove(ix); | |
452 listMap.remove(ix); | |
453 unmapElement(elements[i], getControl()); | |
454 } | |
455 } | |
456 } | |
457 | |
458 /** | |
459 * Removes the given elements from this list viewer. | |
460 * The selection is updated if required. | |
461 * <p> | |
462 * This method should be called (by the content provider) when elements | |
463 * have been removed from the model, in order to cause the viewer to accurately | |
464 * reflect the model. This method only affects the viewer, not the model. | |
465 * </p> | |
466 * | |
467 * @param elements the elements to remove | |
468 */ | |
469 public void remove(Object[] elements) { | |
470 assertElementsNotNull(elements); | |
471 if (elements.length is 0) { | |
472 return; | |
473 } | |
474 preservingSelection( dgRunnable( (Object[] elements_){ | |
475 internalRemove(elements_); | |
476 }, elements)); | |
477 } | |
478 | |
479 /** | |
480 * Removes the given element from this list viewer. | |
481 * The selection is updated if necessary. | |
482 * <p> | |
483 * This method should be called (by the content provider) when a single element | |
484 * has been removed from the model, in order to cause the viewer to accurately | |
485 * reflect the model. This method only affects the viewer, not the model. | |
486 * Note that there is another method for efficiently processing the simultaneous | |
487 * removal of multiple elements. | |
488 * </p> | |
489 * | |
490 * @param element the element | |
491 */ | |
492 public void remove(Object element) { | |
493 remove([ element ]); | |
494 } | |
495 | |
496 /** | |
497 * The list viewer implementation of this <code>Viewer</code> framework | |
498 * method ensures that the given label provider is an instance of | |
499 * <code>ILabelProvider</code>. | |
500 * | |
501 * <b>The optional interfaces {@link IColorProvider} and | |
502 * {@link IFontProvider} have no effect for this type of viewer</b> | |
503 */ | |
504 public override void setLabelProvider(IBaseLabelProvider labelProvider) { | |
505 Assert.isTrue( null !is cast(ILabelProvider)labelProvider ); | |
506 super.setLabelProvider(labelProvider); | |
507 } | |
508 | |
509 /* (non-Javadoc) | |
510 * Method declared on StructuredViewer. | |
511 */ | |
512 protected override void setSelectionToWidget(List in_, bool reveal) { | |
513 if (in_ is null || in_.size() is 0) { // clear selection | |
514 listDeselectAll(); | |
515 } else { | |
516 int n = in_.size(); | |
517 int[] ixs = new int[n]; | |
518 int count = 0; | |
519 for (int i = 0; i < n; ++i) { | |
520 Object el = in_.get(i); | |
521 int ix = getElementIndex(el); | |
522 if (ix >= 0) { | |
523 ixs[count++] = ix; | |
524 } | |
525 } | |
526 if (count < n) { | |
527 System.arraycopy(ixs, 0, ixs = new int[count], 0, count); | |
528 } | |
529 listSetSelection(ixs); | |
530 if (reveal) { | |
531 listShowSelection(); | |
532 } | |
533 } | |
534 } | |
535 | |
536 /** | |
537 * Returns the index of the given element in listMap, or -1 if the element cannot be found. | |
538 * As of 3.3, uses the element comparer if available. | |
539 * | |
540 * @param element | |
541 * @return the index | |
542 */ | |
543 int getElementIndex(Object element) { | |
544 IElementComparer comparer = getComparer(); | |
545 if (comparer is null) { | |
546 return listMap.indexOf(element); | |
547 } | |
548 int size = listMap.size(); | |
549 for (int i = 0; i < size; i++) { | |
550 if (comparer.opEquals(element, listMap.get(i))) | |
551 return i; | |
552 } | |
553 return -1; | |
554 } | |
555 | |
556 /** | |
557 * @param element | |
558 * @return true if listMap contains the given element | |
559 * | |
560 * @since 3.3 | |
561 */ | |
562 private bool listMapContains(Object element) { | |
563 return getElementIndex(element) !is -1; | |
564 } | |
565 | |
566 } |