Mercurial > projects > dwt-addons
view dwtx/jface/viewers/AbstractTableViewer.d @ 90:7ffeace6c47f
Update 3.4M7 to 3.4
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sun, 06 Jul 2008 23:30:07 +0200 |
parents | 46a6e0e6ccd4 |
children | 04b47443bb01 |
line wrap: on
line source
/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation bug 154329 * - fixes in bug 170381, 198665, 200731 * Port to the D programming language: * Frank Benoit <benoit@tionex.de> *******************************************************************************/ module dwtx.jface.viewers.AbstractTableViewer; import dwtx.jface.viewers.ColumnViewer; import dwtx.jface.viewers.ViewerRow; import dwtx.jface.viewers.IBaseLabelProvider; import dwtx.jface.viewers.IContentProvider; import dwtx.jface.viewers.ILazyContentProvider; import dwtx.jface.viewers.ViewerColumn; import dwtx.jface.viewers.ViewerCell; import dwtx.jface.viewers.ViewerComparator; import dwtx.jface.viewers.IStructuredContentProvider; import tango.util.collection.model.SeqView; import tango.util.collection.ArraySeq; import tango.util.collection.HashSet; import dwt.DWT; import dwt.widgets.Control; import dwt.widgets.Event; import dwt.widgets.Item; import dwt.widgets.Listener; import dwt.widgets.Widget; import dwtx.core.runtime.Assert; import dwt.dwthelper.utils; import dwt.dwthelper.Runnable; import tango.core.Array; /** * This is a widget independent class implementors of * {@link dwt.widgets.Table} like widgets can use to provide a * viewer on top of their widget implementations. * * @since 3.3 */ public abstract class AbstractTableViewer : ColumnViewer { alias ColumnViewer.getLabelProvider getLabelProvider; alias ColumnViewer.setSelectionToWidget setSelectionToWidget; private class VirtualManager { /** * The currently invisible elements as provided by the content provider * or by addition. This will not be populated by an * ILazyStructuredContentProvider as an ILazyStructuredContentProvider * is only queried on the virtual callback. */ private Object[] cachedElements = null; /** * Create a new instance of the receiver. * */ public this() { addTableListener(); } /** * Add the listener for SetData on the table */ private void addTableListener() { getControl().addListener(DWT.SetData, new class Listener { /* * (non-Javadoc) * * @see dwt.widgets.Listener#handleEvent(dwt.widgets.Event) */ public void handleEvent(Event event) { Item item = cast(Item) event.item; final int index = doIndexOf(item); Object element = resolveElement(index); if (element is null) { // Didn't find it so make a request // Keep looking if it is not in the cache. IContentProvider contentProvider = getContentProvider(); // If we are building lazily then request lookup now if (auto lcp = cast(ILazyContentProvider)contentProvider ) { lcp.updateElement(index); return; } } associate(element, item); updateItem(item, element); } }); } /** * Get the element at index.Resolve it lazily if this is available. * * @param index * @return Object or <code>null</code> if it could not be found */ protected Object resolveElement(int index) { Object element = null; if (index < cachedElements.length) { element = cachedElements[index]; } return element; } /** * A non visible item has been added. * * @param element * @param index */ public void notVisibleAdded(Object element, int index) { int requiredCount = doGetItemCount() + 1; Object[] newCache = new Object[requiredCount]; System.arraycopy(cachedElements, 0, newCache, 0, index); if (index < cachedElements.length) { System.arraycopy(cachedElements, index, newCache, index + 1, cachedElements.length - index); } newCache[index] = element; cachedElements = newCache; doSetItemCount(requiredCount); } /** * The elements with the given indices need to be removed from the * cache. * * @param indices */ public void removeIndices(int[] indices) { if (indices.length is 1) { removeIndicesFromTo(indices[0], indices[0]); } int requiredCount = doGetItemCount() - indices.length; tango.core.Array.sort( indices ); Object[] newCache = new Object[requiredCount]; int indexInNewCache = 0; int nextToSkip = 0; for (int i = 0; i < cachedElements.length; i++) { if (nextToSkip < indices.length && i is indices[nextToSkip]) { nextToSkip++; } else { newCache[indexInNewCache++] = cachedElements[i]; } } cachedElements = newCache; } /** * The elements between the given indices (inclusive) need to be removed * from the cache. * * @param from * @param to */ public void removeIndicesFromTo(int from, int to) { int indexAfterTo = to + 1; Object[] newCache = new Object[cachedElements.length - (indexAfterTo - from)]; System.arraycopy(cachedElements, 0, newCache, 0, from); if (indexAfterTo < cachedElements.length) { System.arraycopy(cachedElements, indexAfterTo, newCache, from, cachedElements.length - indexAfterTo); } } /** * @param element * @return the index of the element in the cache, or null */ public int find(Object element) { int res = tango.core.Array.find( cachedElements, element ); if( res is cachedElements.length ) res = -1; return res; } /** * @param count */ public void adjustCacheSize(int count) { if (count is cachedElements.length) { return; } else if (count < cachedElements.length) { Object[] newCache = new Object[count]; System.arraycopy(cachedElements, 0, newCache, 0, count); cachedElements = newCache; } else { Object[] newCache = new Object[count]; System.arraycopy(cachedElements, 0, newCache, 0, cachedElements.length); cachedElements = newCache; } } } private VirtualManager virtualManager; /** * Create the new viewer for table like widgets */ public this() { super(); } protected override void hookControl(Control control) { super.hookControl(control); initializeVirtualManager(getControl().getStyle()); } /** * Initialize the virtual manager to manage the virtual state if the table * is VIRTUAL. If not use the default no-op version. * * @param style */ private void initializeVirtualManager(int style) { if ((style & DWT.VIRTUAL) is 0) { return; } virtualManager = new VirtualManager(); } /** * Adds the given elements to this table viewer. If this viewer does not * have a sorter, the elements are added at the end in the order given; * otherwise the elements are inserted at appropriate positions. * <p> * This method should be called (by the content provider) when elements have * been added to the model, in order to cause the viewer to accurately * reflect the model. This method only affects the viewer, not the model. * </p> * * @param elements * the elements to add */ public void add(Object[] elements) { assertElementsNotNull(elements); if (checkBusy()) return; Object[] filtered = filter(elements); for (int i = 0; i < filtered.length; i++) { Object element = filtered[i]; int index = indexForElement(element); createItem(element, index); } } /** * Create a new TableItem at index if required. * * @param element * @param index * * @since 3.1 */ private void createItem(Object element, int index) { if (virtualManager is null) { updateItem(internalCreateNewRowPart(DWT.NONE, index).getItem(), element); } else { virtualManager.notVisibleAdded(element, index); } } /** * Create a new row. Callers can only use the returned object locally and before * making the next call on the viewer since it may be re-used for subsequent method * calls. * * @param style * the style for the new row * @param rowIndex * the index of the row or -1 if the row is appended at the end * @return the newly created row */ protected abstract ViewerRow internalCreateNewRowPart(int style, int rowIndex); /** * Adds the given element to this table viewer. If this viewer does not have * a sorter, the element is added at the end; otherwise the element is * inserted at the appropriate position. * <p> * This method should be called (by the content provider) when a single * element has been added to the model, in order to cause the viewer to * accurately reflect the model. This method only affects the viewer, not * the model. Note that there is another method for efficiently processing * the simultaneous addition of multiple elements. * </p> * * @param element * the element to add */ public void add(Object element) { add([ element ]); } /* * (non-Javadoc) * * @see dwtx.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object) */ protected override Widget doFindInputItem(Object element) { if (opEquals(element, getRoot())) { return getControl(); } return null; } /* * (non-Javadoc) * * @see dwtx.jface.viewers.StructuredViewer#doFindItem(java.lang.Object) */ protected override Widget doFindItem(Object element) { Item[] children = doGetItems(); for (int i = 0; i < children.length; i++) { Item item = children[i]; Object data = item.getData(); if (data !is null && opEquals(data, element)) { return item; } } return null; } /* * (non-Javadoc) * * @see dwtx.jface.viewers.StructuredViewer#doUpdateItem(dwt.widgets.Widget, * java.lang.Object, bool) */ protected override void doUpdateItem(Widget widget, Object element, bool fullMap) { bool oldBusy = isBusy(); setBusy(true); try { if ( auto item = cast(Item)widget ) { // remember element we are showing if (fullMap) { associate(element, item); } else { Object data = item.getData(); if (data !is null) { unmapElement(data, item); } item.setData(element); mapElement(element, item); } int columnCount = doGetColumnCount(); if (columnCount is 0) columnCount = 1;// If there are no columns do the first one ViewerRow viewerRowFromItem = getViewerRowFromItem(item); bool isVirtual = (getControl().getStyle() & DWT.VIRTUAL) !is 0; // If the control is virtual, we cannot use the cached viewer row object. See bug 188663. if (isVirtual) { viewerRowFromItem = cast(ViewerRow) viewerRowFromItem.clone(); } // Also enter loop if no columns added. See 1G9WWGZ: JFUIF:WINNT - // TableViewer with 0 columns does not work for (int column = 0; column < columnCount || column is 0; column++) { ViewerColumn columnViewer = getViewerColumn(column); ViewerCell cellToUpdate = updateCell(viewerRowFromItem, column, element); // If the control is virtual, we cannot use the cached cell object. See bug 188663. if (isVirtual) { cellToUpdate = new ViewerCell(cellToUpdate.getViewerRow(), cellToUpdate.getColumnIndex(), element); } columnViewer.refresh(cellToUpdate); // clear cell (see bug 201280) updateCell(null, 0, null); // As it is possible for user code to run the event // loop check here. if (item.isDisposed()) { unmapElement(element, item); return; } } } } finally { setBusy(oldBusy); } } /* * (non-Javadoc) * * @see dwtx.jface.viewers.ColumnViewer#getColumnViewerOwner(int) */ protected override Widget getColumnViewerOwner(int columnIndex) { int columnCount = doGetColumnCount(); if (columnIndex < 0 || (columnIndex > 0 && columnIndex >= columnCount)) { return null; } if (columnCount is 0)// Hang it off the table if it return getControl(); return doGetColumn(columnIndex); } /** * Returns the element with the given index from this table viewer. Returns * <code>null</code> if the index is out of range. * <p> * This method is internal to the framework. * </p> * * @param index * the zero-based index * @return the element at the given index, or <code>null</code> if the * index is out of range */ public Object getElementAt(int index) { if (index >= 0 && index < doGetItemCount()) { Item i = doGetItem(index); if (i !is null) { return i.getData(); } } return null; } /** * The table viewer implementation of this <code>Viewer</code> framework * method returns the label provider, which in the case of table viewers * will be an instance of either <code>ITableLabelProvider</code> or * <code>ILabelProvider</code>. If it is an * <code>ITableLabelProvider</code>, then it provides a separate label * text and image for each column. If it is an <code>ILabelProvider</code>, * then it provides only the label text and image for the first column, and * any remaining columns are blank. */ public override IBaseLabelProvider getLabelProvider() { return super.getLabelProvider(); } /* * (non-Javadoc) * * @see dwtx.jface.viewers.StructuredViewer#getSelectionFromWidget() */ protected override SeqView!(Object) getSelectionFromWidget() { if (virtualManager !is null) { return getVirtualSelection(); } Widget[] items = doGetSelection(); auto list = new ArraySeq!(Object); list.capacity(items.length); for (int i = 0; i < items.length; i++) { Widget item = items[i]; Object e = item.getData(); if (e !is null) { list.append(e); } } return list; } /** * Get the virtual selection. Avoid calling DWT whenever possible to prevent * extra widget creation. * * @return List of Object */ private SeqView!(Object) getVirtualSelection() { auto result = new ArraySeq!(Object); int[] selectionIndices = doGetSelectionIndices(); if (auto lazy_ = cast(ILazyContentProvider) getContentProvider() ) { for (int i = 0; i < selectionIndices.length; i++) { int selectionIndex = selectionIndices[i]; lazy_.updateElement(selectionIndex);// Start the update Object element = doGetItem(selectionIndex).getData(); // Only add the element if it got updated. // If this is done deferred the selection will // be incomplete until selection is finished. if (element !is null) { result.append(element); } } } else { for (int i = 0; i < selectionIndices.length; i++) { Object element = null; // See if it is cached int selectionIndex = selectionIndices[i]; if (selectionIndex < virtualManager.cachedElements.length) { element = virtualManager.cachedElements[selectionIndex]; } if (element is null) { // Not cached so try the item's data Item item = doGetItem(selectionIndex); element = item.getData(); } if (element !is null) { result.append(element); } } } return result; } /** * @param element * the element to insert * @return the index where the item should be inserted. */ protected int indexForElement(Object element) { ViewerComparator comparator = getComparator(); if (comparator is null) { return doGetItemCount(); } int count = doGetItemCount(); int min = 0, max = count - 1; while (min <= max) { int mid = (min + max) / 2; Object data = doGetItem(mid).getData(); int compare = comparator.compare(this, data, element); if (compare is 0) { // find first item > element while (compare is 0) { ++mid; if (mid >= count) { break; } data = doGetItem(mid).getData(); compare = comparator.compare(this, data, element); } return mid; } if (compare < 0) { min = mid + 1; } else { max = mid - 1; } } return min; } /* * (non-Javadoc) * * @see dwtx.jface.viewers.Viewer#inputChanged(java.lang.Object, * java.lang.Object) */ protected override void inputChanged(Object input, Object oldInput) { getControl().setRedraw(false); try { preservingSelection(new class Runnable { public void run() { internalRefresh(getRoot()); } }); } finally { getControl().setRedraw(true); } } /** * Inserts the given element into this table viewer at the given position. * If this viewer has a sorter, the position is ignored and the element is * inserted at the correct position in the sort order. * <p> * This method should be called (by the content provider) when elements have * been added to the model, in order to cause the viewer to accurately * reflect the model. This method only affects the viewer, not the model. * </p> * * @param element * the element * @param position * a 0-based position relative to the model, or -1 to indicate * the last position */ public void insert(Object element, int position) { applyEditorValue(); if (getComparator() !is null || hasFilters()) { add(element); return; } if (position is -1) { position = doGetItemCount(); } if (checkBusy()) return; createItem(element, position); } /* * (non-Javadoc) * * @see dwtx.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object) */ protected override void internalRefresh(Object element) { internalRefresh(element, true); } /* * (non-Javadoc) * * @see dwtx.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object, * bool) */ protected override void internalRefresh(Object element, bool updateLabels) { applyEditorValue(); if (element is null || opEquals(element, getRoot())) { if (virtualManager is null) { internalRefreshAll(updateLabels); } else { internalVirtualRefreshAll(); } } else { Widget w = findItem(element); if (w !is null) { updateItem(w, element); } } } /** * Refresh all with virtual elements. * * @since 3.1 */ private void internalVirtualRefreshAll() { Object root = getRoot(); IContentProvider contentProvider = getContentProvider(); // Invalidate for lazy if (!(cast(ILazyContentProvider)contentProvider ) && cast(IStructuredContentProvider)contentProvider ) { // Don't cache if the root is null but cache if it is not lazy. if (root !is null) { virtualManager.cachedElements = getSortedChildren(root); doSetItemCount(virtualManager.cachedElements.length); } } doClearAll(); } /** * Refresh all of the elements of the table. update the labels if * updatLabels is true; * * @param updateLabels * * @since 3.1 */ private void internalRefreshAll(bool updateLabels) { // the parent // in the code below, it is important to do all disassociates // before any associates, since a later disassociate can undo an // earlier associate // e.g. if (a, b) is replaced by (b, a), the disassociate of b to // item 1 could undo // the associate of b to item 0. Object[] children = getSortedChildren(getRoot()); Item[] items = doGetItems(); int min = Math.min(children.length, items.length); for (int i = 0; i < min; ++i) { Item item = items[i]; // if the element is unchanged, update its label if appropriate if (opEquals(children[i], item.getData())) { if (updateLabels) { updateItem(item, children[i]); } else { // associate the new element, even if equal to the old // one, // to remove stale references (see bug 31314) associate(children[i], item); } } else { // updateItem does an associate(...), which can mess up // the associations if the order of elements has changed. // E.g. (a, b) -> (b, a) first replaces a->0 with b->0, then // replaces b->1 with a->1, but this actually removes b->0. // So, if the object associated with this item has changed, // just disassociate it for now, and update it below. // we also need to reset the item (set its text,images etc. to // default values) because the label decorators rely on this disassociate(item); doClear(i); } } // dispose of all items beyond the end of the current elements if (min < items.length) { for (int i = items.length; --i >= min;) { disassociate(items[i]); } if (virtualManager !is null) { virtualManager.removeIndicesFromTo(min, items.length - 1); } doRemove(min, items.length - 1); } // Workaround for 1GDGN4Q: ITPUI:WIN2000 - TableViewer icons get // scrunched if (doGetItemCount() is 0) { doRemoveAll(); } // Update items which were disassociated above for (int i = 0; i < min; ++i) { Item item = items[i]; if (item.getData() is null) { updateItem(item, children[i]); } } // add any remaining elements for (int i = min; i < children.length; ++i) { createItem(children[i], i); } } /** * Removes the given elements from this table viewer. * * @param elements * the elements to remove */ private void internalRemove(Object[] elements) { Object input = getInput(); for (int i = 0; i < elements.length; ++i) { if (opEquals(elements[i], input)) { bool oldBusy = isBusy(); setBusy(false); try { setInput(null); } finally { setBusy(oldBusy); } return; } } // use remove(int[]) rather than repeated TableItem.dispose() calls // to allow DWT to optimize multiple removals int[] indices = new int[elements.length]; int count = 0; for (int i = 0; i < elements.length; ++i) { Widget w = findItem(elements[i]); if (w is null && virtualManager !is null) { int index = virtualManager.find(elements[i]); if (index !is -1) { indices[count++] = index; } } else if (auto item = cast(Item) w ) { disassociate(item); indices[count++] = doIndexOf(item); } } if (count < indices.length) { System.arraycopy(indices, 0, indices = new int[count], 0, count); } if (virtualManager !is null) { virtualManager.removeIndices(indices); } doRemove(indices); // Workaround for 1GDGN4Q: ITPUI:WIN2000 - TableViewer icons get // scrunched if (doGetItemCount() is 0) { doRemoveAll(); } } /** * Removes the given elements from this table viewer. The selection is * updated if required. * <p> * This method should be called (by the content provider) when elements have * been removed from the model, in order to cause the viewer to accurately * reflect the model. This method only affects the viewer, not the model. * </p> * * @param elements * the elements to remove */ public void remove( Object[] elements) { assertElementsNotNull(elements); if (checkBusy()) return; if (elements.length is 0) { return; } preservingSelection(new class(elements) Runnable { Object[] elements_; this(Object[] a){ elements_=a; } public void run() { internalRemove(elements_); } }); } /** * Removes the given element from this table viewer. The selection is * updated if necessary. * <p> * This method should be called (by the content provider) when a single * element has been removed from the model, in order to cause the viewer to * accurately reflect the model. This method only affects the viewer, not * the model. Note that there is another method for efficiently processing * the simultaneous removal of multiple elements. * </p> * <strong>NOTE:</strong> removing an object from a virtual table will * decrement the itemCount. * * @param element * the element */ public void remove(Object element) { remove([ element ]); } /* * (non-Javadoc) * * @see dwtx.jface.viewers.StructuredViewer#reveal(java.lang.Object) */ public override void reveal(Object element) { Assert.isNotNull(element); Widget w = findItem(element); if (auto i = cast(Item)w ) { doShowItem(i); } } /* * (non-Javadoc) * * @see dwtx.jface.viewers.StructuredViewer#setSelectionToWidget(java.util.List, * bool) */ protected override void setSelectionToWidget(SeqView!(Object) list, bool reveal) { if (list is null) { doDeselectAll(); return; } if (virtualManager !is null) { virtualSetSelectionToWidget(list, reveal); return; } // This is vital to use doSetSelection because on DWT-Table on Win32 this will also // move the focus to this row (See bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=198665) if (reveal) { int size = list.size(); Item[] items = new Item[size]; int count = 0; foreach( o; list ) { Widget w = findItem(o); if (auto item = cast(Item)w ) { items[count++] = item; } } if (count < size) { System.arraycopy(items, 0, items = new Item[count], 0, count); } doSetSelection(items); } else { doDeselectAll(); // Clear the selection if( ! list.drained() ) { int[] indices = new int[list.size()]; Item[] items = doGetItems(); int count = 0; foreach( modelElement; list ){ bool found = false; for (int i = 0; i < items.length && !found; i++) { if (opEquals(modelElement, items[i].getData())) { indices[count++] = i; found = true; } } } if (count < indices.length) { System.arraycopy(indices, 0, indices = new int[count], 0, count); } doSelect(indices); } } } /** * Set the selection on a virtual table * * @param list * The elements to set * @param reveal * Whether or not reveal the first item. */ private void virtualSetSelectionToWidget(SeqView!(Object) list, bool reveal) { int size = list.size(); int[] indices = new int[list.size()]; Item firstItem = null; int count = 0; auto virtualElements = new HashSet!(Object); foreach( o; list ){ Widget w = findItem(o); if (auto item = cast(Item)w ) { indices[count++] = doIndexOf(item); if (firstItem is null) { firstItem = item; } } else { virtualElements.add(o); } } if ( auto provider = cast(ILazyContentProvider) getContentProvider() ) { // Now go through it again until all is done or we are no longer // virtual // This may create all items so it is not a good // idea in general. // Use #setSelection (int [] indices,bool reveal) instead for (int i = 0; virtualElements.size() > 0 && i < doGetItemCount(); i++) { provider.updateElement(i); Item item = doGetItem(i); if (virtualElements.contains(item.getData())) { indices[count++] = i; virtualElements.remove(item.getData()); if (firstItem is null) { firstItem = item; } } } } else { if (count !is list.size()) {// As this is expensive skip it if all // have been found // If it is not lazy we can use the cache for (int i = 0; i < virtualManager.cachedElements.length; i++) { Object element = virtualManager.cachedElements[i]; if (virtualElements.contains(element)) { Item item = doGetItem(i); item.getText();// Be sure to fire the update indices[count++] = i; virtualElements.remove(element); if (firstItem is null) { firstItem = item; } } } } } if (count < size) { System.arraycopy(indices, 0, indices = new int[count], 0, count); } doDeselectAll(); doSelect(indices); if (reveal && firstItem !is null) { doShowItem(firstItem); } } /** * Set the item count of the receiver. * * @param count * the new table size. * * @since 3.1 */ public void setItemCount(int count) { if (checkBusy()) return; int oldCount = doGetItemCount(); if (count < oldCount) { // need to disassociate elements that are being disposed for (int i = count; i < oldCount; i++) { Item item = doGetItem(i); if (item.getData() !is null) { disassociate(item); } } } doSetItemCount(count); if (virtualManager !is null) { virtualManager.adjustCacheSize(count); } getControl().redraw(); } /** * Replace the element at the given index with the given element. This * method will not call the content provider to verify. <strong>Note that * this method will materialize a TableItem the given index.</strong>. * * @param element * @param index * @see ILazyContentProvider * * @since 3.1 */ public void replace(Object element, int index) { if (checkBusy()) return; Item item = doGetItem(index); refreshItem(item, element); } /** * Clear the table item at the specified index * * @param index * the index of the table item to be cleared * * @since 3.1 */ public void clear(int index) { Item item = doGetItem(index); if (item.getData() !is null) { disassociate(item); } doClear(index); } /* * (non-Javadoc) * * @see dwtx.jface.viewers.StructuredViewer#getRawChildren(java.lang.Object) */ protected override Object[] getRawChildren(Object parent) { Assert.isTrue(!( null !is cast(ILazyContentProvider) getContentProvider() ), "Cannot get raw children with an ILazyContentProvider");//$NON-NLS-1$ return super.getRawChildren(parent); } /* * (non-Javadoc) * * @see dwtx.jface.viewers.StructuredViewer#assertContentProviderType(dwtx.jface.viewers.IContentProvider) */ protected override void assertContentProviderType(IContentProvider provider) { Assert.isTrue(null !is cast(IStructuredContentProvider)provider || null !is cast(ILazyContentProvider)provider ); } /** * Searches the receiver's list starting at the first item (index 0) until * an item is found that is equal to the argument, and returns the index of * that item. If no item is found, returns -1. * * @param item * the search item * @return the index of the item * * @since 3.3 */ protected abstract int doIndexOf(Item item); /** * Returns the number of items contained in the receiver. * * @return the number of items * * @since 3.3 */ protected abstract int doGetItemCount(); /** * Sets the number of items contained in the receiver. * * @param count * the number of items * * @since 3.3 */ protected abstract void doSetItemCount(int count); /** * Returns a (possibly empty) array of TableItems which are the items in the * receiver. * * @return the items in the receiver * * @since 3.3 */ protected abstract Item[] doGetItems(); /** * Returns the column at the given, zero-relative index in the receiver. * Throws an exception if the index is out of range. Columns are returned in * the order that they were created. If no TableColumns were created by the * programmer, this method will throw ERROR_INVALID_RANGE despite the fact * that a single column of data may be visible in the table. This occurs * when the programmer uses the table like a list, adding items but never * creating a column. * * @param index * the index of the column to return * @return the column at the given index * @exception IllegalArgumentException - * if the index is not between 0 and the number of elements * in the list minus 1 (inclusive) * * @since 3.3 */ protected abstract Widget doGetColumn(int index); /** * Returns the item at the given, zero-relative index in the receiver. * Throws an exception if the index is out of range. * * @param index * the index of the item to return * @return the item at the given index * @exception IllegalArgumentException - * if the index is not between 0 and the number of elements * in the list minus 1 (inclusive) * * @since 3.3 */ protected abstract Item doGetItem(int index); /** * Returns an array of {@link Item} that are currently selected in the * receiver. The order of the items is unspecified. An empty array indicates * that no items are selected. * * @return an array representing the selection * * @since 3.3 */ protected abstract Item[] doGetSelection(); /** * Returns the zero-relative indices of the items which are currently * selected in the receiver. The order of the indices is unspecified. The * array is empty if no items are selected. * * @return an array representing the selection * * @since 3.3 */ protected abstract int[] doGetSelectionIndices(); /** * Clears all the items in the receiver. The text, icon and other attributes * of the items are set to their default values. If the table was created * with the <code>DWT.VIRTUAL</code> style, these attributes are requested * again as needed. * * @since 3.3 */ protected abstract void doClearAll(); /** * Resets the given item in the receiver. The text, icon and other attributes * of the item are set to their default values. * * @param item the item to reset * * @since 3.3 */ protected abstract void doResetItem(Item item); /** * Removes the items from the receiver which are between the given * zero-relative start and end indices (inclusive). * * @param start * the start of the range * @param end * the end of the range * * @exception IllegalArgumentException - * if either the start or end are not between 0 and the * number of elements in the list minus 1 (inclusive) * * @since 3.3 */ protected abstract void doRemove(int start, int end); /** * Removes all of the items from the receiver. * * @since 3.3 */ protected abstract void doRemoveAll(); /** * Removes the items from the receiver's list at the given zero-relative * indices. * * @param indices * the array of indices of the items * * @exception IllegalArgumentException - * if the array is null, or if any of the indices is not * between 0 and the number of elements in the list minus 1 * (inclusive) * * @since 3.3 */ protected abstract void doRemove(int[] indices); /** * Shows the item. If the item is already showing in the receiver, this * method simply returns. Otherwise, the items are scrolled until the item * is visible. * * @param item * the item to be shown * * @exception IllegalArgumentException - * if the item is null * * @since 3.3 */ protected abstract void doShowItem(Item item); /** * Deselects all selected items in the receiver. * * @since 3.3 */ protected abstract void doDeselectAll(); /** * Sets the receiver's selection to be the given array of items. The current * selection is cleared before the new items are selected. * <p> * Items that are not in the receiver are ignored. If the receiver is * single-select and multiple items are specified, then all items are * ignored. * </p> * * @param items * the array of items * * @exception IllegalArgumentException - * if the array of items is null * * @since 3.3 */ protected abstract void doSetSelection(Item[] items); /** * Shows the selection. If the selection is already showing in the receiver, * this method simply returns. Otherwise, the items are scrolled until the * selection is visible. * * @since 3.3 */ protected abstract void doShowSelection(); /** * Selects the items at the given zero-relative indices in the receiver. The * current selection is cleared before the new items are selected. * <p> * Indices that are out of range and duplicate indices are ignored. If the * receiver is single-select and multiple indices are specified, then all * indices are ignored. * </p> * * @param indices * the indices of the items to select * * @exception IllegalArgumentException - * if the array of indices is null * * @since 3.3 */ protected abstract void doSetSelection(int[] indices); /** * Clears the item at the given zero-relative index in the receiver. The * text, icon and other attributes of the item are set to the default value. * If the table was created with the <code>DWT.VIRTUAL</code> style, these * attributes are requested again as needed. * * @param index * the index of the item to clear * * @exception IllegalArgumentException - * if the index is not between 0 and the number of elements * in the list minus 1 (inclusive) * * @see DWT#VIRTUAL * @see DWT#SetData * * @since 3.3 */ protected abstract void doClear(int index); /** * Selects the items at the given zero-relative indices in the receiver. * The current selection is not cleared before the new items are selected. * <p> * If the item at a given index is not selected, it is selected. * If the item at a given index was already selected, it remains selected. * Indices that are out of range and duplicate indices are ignored. * If the receiver is single-select and multiple indices are specified, * then all indices are ignored. * </p> * * @param indices the array of indices for the items to select * * @exception IllegalArgumentException - if the array of indices is null * */ protected abstract void doSelect(int[] indices); }