KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > viewers > AbstractListViewer


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  *******************************************************************************/

14
15 package org.eclipse.jface.viewers;
16
17 import java.util.ArrayList JavaDoc;
18 import java.util.List JavaDoc;
19
20 import org.eclipse.core.runtime.Assert;
21 import org.eclipse.swt.widgets.Control;
22 import org.eclipse.swt.widgets.Widget;
23
24 /**
25  * Abstract base class for viewers that contain lists of items (such as a combo or list).
26  * Most of the viewer implementation is in this base class, except for the minimal code that
27  * actually communicates with the underlying widget.
28  *
29  * @see org.eclipse.jface.viewers.ListViewer
30  * @see org.eclipse.jface.viewers.ComboViewer
31  *
32  * @since 3.0
33  */

34 public abstract class AbstractListViewer extends StructuredViewer {
35
36     /**
37      * A list of viewer elements (element type: <code>Object</code>).
38      */

39     private java.util.List JavaDoc listMap = new ArrayList JavaDoc();
40
41     /**
42      * Adds the given string to the underlying widget at the given index
43      *
44      * @param string the string to add
45      * @param index position to insert the string into
46      */

47     protected abstract void listAdd(String JavaDoc string, int index);
48
49     /**
50      * Sets the text of the item at the given index in the underlying widget.
51      *
52      * @param index index to modify
53      * @param string new text
54      */

55     protected abstract void listSetItem(int index, String JavaDoc string);
56
57     /**
58      * Returns the zero-relative indices of the items which are currently
59      * selected in the underlying widget. The array is empty if no items are selected.
60      * <p>
61      * Note: This is not the actual structure used by the receiver
62      * to maintain its selection, so modifying the array will
63      * not affect the receiver.
64      * </p>
65      * @return the array of indices of the selected items
66      */

67     protected abstract int[] listGetSelectionIndices();
68
69     /**
70      * Returns the number of items contained in the underlying widget.
71      *
72      * @return the number of items
73      */

74     protected abstract int listGetItemCount();
75
76     /**
77      * Sets the underlying widget's items to be the given array of items.
78      *
79      * @param labels the array of label text
80      */

81     protected abstract void listSetItems(String JavaDoc[] labels);
82
83     /**
84      * Removes all of the items from the underlying widget.
85      */

86     protected abstract void listRemoveAll();
87
88     /**
89      * Removes the item from the underlying widget at the given
90      * zero-relative index.
91      *
92      * @param index the index for the item
93      */

94     protected abstract void listRemove(int index);
95
96     /**
97      * Selects the items at the given zero-relative indices in the underlying widget.
98      * The current selection is cleared before the new items are selected.
99      * <p>
100      * Indices that are out of range and duplicate indices are ignored.
101      * If the receiver is single-select and multiple indices are specified,
102      * then all indices are ignored.
103      *
104      * @param ixs the indices of the items to select
105      */

106     protected abstract void listSetSelection(int[] ixs);
107
108     /**
109      * Shows the selection. If the selection is already showing in the receiver,
110      * this method simply returns. Otherwise, the items are scrolled until
111      * the selection is visible.
112      */

113     protected abstract void listShowSelection();
114
115     /**
116      * Deselects all selected items in the underlying widget.
117      */

118     protected abstract void listDeselectAll();
119
120     /**
121      * Adds the given elements to this list viewer.
122      * If this viewer does not have a sorter, the elements are added at the end
123      * in the order given; otherwise the elements are inserted at appropriate positions.
124      * <p>
125      * This method should be called (by the content provider) when elements
126      * have been added to the model, in order to cause the viewer to accurately
127      * reflect the model. This method only affects the viewer, not the model.
128      * </p>
129      *
130      * @param elements the elements to add
131      */

132     public void add(Object JavaDoc[] elements) {
133         assertElementsNotNull(elements);
134         Object JavaDoc[] filtered = filter(elements);
135         ILabelProvider labelProvider = (ILabelProvider) getLabelProvider();
136         for (int i = 0; i < filtered.length; i++) {
137             Object JavaDoc element = filtered[i];
138             int ix = indexForElement(element);
139             insertItem(labelProvider, element, ix);
140         }
141     }
142     
143     private void insertItem(ILabelProvider labelProvider, Object JavaDoc element, int index) {
144         listAdd(getLabelProviderText(labelProvider, element), index);
145         listMap.add(index, element);
146         mapElement(element, getControl()); // must map it, since findItem only looks in map, if enabled
147
}
148     
149     /**
150      * Inserts the given element into this list viewer at the given position.
151      * If this viewer has a sorter, the position is ignored and the element is
152      * inserted at the correct position in the sort order.
153      * <p>
154      * This method should be called (by the content provider) when elements have
155      * been added to the model, in order to cause the viewer to accurately
156      * reflect the model. This method only affects the viewer, not the model.
157      * </p>
158      *
159      * @param element
160      * the element
161      * @param position
162      * a 0-based position relative to the model, or -1 to indicate
163      * the last position
164      * @since 3.3
165      */

166     public void insert(Object JavaDoc element, int position) {
167         if (getComparator() != null || hasFilters()) {
168             add(element);
169             return;
170         }
171         
172         insertItem((ILabelProvider) getLabelProvider(), element, position);
173     }
174     
175     
176     /**
177      * Return the text for the element from the labelProvider.
178      * If it is null then return the empty String.
179      * @param labelProvider ILabelProvider
180      * @param element
181      * @return String. Return the emptyString if the labelProvider
182      * returns null for the text.
183      *
184      * @since 3.1
185      */

186     private String JavaDoc getLabelProviderText(ILabelProvider labelProvider, Object JavaDoc element){
187         String JavaDoc text = labelProvider.getText(element);
188         if(text == null) {
189             return "";//$NON-NLS-1$
190
}
191         return text;
192     }
193
194     /**
195      * Adds the given element to this list viewer.
196      * If this viewer does not have a sorter, the element is added at the end;
197      * otherwise the element is inserted at the appropriate position.
198      * <p>
199      * This method should be called (by the content provider) when a single element
200      * has been added to the model, in order to cause the viewer to accurately
201      * reflect the model. This method only affects the viewer, not the model.
202      * Note that there is another method for efficiently processing the simultaneous
203      * addition of multiple elements.
204      * </p>
205      *
206      * @param element the element
207      */

208     public void add(Object JavaDoc element) {
209         add(new Object JavaDoc[] { element });
210     }
211
212     /* (non-Javadoc)
213      * Method declared on StructuredViewer.
214      * Since SWT.List doesn't use items we always return the List itself.
215      */

216     protected Widget doFindInputItem(Object JavaDoc element) {
217         if (element != null && equals(element, getRoot())) {
218             return getControl();
219         }
220         return null;
221     }
222
223     /* (non-Javadoc)
224      * Method declared on StructuredViewer.
225      * Since SWT.List doesn't use items we always return the List itself.
226      */

227     protected Widget doFindItem(Object JavaDoc element) {
228         if (element != null) {
229             if (listMapContains(element)) {
230                 return getControl();
231             }
232         }
233         return null;
234     }
235
236     /* (non-Javadoc)
237      * Method declared on StructuredViewer.
238      */

239     protected void doUpdateItem(Widget data, Object JavaDoc element, boolean fullMap) {
240         if (element != null) {
241             int ix = getElementIndex(element);
242             if (ix >= 0) {
243                 ILabelProvider labelProvider = (ILabelProvider) getLabelProvider();
244                 listSetItem(ix, getLabelProviderText(labelProvider,element));
245             }
246         }
247     }
248
249     /* (non-Javadoc)
250      * Method declared on Viewer.
251      */

252     public abstract Control getControl();
253
254     /**
255      * Returns the element with the given index from this list viewer.
256      * Returns <code>null</code> if the index is out of range.
257      *
258      * @param index the zero-based index
259      * @return the element at the given index, or <code>null</code> if the
260      * index is out of range
261      */

262     public Object JavaDoc getElementAt(int index) {
263         if (index >= 0 && index < listMap.size()) {
264             return listMap.get(index);
265         }
266         return null;
267     }
268
269     /**
270      * The list viewer implementation of this <code>Viewer</code> framework
271      * method returns the label provider, which in the case of list
272      * viewers will be an instance of <code>ILabelProvider</code>.
273      */

274     public IBaseLabelProvider getLabelProvider() {
275         return super.getLabelProvider();
276     }
277
278     /* (non-Javadoc)
279      * Method declared on Viewer.
280      */

281     /* (non-Javadoc)
282      * Method declared on StructuredViewer.
283      */

284     protected List JavaDoc getSelectionFromWidget() {
285         int[] ixs = listGetSelectionIndices();
286         ArrayList JavaDoc list = new ArrayList JavaDoc(ixs.length);
287         for (int i = 0; i < ixs.length; i++) {
288             Object JavaDoc e = getElementAt(ixs[i]);
289             if (e != null) {
290                 list.add(e);
291             }
292         }
293         return list;
294     }
295
296     /**
297      * @param element the element to insert
298      * @return the index where the item should be inserted.
299      */

300     protected int indexForElement(Object JavaDoc element) {
301         ViewerComparator comparator = getComparator();
302         if (comparator == null) {
303             return listGetItemCount();
304         }
305         int count = listGetItemCount();
306         int min = 0, max = count - 1;
307         while (min <= max) {
308             int mid = (min + max) / 2;
309             Object JavaDoc data = listMap.get(mid);
310             int compare = comparator.compare(this, data, element);
311             if (compare == 0) {
312                 // find first item > element
313
while (compare == 0) {
314                     ++mid;
315                     if (mid >= count) {
316                         break;
317                     }
318                     data = listMap.get(mid);
319                     compare = comparator.compare(this, data, element);
320                 }
321                 return mid;
322             }
323             if (compare < 0) {
324                 min = mid + 1;
325             } else {
326                 max = mid - 1;
327             }
328         }
329         return min;
330     }
331
332     /* (non-Javadoc)
333      * Method declared on Viewer.
334      */

335     protected void inputChanged(Object JavaDoc input, Object JavaDoc oldInput) {
336         listMap.clear();
337         Object JavaDoc[] children = getSortedChildren(getRoot());
338         int size = children.length;
339
340         listRemoveAll();
341         String JavaDoc[] labels = new String JavaDoc[size];
342         for (int i = 0; i < size; i++) {
343             Object JavaDoc el = children[i];
344             labels[i] = getLabelProviderText((ILabelProvider) getLabelProvider(),el);
345             listMap.add(el);
346             mapElement(el, getControl()); // must map it, since findItem only looks in map, if enabled
347
}
348         listSetItems(labels);
349     }
350
351     /* (non-Javadoc)
352      * Method declared on StructuredViewer.
353      */

354     protected void internalRefresh(Object JavaDoc element) {
355         Control list = getControl();
356         if (element == null || equals(element, getRoot())) {
357             // the parent
358
if (listMap != null) {
359                 listMap.clear();
360             }
361             unmapAllElements();
362             List JavaDoc selection = getSelectionFromWidget();
363             
364             int topIndex = -1;
365             if (selection == null || selection.isEmpty()) {
366                 topIndex = listGetTopIndex();
367             }
368             
369             list.setRedraw(false);
370             listRemoveAll();
371             
372             Object JavaDoc[] children = getSortedChildren(getRoot());
373             String JavaDoc[] items = new String JavaDoc[children.length];
374             
375             ILabelProvider labelProvider = (ILabelProvider) getLabelProvider();
376             
377             for (int i = 0; i < items.length; i++) {
378                 Object JavaDoc el = children[i];
379                 items[i] = getLabelProviderText(labelProvider, el);
380                 listMap.add(el);
381                 mapElement(el, list); // must map it, since findItem only looks in map, if enabled
382
}
383             
384             listSetItems(items);
385             list.setRedraw(true);
386             
387             if (topIndex == -1) {
388                 setSelectionToWidget(selection, false);
389             } else {
390                 listSetTopIndex(Math.min(topIndex, children.length));
391             }
392         } else {
393             doUpdateItem(list, element, true);
394         }
395     }
396     
397     /**
398      * Returns the index of the item currently at the top of the viewable area.
399      * <p>
400      * Default implementation returns -1.
401      * </p>
402      * @return index, -1 for none
403      * @since 3.3
404      */

405     protected int listGetTopIndex(){
406         return -1;
407     }
408
409     /**
410      * Sets the index of the item to be at the top of the viewable area.
411      * <p>
412      * Default implementation does nothing.
413      * </p>
414      * @param index the given index. -1 for none. index will always refer to a valid index.
415      * @since 3.3
416      */

417     protected void listSetTopIndex(int index) {
418     }
419     
420     /**
421      * Removes the given elements from this list viewer.
422      *
423      * @param elements the elements to remove
424      */

425     private void internalRemove(final Object JavaDoc[] elements) {
426         Object JavaDoc input = getInput();
427         for (int i = 0; i < elements.length; ++i) {
428             if (equals(elements[i], input)) {
429                 setInput(null);
430                 return;
431             }
432             int ix = getElementIndex(elements[i]);
433             if (ix >= 0) {
434                 listRemove(ix);
435                 listMap.remove(ix);
436                 unmapElement(elements[i], getControl());
437             }
438         }
439     }
440
441     /**
442      * Removes the given elements from this list viewer.
443      * The selection is updated if required.
444      * <p>
445      * This method should be called (by the content provider) when elements
446      * have been removed from the model, in order to cause the viewer to accurately
447      * reflect the model. This method only affects the viewer, not the model.
448      * </p>
449      *
450      * @param elements the elements to remove
451      */

452     public void remove(final Object JavaDoc[] elements) {
453         assertElementsNotNull(elements);
454         if (elements.length == 0) {
455             return;
456         }
457         preservingSelection(new Runnable JavaDoc() {
458             public void run() {
459                 internalRemove(elements);
460             }
461         });
462     }
463
464     /**
465      * Removes the given element from this list viewer.
466      * The selection is updated if necessary.
467      * <p>
468      * This method should be called (by the content provider) when a single element
469      * has been removed from the model, in order to cause the viewer to accurately
470      * reflect the model. This method only affects the viewer, not the model.
471      * Note that there is another method for efficiently processing the simultaneous
472      * removal of multiple elements.
473      * </p>
474      *
475      * @param element the element
476      */

477     public void remove(Object JavaDoc element) {
478         remove(new Object JavaDoc[] { element });
479     }
480
481     /**
482      * The list viewer implementation of this <code>Viewer</code> framework
483      * method ensures that the given label provider is an instance of
484      * <code>ILabelProvider</code>.
485      *
486      * <b>The optional interfaces {@link IColorProvider} and
487      * {@link IFontProvider} have no effect for this type of viewer</b>
488      */

489     public void setLabelProvider(IBaseLabelProvider labelProvider) {
490         Assert.isTrue(labelProvider instanceof ILabelProvider);
491         super.setLabelProvider(labelProvider);
492     }
493
494     /* (non-Javadoc)
495      * Method declared on StructuredViewer.
496      */

497     protected void setSelectionToWidget(List JavaDoc in, boolean reveal) {
498         if (in == null || in.size() == 0) { // clear selection
499
listDeselectAll();
500         } else {
501             int n = in.size();
502             int[] ixs = new int[n];
503             int count = 0;
504             for (int i = 0; i < n; ++i) {
505                 Object JavaDoc el = in.get(i);
506                 int ix = getElementIndex(el);
507                 if (ix >= 0) {
508                     ixs[count++] = ix;
509                 }
510             }
511             if (count < n) {
512                 System.arraycopy(ixs, 0, ixs = new int[count], 0, count);
513             }
514             listSetSelection(ixs);
515             if (reveal) {
516                 listShowSelection();
517             }
518         }
519     }
520
521     /**
522      * Returns the index of the given element in listMap, or -1 if the element cannot be found.
523      * As of 3.3, uses the element comparer if available.
524      *
525      * @param element
526      * @return the index
527      */

528     int getElementIndex(Object JavaDoc element) {
529         IElementComparer comparer = getComparer();
530         if (comparer == null) {
531             return listMap.indexOf(element);
532         }
533         int size = listMap.size();
534         for (int i = 0; i < size; i++) {
535             if (comparer.equals(element, listMap.get(i)))
536                 return i;
537         }
538         return -1;
539     }
540
541     /**
542      * @param element
543      * @return true if listMap contains the given element
544      *
545      * @since 3.3
546      */

547     private boolean listMapContains(Object JavaDoc element) {
548         return getElementIndex(element) != -1;
549     }
550
551 }
552
Popular Tags