KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 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  * Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation bug 154329
11  * - fixes in bug 170381, 198665
12  *******************************************************************************/

13
14 package org.eclipse.jface.viewers;
15
16 import java.util.ArrayList JavaDoc;
17 import java.util.Arrays JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.List JavaDoc;
21
22 import org.eclipse.core.runtime.Assert;
23 import org.eclipse.swt.SWT;
24 import org.eclipse.swt.widgets.Control;
25 import org.eclipse.swt.widgets.Event;
26 import org.eclipse.swt.widgets.Item;
27 import org.eclipse.swt.widgets.Listener;
28 import org.eclipse.swt.widgets.Widget;
29
30 /**
31  * This is a widget independent class implementors of
32  * {@link org.eclipse.swt.widgets.Table} like widgets can use to provide a
33  * viewer on top of their widget implementations.
34  *
35  * @since 3.3
36  */

37 public abstract class AbstractTableViewer extends ColumnViewer {
38
39     private class VirtualManager {
40
41         /**
42          * The currently invisible elements as provided by the content provider
43          * or by addition. This will not be populated by an
44          * ILazyStructuredContentProvider as an ILazyStructuredContentProvider
45          * is only queried on the virtual callback.
46          */

47         private Object JavaDoc[] cachedElements = new Object JavaDoc[0];
48
49         /**
50          * Create a new instance of the receiver.
51          *
52          */

53         public VirtualManager() {
54             addTableListener();
55         }
56
57         /**
58          * Add the listener for SetData on the table
59          */

60         private void addTableListener() {
61             getControl().addListener(SWT.SetData, new Listener() {
62                 /*
63                  * (non-Javadoc)
64                  *
65                  * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
66                  */

67                 public void handleEvent(Event event) {
68                     Item item = (Item) event.item;
69                     final int index = doIndexOf(item);
70                     Object JavaDoc element = resolveElement(index);
71                     if (element == null) {
72                         // Didn't find it so make a request
73
// Keep looking if it is not in the cache.
74
IContentProvider contentProvider = getContentProvider();
75                         // If we are building lazily then request lookup now
76
if (contentProvider instanceof ILazyContentProvider) {
77                             ((ILazyContentProvider) contentProvider)
78                                     .updateElement(index);
79                             return;
80                         }
81                     }
82
83                     associate(element, item);
84                     updateItem(item, element);
85                 }
86
87             });
88         }
89
90         /**
91          * Get the element at index.Resolve it lazily if this is available.
92          *
93          * @param index
94          * @return Object or <code>null</code> if it could not be found
95          */

96         protected Object JavaDoc resolveElement(int index) {
97
98             Object JavaDoc element = null;
99             if (index < cachedElements.length) {
100                 element = cachedElements[index];
101             }
102
103             return element;
104         }
105
106         /**
107          * A non visible item has been added.
108          *
109          * @param element
110          * @param index
111          */

112         public void notVisibleAdded(Object JavaDoc element, int index) {
113
114             int requiredCount = doGetItemCount() + 1;
115
116             Object JavaDoc[] newCache = new Object JavaDoc[requiredCount];
117             System.arraycopy(cachedElements, 0, newCache, 0, index);
118             if (index < cachedElements.length) {
119                 System.arraycopy(cachedElements, index, newCache, index + 1,
120                         cachedElements.length - index);
121             }
122             newCache[index] = element;
123             cachedElements = newCache;
124
125             doSetItemCount(requiredCount);
126         }
127
128         /**
129          * The elements with the given indices need to be removed from the
130          * cache.
131          *
132          * @param indices
133          */

134         public void removeIndices(int[] indices) {
135             if (indices.length == 1) {
136                 removeIndicesFromTo(indices[0], indices[0]);
137             }
138             int requiredCount = doGetItemCount() - indices.length;
139
140             Arrays.sort(indices);
141             Object JavaDoc[] newCache = new Object JavaDoc[requiredCount];
142             int indexInNewCache = 0;
143             int nextToSkip = 0;
144             for (int i = 0; i < cachedElements.length; i++) {
145                 if (nextToSkip < indices.length && i == indices[nextToSkip]) {
146                     nextToSkip++;
147                 } else {
148                     newCache[indexInNewCache++] = cachedElements[i];
149                 }
150             }
151             cachedElements = newCache;
152         }
153
154         /**
155          * The elements between the given indices (inclusive) need to be removed
156          * from the cache.
157          *
158          * @param from
159          * @param to
160          */

161         public void removeIndicesFromTo(int from, int to) {
162             int indexAfterTo = to + 1;
163             Object JavaDoc[] newCache = new Object JavaDoc[cachedElements.length
164                     - (indexAfterTo - from)];
165             System.arraycopy(cachedElements, 0, newCache, 0, from);
166             if (indexAfterTo < cachedElements.length) {
167                 System.arraycopy(cachedElements, indexAfterTo, newCache, from,
168                         cachedElements.length - indexAfterTo);
169             }
170         }
171
172         /**
173          * @param element
174          * @return the index of the element in the cache, or null
175          */

176         public int find(Object JavaDoc element) {
177             return Arrays.asList(cachedElements).indexOf(element);
178         }
179
180         /**
181          * @param count
182          */

183         public void adjustCacheSize(int count) {
184             if (count == cachedElements.length) {
185                 return;
186             } else if (count < cachedElements.length) {
187                 Object JavaDoc[] newCache = new Object JavaDoc[count];
188                 System.arraycopy(cachedElements, 0, newCache, 0, count);
189                 cachedElements = newCache;
190             } else {
191                 Object JavaDoc[] newCache = new Object JavaDoc[count];
192                 System.arraycopy(cachedElements, 0, newCache, 0,
193                         cachedElements.length);
194                 cachedElements = newCache;
195             }
196         }
197
198     }
199
200     private VirtualManager virtualManager;
201
202     /**
203      * Create the new viewer for table like widgets
204      */

205     public AbstractTableViewer() {
206         super();
207     }
208
209     protected void hookControl(Control control) {
210         super.hookControl(control);
211         initializeVirtualManager(getControl().getStyle());
212     }
213
214     /**
215      * Initialize the virtual manager to manage the virtual state if the table
216      * is VIRTUAL. If not use the default no-op version.
217      *
218      * @param style
219      */

220     private void initializeVirtualManager(int style) {
221         if ((style & SWT.VIRTUAL) == 0) {
222             return;
223         }
224
225         virtualManager = new VirtualManager();
226     }
227
228     /**
229      * Adds the given elements to this table viewer. If this viewer does not
230      * have a sorter, the elements are added at the end in the order given;
231      * otherwise the elements are inserted at appropriate positions.
232      * <p>
233      * This method should be called (by the content provider) when elements have
234      * been added to the model, in order to cause the viewer to accurately
235      * reflect the model. This method only affects the viewer, not the model.
236      * </p>
237      *
238      * @param elements
239      * the elements to add
240      */

241     public void add(Object JavaDoc[] elements) {
242         assertElementsNotNull(elements);
243         if (isBusy())
244             return;
245         Object JavaDoc[] filtered = filter(elements);
246         
247         for (int i = 0; i < filtered.length; i++) {
248             Object JavaDoc element = filtered[i];
249             int index = indexForElement(element);
250             createItem(element, index);
251         }
252     }
253
254     /**
255      * Create a new TableItem at index if required.
256      *
257      * @param element
258      * @param index
259      *
260      * @since 3.1
261      */

262     private void createItem(Object JavaDoc element, int index) {
263         if (virtualManager == null) {
264             updateItem(internalCreateNewRowPart(SWT.NONE, index).getItem(),
265                     element);
266         } else {
267             virtualManager.notVisibleAdded(element, index);
268
269         }
270     }
271
272     /**
273      * Create a new row. Callers can only use the returned object locally and before
274      * making the next call on the viewer since it may be re-used for subsequent method
275      * calls.
276      *
277      * @param style
278      * the style for the new row
279      * @param rowIndex
280      * the index of the row or -1 if the row is appended at the end
281      * @return the newly created row
282      */

283     protected abstract ViewerRow internalCreateNewRowPart(int style,
284             int rowIndex);
285
286     /**
287      * Adds the given element to this table viewer. If this viewer does not have
288      * a sorter, the element is added at the end; otherwise the element is
289      * inserted at the appropriate position.
290      * <p>
291      * This method should be called (by the content provider) when a single
292      * element has been added to the model, in order to cause the viewer to
293      * accurately reflect the model. This method only affects the viewer, not
294      * the model. Note that there is another method for efficiently processing
295      * the simultaneous addition of multiple elements.
296      * </p>
297      *
298      * @param element
299      * the element to add
300      */

301     public void add(Object JavaDoc element) {
302         add(new Object JavaDoc[] { element });
303     }
304
305     /*
306      * (non-Javadoc)
307      *
308      * @see org.eclipse.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object)
309      */

310     protected Widget doFindInputItem(Object JavaDoc element) {
311         if (equals(element, getRoot())) {
312             return getControl();
313         }
314         return null;
315     }
316
317     /*
318      * (non-Javadoc)
319      *
320      * @see org.eclipse.jface.viewers.StructuredViewer#doFindItem(java.lang.Object)
321      */

322     protected Widget doFindItem(Object JavaDoc element) {
323
324         Item[] children = doGetItems();
325         for (int i = 0; i < children.length; i++) {
326             Item item = children[i];
327             Object JavaDoc data = item.getData();
328             if (data != null && equals(data, element)) {
329                 return item;
330             }
331         }
332
333         return null;
334     }
335
336     /*
337      * (non-Javadoc)
338      *
339      * @see org.eclipse.jface.viewers.StructuredViewer#doUpdateItem(org.eclipse.swt.widgets.Widget,
340      * java.lang.Object, boolean)
341      */

342     protected void doUpdateItem(Widget widget, Object JavaDoc element, boolean fullMap) {
343         boolean oldBusy = busy;
344         busy = true;
345         try {
346             if (widget instanceof Item) {
347                 final Item item = (Item) widget;
348     
349                 // remember element we are showing
350
if (fullMap) {
351                     associate(element, item);
352                 } else {
353                     Object JavaDoc data = item.getData();
354                     if (data != null) {
355                         unmapElement(data, item);
356                     }
357                     item.setData(element);
358                     mapElement(element, item);
359                 }
360     
361                 int columnCount = doGetColumnCount();
362                 if (columnCount == 0)
363                     columnCount = 1;// If there are no columns do the first one
364

365                 ViewerRow viewerRowFromItem = getViewerRowFromItem(item);
366
367                 boolean isVirtual = (getControl().getStyle() & SWT.VIRTUAL) != 0;
368
369                 // If the control is virtual, we cannot use the cached viewer row object. See bug 188663.
370
if (isVirtual) {
371                     viewerRowFromItem = (ViewerRow) viewerRowFromItem.clone();
372                 }
373                 
374                 // Also enter loop if no columns added. See 1G9WWGZ: JFUIF:WINNT -
375
// TableViewer with 0 columns does not work
376
for (int column = 0; column < columnCount || column == 0; column++) {
377                     ViewerColumn columnViewer = getViewerColumn(column);
378                     ViewerCell cellToUpdate = updateCell(viewerRowFromItem,
379                             column, element);
380                     
381                     // If the control is virtual, we cannot use the cached cell object. See bug 188663.
382
if (isVirtual) {
383                         cellToUpdate = new ViewerCell(cellToUpdate.getViewerRow(), cellToUpdate.getColumnIndex(), element);
384                     }
385
386                     columnViewer.refresh(cellToUpdate);
387     
388                     // clear cell (see bug 201280)
389
updateCell(null, 0, null);
390
391                     // As it is possible for user code to run the event
392
// loop check here.
393
if (item.isDisposed()) {
394                         unmapElement(element, item);
395                         return;
396                     }
397     
398                 }
399     
400             }
401         } finally {
402             busy = oldBusy;
403         }
404     }
405
406     /*
407      * (non-Javadoc)
408      *
409      * @see org.eclipse.jface.viewers.ColumnViewer#getColumnViewerOwner(int)
410      */

411     protected Widget getColumnViewerOwner(int columnIndex) {
412         int columnCount = doGetColumnCount();
413
414         if (columnIndex < 0
415                 || (columnIndex > 0 && columnIndex >= columnCount)) {
416             return null;
417         }
418
419         if (columnCount == 0)// Hang it off the table if it
420
return getControl();
421         
422         return doGetColumn(columnIndex);
423     }
424
425     /**
426      * Returns the element with the given index from this table viewer. Returns
427      * <code>null</code> if the index is out of range.
428      * <p>
429      * This method is internal to the framework.
430      * </p>
431      *
432      * @param index
433      * the zero-based index
434      * @return the element at the given index, or <code>null</code> if the
435      * index is out of range
436      */

437     public Object JavaDoc getElementAt(int index) {
438         if (index >= 0 && index < doGetItemCount()) {
439             Item i = doGetItem(index);
440             if (i != null) {
441                 return i.getData();
442             }
443         }
444         return null;
445     }
446
447     /**
448      * The table viewer implementation of this <code>Viewer</code> framework
449      * method returns the label provider, which in the case of table viewers
450      * will be an instance of either <code>ITableLabelProvider</code> or
451      * <code>ILabelProvider</code>. If it is an
452      * <code>ITableLabelProvider</code>, then it provides a separate label
453      * text and image for each column. If it is an <code>ILabelProvider</code>,
454      * then it provides only the label text and image for the first column, and
455      * any remaining columns are blank.
456      */

457     public IBaseLabelProvider getLabelProvider() {
458         return super.getLabelProvider();
459     }
460
461     /*
462      * (non-Javadoc)
463      *
464      * @see org.eclipse.jface.viewers.StructuredViewer#getSelectionFromWidget()
465      */

466     protected List JavaDoc getSelectionFromWidget() {
467         if (virtualManager != null) {
468             return getVirtualSelection();
469         }
470         Widget[] items = doGetSelection();
471         ArrayList JavaDoc list = new ArrayList JavaDoc(items.length);
472         for (int i = 0; i < items.length; i++) {
473             Widget item = items[i];
474             Object JavaDoc e = item.getData();
475             if (e != null) {
476                 list.add(e);
477             }
478         }
479         return list;
480     }
481
482     /**
483      * Get the virtual selection. Avoid calling SWT whenever possible to prevent
484      * extra widget creation.
485      *
486      * @return List of Object
487      */

488
489     private List JavaDoc getVirtualSelection() {
490
491         List JavaDoc result = new ArrayList JavaDoc();
492         int[] selectionIndices = doGetSelectionIndices();
493         if (getContentProvider() instanceof ILazyContentProvider) {
494             ILazyContentProvider lazy = (ILazyContentProvider) getContentProvider();
495             for (int i = 0; i < selectionIndices.length; i++) {
496                 int selectionIndex = selectionIndices[i];
497                 lazy.updateElement(selectionIndex);// Start the update
498
Object JavaDoc element = doGetItem(selectionIndex).getData();
499                 // Only add the element if it got updated.
500
// If this is done deferred the selection will
501
// be incomplete until selection is finished.
502
if (element != null) {
503                     result.add(element);
504                 }
505             }
506         } else {
507             for (int i = 0; i < selectionIndices.length; i++) {
508                 Object JavaDoc element = null;
509                 // See if it is cached
510
int selectionIndex = selectionIndices[i];
511                 if (selectionIndex < virtualManager.cachedElements.length) {
512                     element = virtualManager.cachedElements[selectionIndex];
513                 }
514                 if (element == null) {
515                     // Not cached so try the item's data
516
Item item = doGetItem(selectionIndex);
517                     element = item.getData();
518                 }
519                 if (element != null) {
520                     result.add(element);
521                 }
522             }
523
524         }
525         return result;
526     }
527
528     /**
529      * @param element
530      * the element to insert
531      * @return the index where the item should be inserted.
532      */

533     protected int indexForElement(Object JavaDoc element) {
534         ViewerComparator comparator = getComparator();
535         if (comparator == null) {
536             return doGetItemCount();
537         }
538         int count = doGetItemCount();
539         int min = 0, max = count - 1;
540         while (min <= max) {
541             int mid = (min + max) / 2;
542             Object JavaDoc data = doGetItem(mid).getData();
543             int compare = comparator.compare(this, data, element);
544             if (compare == 0) {
545                 // find first item > element
546
while (compare == 0) {
547                     ++mid;
548                     if (mid >= count) {
549                         break;
550                     }
551                     data = doGetItem(mid).getData();
552                     compare = comparator.compare(this, data, element);
553                 }
554                 return mid;
555             }
556             if (compare < 0) {
557                 min = mid + 1;
558             } else {
559                 max = mid - 1;
560             }
561         }
562         return min;
563     }
564
565     /*
566      * (non-Javadoc)
567      *
568      * @see org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object,
569      * java.lang.Object)
570      */

571     protected void inputChanged(Object JavaDoc input, Object JavaDoc oldInput) {
572         getControl().setRedraw(false);
573         try {
574             preservingSelection(new Runnable JavaDoc() {
575                 public void run() {
576                     internalRefresh(getRoot());
577                 }
578             });
579         } finally {
580             getControl().setRedraw(true);
581         }
582     }
583
584     /**
585      * Inserts the given element into this table viewer at the given position.
586      * If this viewer has a sorter, the position is ignored and the element is
587      * inserted at the correct position in the sort order.
588      * <p>
589      * This method should be called (by the content provider) when elements have
590      * been added to the model, in order to cause the viewer to accurately
591      * reflect the model. This method only affects the viewer, not the model.
592      * </p>
593      *
594      * @param element
595      * the element
596      * @param position
597      * a 0-based position relative to the model, or -1 to indicate
598      * the last position
599      */

600     public void insert(Object JavaDoc element, int position) {
601         applyEditorValue();
602         if (getComparator() != null || hasFilters()) {
603             add(element);
604             return;
605         }
606         if (position == -1) {
607             position = doGetItemCount();
608         }
609         if (isBusy())
610             return;
611         createItem(element, position);
612     }
613
614     /*
615      * (non-Javadoc)
616      *
617      * @see org.eclipse.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object)
618      */

619     protected void internalRefresh(Object JavaDoc element) {
620         internalRefresh(element, true);
621     }
622
623     /*
624      * (non-Javadoc)
625      *
626      * @see org.eclipse.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object,
627      * boolean)
628      */

629     protected void internalRefresh(Object JavaDoc element, boolean updateLabels) {
630         applyEditorValue();
631         if (element == null || equals(element, getRoot())) {
632             if (virtualManager == null) {
633                 internalRefreshAll(updateLabels);
634             } else {
635                 internalVirtualRefreshAll();
636             }
637         } else {
638             Widget w = findItem(element);
639             if (w != null) {
640                 updateItem(w, element);
641             }
642         }
643     }
644
645     /**
646      * Refresh all with virtual elements.
647      *
648      * @since 3.1
649      */

650     private void internalVirtualRefreshAll() {
651
652         Object JavaDoc root = getRoot();
653         IContentProvider contentProvider = getContentProvider();
654
655         // Invalidate for lazy
656
if (!(contentProvider instanceof ILazyContentProvider)
657                 && (contentProvider instanceof IStructuredContentProvider)) {
658             // Don't cache if the root is null but cache if it is not lazy.
659
if (root != null) {
660                 virtualManager.cachedElements = getSortedChildren(root);
661                 doSetItemCount(virtualManager.cachedElements.length);
662             }
663         }
664         doClearAll();
665     }
666
667     /**
668      * Refresh all of the elements of the table. update the labels if
669      * updatLabels is true;
670      *
671      * @param updateLabels
672      *
673      * @since 3.1
674      */

675     private void internalRefreshAll(boolean updateLabels) {
676         // the parent
677

678         // in the code below, it is important to do all disassociates
679
// before any associates, since a later disassociate can undo an
680
// earlier associate
681
// e.g. if (a, b) is replaced by (b, a), the disassociate of b to
682
// item 1 could undo
683
// the associate of b to item 0.
684

685         Object JavaDoc[] children = getSortedChildren(getRoot());
686         Item[] items = doGetItems();
687         int min = Math.min(children.length, items.length);
688         for (int i = 0; i < min; ++i) {
689
690             Item item = items[i];
691
692             // if the element is unchanged, update its label if appropriate
693
if (equals(children[i], item.getData())) {
694                 if (updateLabels) {
695                     updateItem(item, children[i]);
696                 } else {
697                     // associate the new element, even if equal to the old
698
// one,
699
// to remove stale references (see bug 31314)
700
associate(children[i], item);
701                 }
702             } else {
703                 // updateItem does an associate(...), which can mess up
704
// the associations if the order of elements has changed.
705
// E.g. (a, b) -> (b, a) first replaces a->0 with b->0, then
706
// replaces b->1 with a->1, but this actually removes b->0.
707
// So, if the object associated with this item has changed,
708
// just disassociate it for now, and update it below.
709
// we also need to reset the item (set its text,images etc. to
710
// default values) because the label decorators rely on this
711
disassociate(item);
712                 doClear(i);
713             }
714         }
715         // dispose of all items beyond the end of the current elements
716
if (min < items.length) {
717             for (int i = items.length; --i >= min;) {
718
719                 disassociate(items[i]);
720             }
721             if (virtualManager != null) {
722                 virtualManager.removeIndicesFromTo(min, items.length - 1);
723             }
724             doRemove(min, items.length - 1);
725         }
726         // Workaround for 1GDGN4Q: ITPUI:WIN2000 - TableViewer icons get
727
// scrunched
728
if (doGetItemCount() == 0) {
729             doRemoveAll();
730         }
731         // Update items which were disassociated above
732
for (int i = 0; i < min; ++i) {
733
734             Item item = items[i];
735             if (item.getData() == null) {
736                 updateItem(item, children[i]);
737             }
738         }
739         // add any remaining elements
740
for (int i = min; i < children.length; ++i) {
741             createItem(children[i], i);
742         }
743     }
744
745     /**
746      * Removes the given elements from this table viewer.
747      *
748      * @param elements
749      * the elements to remove
750      */

751     private void internalRemove(final Object JavaDoc[] elements) {
752         Object JavaDoc input = getInput();
753         for (int i = 0; i < elements.length; ++i) {
754             if (equals(elements[i], input)) {
755                 boolean oldBusy = busy;
756                 busy = false;
757                 try {
758                     setInput(null);
759                 } finally {
760                     busy = oldBusy;
761                 }
762                 return;
763             }
764         }
765         // use remove(int[]) rather than repeated TableItem.dispose() calls
766
// to allow SWT to optimize multiple removals
767
int[] indices = new int[elements.length];
768         int count = 0;
769         for (int i = 0; i < elements.length; ++i) {
770             Widget w = findItem(elements[i]);
771             if (w == null && virtualManager != null) {
772                 int index = virtualManager.find(elements[i]);
773                 if (index != -1) {
774                     indices[count++] = index;
775                 }
776             } else if (w instanceof Item) {
777                 Item item = (Item) w;
778                 disassociate(item);
779                 indices[count++] = doIndexOf(item);
780             }
781         }
782         if (count < indices.length) {
783             System.arraycopy(indices, 0, indices = new int[count], 0, count);
784         }
785         if (virtualManager != null) {
786             virtualManager.removeIndices(indices);
787         }
788         doRemove(indices);
789
790         // Workaround for 1GDGN4Q: ITPUI:WIN2000 - TableViewer icons get
791
// scrunched
792
if (doGetItemCount() == 0) {
793             doRemoveAll();
794         }
795     }
796
797     /**
798      * Removes the given elements from this table viewer. The selection is
799      * updated if required.
800      * <p>
801      * This method should be called (by the content provider) when elements have
802      * been removed from the model, in order to cause the viewer to accurately
803      * reflect the model. This method only affects the viewer, not the model.
804      * </p>
805      *
806      * @param elements
807      * the elements to remove
808      */

809     public void remove(final Object JavaDoc[] elements) {
810         assertElementsNotNull(elements);
811         if (isBusy())
812             return;
813         if (elements.length == 0) {
814             return;
815         }
816         preservingSelection(new Runnable JavaDoc() {
817             public void run() {
818                 internalRemove(elements);
819             }
820         });
821     }
822
823     /**
824      * Removes the given element from this table viewer. The selection is
825      * updated if necessary.
826      * <p>
827      * This method should be called (by the content provider) when a single
828      * element has been removed from the model, in order to cause the viewer to
829      * accurately reflect the model. This method only affects the viewer, not
830      * the model. Note that there is another method for efficiently processing
831      * the simultaneous removal of multiple elements.
832      * </p>
833      * <strong>NOTE:</strong> removing an object from a virtual table will
834      * decrement the itemCount.
835      *
836      * @param element
837      * the element
838      */

839     public void remove(Object JavaDoc element) {
840         remove(new Object JavaDoc[] { element });
841     }
842
843     /*
844      * (non-Javadoc)
845      *
846      * @see org.eclipse.jface.viewers.StructuredViewer#reveal(java.lang.Object)
847      */

848     public void reveal(Object JavaDoc element) {
849         Assert.isNotNull(element);
850         Widget w = findItem(element);
851         if (w instanceof Item) {
852             doShowItem((Item) w);
853         }
854     }
855
856     /*
857      * (non-Javadoc)
858      *
859      * @see org.eclipse.jface.viewers.StructuredViewer#setSelectionToWidget(java.util.List,
860      * boolean)
861      */

862     protected void setSelectionToWidget(List JavaDoc list, boolean reveal) {
863         if (list == null) {
864             doDeselectAll();
865             return;
866         }
867
868         if (virtualManager != null) {
869             virtualSetSelectionToWidget(list, reveal);
870             return;
871         }
872         
873         // This is vital to use doSetSelection because on SWT-Table on Win32 this will also
874
// move the focus to this row (See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=198665)
875
if (reveal) {
876             int size = list.size();
877             Item[] items = new Item[size];
878             int count = 0;
879             for (int i = 0; i < size; ++i) {
880                 Object JavaDoc o = list.get(i);
881                 Widget w = findItem(o);
882                 if (w instanceof Item) {
883                     Item item = (Item) w;
884                     items[count++] = item;
885                 }
886             }
887             if (count < size) {
888                 System.arraycopy(items, 0, items = new Item[count], 0, count);
889             }
890             doSetSelection(items);
891         } else {
892             doDeselectAll(); // Clear the selection
893
if( ! list.isEmpty() ) {
894                 int[] indices = new int[list.size()];
895
896                 Iterator JavaDoc it = list.iterator();
897                 Item[] items = doGetItems();
898                 Object JavaDoc modelElement;
899
900                 int count = 0;
901                 while( it.hasNext() ) {
902                     modelElement = it.next();
903                     boolean found = false;
904                     for (int i = 0; i < items.length && !found; i++) {
905                         if (equals(modelElement, items[i].getData())) {
906                             indices[count++] = i;
907                             found = true;
908                         }
909                     }
910                 }
911
912                 if (count < indices.length) {
913                     System.arraycopy(indices, 0, indices = new int[count], 0, count);
914                 }
915
916                 doSelect(indices);
917             }
918         }
919     }
920     
921     /**
922      * Set the selection on a virtual table
923      *
924      * @param list
925      * The elements to set
926      * @param reveal
927      * Whether or not reveal the first item.
928      */

929     private void virtualSetSelectionToWidget(List JavaDoc list, boolean reveal) {
930         int size = list.size();
931         int[] indices = new int[list.size()];
932
933         Item firstItem = null;
934         int count = 0;
935         HashSet JavaDoc virtualElements = new HashSet JavaDoc();
936         for (int i = 0; i < size; ++i) {
937             Object JavaDoc o = list.get(i);
938             Widget w = findItem(o);
939             if (w instanceof Item) {
940                 Item item = (Item) w;
941                 indices[count++] = doIndexOf(item);
942                 if (firstItem == null) {
943                     firstItem = item;
944                 }
945             } else {
946                 virtualElements.add(o);
947             }
948         }
949
950         if (getContentProvider() instanceof ILazyContentProvider) {
951             ILazyContentProvider provider = (ILazyContentProvider) getContentProvider();
952
953             // Now go through it again until all is done or we are no longer
954
// virtual
955
// This may create all items so it is not a good
956
// idea in general.
957
// Use #setSelection (int [] indices,boolean reveal) instead
958
for (int i = 0; virtualElements.size() > 0 && i < doGetItemCount(); i++) {
959                 provider.updateElement(i);
960                 Item item = doGetItem(i);
961                 if (virtualElements.contains(item.getData())) {
962                     indices[count++] = i;
963                     virtualElements.remove(item.getData());
964                     if (firstItem == null) {
965                         firstItem = item;
966                     }
967                 }
968             }
969         } else {
970
971             if (count != list.size()) {// As this is expensive skip it if all
972
// have been found
973
// If it is not lazy we can use the cache
974
for (int i = 0; i < virtualManager.cachedElements.length; i++) {
975                     Object JavaDoc element = virtualManager.cachedElements[i];
976                     if (virtualElements.contains(element)) {
977                         Item item = doGetItem(i);
978                         item.getText();// Be sure to fire the update
979
indices[count++] = i;
980                         virtualElements.remove(element);
981                         if (firstItem == null) {
982                             firstItem = item;
983                         }
984                     }
985                 }
986             }
987         }
988
989         if (count < size) {
990             System.arraycopy(indices, 0, indices = new int[count], 0, count);
991         }
992         doSetSelection(indices);
993
994         if (reveal && firstItem != null) {
995             doShowItem(firstItem);
996         }
997     }
998
999     /**
1000     * Set the item count of the receiver.
1001     *
1002     * @param count
1003     * the new table size.
1004     *
1005     * @since 3.1
1006     */

1007    public void setItemCount(int count) {
1008        if (isBusy())
1009            return;
1010        int oldCount = doGetItemCount();
1011        if (count < oldCount) {
1012            // need to disassociate elements that are being disposed
1013
for (int i = count; i < oldCount; i++) {
1014                Item item = doGetItem(i);
1015                if (item.getData() != null) {
1016                    disassociate(item);
1017                }
1018            }
1019        }
1020        doSetItemCount(count);
1021        if (virtualManager != null) {
1022            virtualManager.adjustCacheSize(count);
1023        }
1024        getControl().redraw();
1025    }
1026
1027    /**
1028     * Replace the entries starting at index with elements. This method assumes
1029     * all of these values are correct and will not call the content provider to
1030     * verify. <strong>Note that this method will create a TableItem for all of
1031     * the elements provided</strong>.
1032     *
1033     * @param element
1034     * @param index
1035     * @see ILazyContentProvider
1036     *
1037     * @since 3.1
1038     */

1039    public void replace(Object JavaDoc element, int index) {
1040        if (isBusy())
1041            return;
1042        Item item = doGetItem(index);
1043        refreshItem(item, element);
1044    }
1045
1046    /**
1047     * Clear the table item at the specified index
1048     *
1049     * @param index
1050     * the index of the table item to be cleared
1051     *
1052     * @since 3.1
1053     */

1054    public void clear(int index) {
1055        Item item = doGetItem(index);
1056        if (item.getData() != null) {
1057            disassociate(item);
1058        }
1059        doClear(index);
1060    }
1061
1062    /*
1063     * (non-Javadoc)
1064     *
1065     * @see org.eclipse.jface.viewers.StructuredViewer#getRawChildren(java.lang.Object)
1066     */

1067    protected Object JavaDoc[] getRawChildren(Object JavaDoc parent) {
1068
1069        Assert.isTrue(!(getContentProvider() instanceof ILazyContentProvider),
1070                "Cannot get raw children with an ILazyContentProvider");//$NON-NLS-1$
1071
return super.getRawChildren(parent);
1072
1073    }
1074
1075    /*
1076     * (non-Javadoc)
1077     *
1078     * @see org.eclipse.jface.viewers.StructuredViewer#assertContentProviderType(org.eclipse.jface.viewers.IContentProvider)
1079     */

1080    protected void assertContentProviderType(IContentProvider provider) {
1081        Assert.isTrue(provider instanceof IStructuredContentProvider
1082                || provider instanceof ILazyContentProvider);
1083    }
1084
1085    /**
1086     * Searches the receiver's list starting at the first item (index 0) until
1087     * an item is found that is equal to the argument, and returns the index of
1088     * that item. If no item is found, returns -1.
1089     *
1090     * @param item
1091     * the search item
1092     * @return the index of the item
1093     *
1094     * @since 3.3
1095     */

1096    protected abstract int doIndexOf(Item item);
1097
1098    /**
1099     * Returns the number of items contained in the receiver.
1100     *
1101     * @return the number of items
1102     *
1103     * @since 3.3
1104     */

1105    protected abstract int doGetItemCount();
1106
1107    /**
1108     * Sets the number of items contained in the receiver.
1109     *
1110     * @param count
1111     * the number of items
1112     *
1113     * @since 3.3
1114     */

1115    protected abstract void doSetItemCount(int count);
1116
1117    /**
1118     * Returns a (possibly empty) array of TableItems which are the items in the
1119     * receiver.
1120     *
1121     * @return the items in the receiver
1122     *
1123     * @since 3.3
1124     */

1125    protected abstract Item[] doGetItems();
1126
1127    /**
1128     * Returns the column at the given, zero-relative index in the receiver.
1129     * Throws an exception if the index is out of range. Columns are returned in
1130     * the order that they were created. If no TableColumns were created by the
1131     * programmer, this method will throw ERROR_INVALID_RANGE despite the fact
1132     * that a single column of data may be visible in the table. This occurs
1133     * when the programmer uses the table like a list, adding items but never
1134     * creating a column.
1135     *
1136     * @param index
1137     * the index of the column to return
1138     * @return the column at the given index
1139     * @exception IllegalArgumentException -
1140     * if the index is not between 0 and the number of elements
1141     * in the list minus 1 (inclusive)
1142     *
1143     * @since 3.3
1144     */

1145    protected abstract Widget doGetColumn(int index);
1146
1147    /**
1148     * Returns the item at the given, zero-relative index in the receiver.
1149     * Throws an exception if the index is out of range.
1150     *
1151     * @param index
1152     * the index of the item to return
1153     * @return the item at the given index
1154     * @exception IllegalArgumentException -
1155     * if the index is not between 0 and the number of elements
1156     * in the list minus 1 (inclusive)
1157     *
1158     * @since 3.3
1159     */

1160    protected abstract Item doGetItem(int index);
1161
1162    /**
1163     * Returns an array of {@link Item} that are currently selected in the
1164     * receiver. The order of the items is unspecified. An empty array indicates
1165     * that no items are selected.
1166     *
1167     * @return an array representing the selection
1168     *
1169     * @since 3.3
1170     */

1171    protected abstract Item[] doGetSelection();
1172
1173    /**
1174     * Returns the zero-relative indices of the items which are currently
1175     * selected in the receiver. The order of the indices is unspecified. The
1176     * array is empty if no items are selected.
1177     *
1178     * @return an array representing the selection
1179     *
1180     * @since 3.3
1181     */

1182    protected abstract int[] doGetSelectionIndices();
1183
1184    /**
1185     * Clears all the items in the receiver. The text, icon and other attributes
1186     * of the items are set to their default values. If the table was created
1187     * with the <code>SWT.VIRTUAL</code> style, these attributes are requested
1188     * again as needed.
1189     *
1190     * @since 3.3
1191     */

1192    protected abstract void doClearAll();
1193
1194    /**
1195     * Resets the given item in the receiver. The text, icon and other attributes
1196     * of the item are set to their default values.
1197     *
1198     * @param item the item to reset
1199     *
1200     * @since 3.3
1201     */

1202    protected abstract void doResetItem(Item item);
1203    
1204    /**
1205     * Removes the items from the receiver which are between the given
1206     * zero-relative start and end indices (inclusive).
1207     *
1208     * @param start
1209     * the start of the range
1210     * @param end
1211     * the end of the range
1212     *
1213     * @exception IllegalArgumentException -
1214     * if either the start or end are not between 0 and the
1215     * number of elements in the list minus 1 (inclusive)
1216     *
1217     * @since 3.3
1218     */

1219    protected abstract void doRemove(int start, int end);
1220
1221    /**
1222     * Removes all of the items from the receiver.
1223     *
1224     * @since 3.3
1225     */

1226    protected abstract void doRemoveAll();
1227
1228    /**
1229     * Removes the items from the receiver's list at the given zero-relative
1230     * indices.
1231     *
1232     * @param indices
1233     * the array of indices of the items
1234     *
1235     * @exception IllegalArgumentException -
1236     * if the array is null, or if any of the indices is not
1237     * between 0 and the number of elements in the list minus 1
1238     * (inclusive)
1239     *
1240     * @since 3.3
1241     */

1242    protected abstract void doRemove(int[] indices);
1243
1244    /**
1245     * Shows the item. If the item is already showing in the receiver, this
1246     * method simply returns. Otherwise, the items are scrolled until the item
1247     * is visible.
1248     *
1249     * @param item
1250     * the item to be shown
1251     *
1252     * @exception IllegalArgumentException -
1253     * if the item is null
1254     *
1255     * @since 3.3
1256     */

1257    protected abstract void doShowItem(Item item);
1258
1259    /**
1260     * Deselects all selected items in the receiver.
1261     *
1262     * @since 3.3
1263     */

1264    protected abstract void doDeselectAll();
1265
1266    /**
1267     * Sets the receiver's selection to be the given array of items. The current
1268     * selection is cleared before the new items are selected.
1269     * <p>
1270     * Items that are not in the receiver are ignored. If the receiver is
1271     * single-select and multiple items are specified, then all items are
1272     * ignored.
1273     * </p>
1274     *
1275     * @param items
1276     * the array of items
1277     *
1278     * @exception IllegalArgumentException -
1279     * if the array of items is null
1280     *
1281     * @since 3.3
1282     */

1283    protected abstract void doSetSelection(Item[] items);
1284
1285    /**
1286     * Shows the selection. If the selection is already showing in the receiver,
1287     * this method simply returns. Otherwise, the items are scrolled until the
1288     * selection is visible.
1289     *
1290     * @since 3.3
1291     */

1292    protected abstract void doShowSelection();
1293
1294    /**
1295     * Selects the items at the given zero-relative indices in the receiver. The
1296     * current selection is cleared before the new items are selected.
1297     * <p>
1298     * Indices that are out of range and duplicate indices are ignored. If the
1299     * receiver is single-select and multiple indices are specified, then all
1300     * indices are ignored.
1301     * </p>
1302     *
1303     * @param indices
1304     * the indices of the items to select
1305     *
1306     * @exception IllegalArgumentException -
1307     * if the array of indices is null
1308     *
1309     * @since 3.3
1310     */

1311    protected abstract void doSetSelection(int[] indices);
1312
1313    /**
1314     * Clears the item at the given zero-relative index in the receiver. The
1315     * text, icon and other attributes of the item are set to the default value.
1316     * If the table was created with the <code>SWT.VIRTUAL</code> style, these
1317     * attributes are requested again as needed.
1318     *
1319     * @param index
1320     * the index of the item to clear
1321     *
1322     * @exception IllegalArgumentException -
1323     * if the index is not between 0 and the number of elements
1324     * in the list minus 1 (inclusive)
1325     *
1326     * @see SWT#VIRTUAL
1327     * @see SWT#SetData
1328     *
1329     * @since 3.3
1330     */

1331    protected abstract void doClear(int index);
1332    
1333        
1334            
1335    /**
1336     * Selects the items at the given zero-relative indices in the receiver.
1337     * The current selection is not cleared before the new items are selected.
1338     * <p>
1339     * If the item at a given index is not selected, it is selected.
1340     * If the item at a given index was already selected, it remains selected.
1341     * Indices that are out of range and duplicate indices are ignored.
1342     * If the receiver is single-select and multiple indices are specified,
1343     * then all indices are ignored.
1344     * </p>
1345     *
1346     * @param indices the array of indices for the items to select
1347     *
1348     * @exception IllegalArgumentException - if the array of indices is null
1349     *
1350     */

1351    protected abstract void doSelect(int[] indices);
1352    
1353}
1354
Popular Tags