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 }