blob: 9975f7243e7877100d926561744ab6221a04f2b9 [file] [log] [blame]
/*******************************************************************************
* 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
*******************************************************************************/
package org.eclipse.jface.viewers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Widget;
/**
* This is a widget independent class implementors of
* {@link org.eclipse.swt.widgets.Table} like widgets can use to provide a
* viewer on top of their widget implementations.
*
* @since 3.3
*/
public abstract class AbstractTableViewer extends ColumnViewer {
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 = new Object[0];
/**
* Create a new instance of the receiver.
*
*/
public VirtualManager() {
addTableListener();
}
/**
* Add the listener for SetData on the table
*/
private void addTableListener() {
getControl().addListener(SWT.SetData, new Listener() {
/*
* (non-Javadoc)
*
* @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
*/
public void handleEvent(Event event) {
Item item = (Item) event.item;
final int index = doIndexOf(item);
Object element = resolveElement(index);
if (element == 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 (contentProvider instanceof ILazyContentProvider) {
((ILazyContentProvider) contentProvider)
.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 == 1) {
removeIndicesFromTo(indices[0], indices[0]);
}
int requiredCount = doGetItemCount() - indices.length;
Arrays.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 == 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) {
return Arrays.asList(cachedElements).indexOf(element);
}
/**
* @param count
*/
public void adjustCacheSize(int count) {
if (count == 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 AbstractTableViewer() {
super();
}
protected 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 & SWT.VIRTUAL) == 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 == null) {
updateItem(internalCreateNewRowPart(SWT.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(new Object[] { element });
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.StructuredViewer#doFindInputItem(java.lang.Object)
*/
protected Widget doFindInputItem(Object element) {
if (equals(element, getRoot())) {
return getControl();
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.StructuredViewer#doFindItem(java.lang.Object)
*/
protected 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 != null && equals(data, element)) {
return item;
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.StructuredViewer#doUpdateItem(org.eclipse.swt.widgets.Widget,
* java.lang.Object, boolean)
*/
protected void doUpdateItem(Widget widget, Object element, boolean fullMap) {
boolean oldBusy = isBusy();
setBusy(true);
try {
if (widget instanceof Item) {
final Item item = (Item) widget;
// remember element we are showing
if (fullMap) {
associate(element, item);
} else {
Object data = item.getData();
if (data != null) {
unmapElement(data, item);
}
item.setData(element);
mapElement(element, item);
}
int columnCount = doGetColumnCount();
if (columnCount == 0)
columnCount = 1;// If there are no columns do the first one
ViewerRow viewerRowFromItem = getViewerRowFromItem(item);
boolean isVirtual = (getControl().getStyle() & SWT.VIRTUAL) != 0;
// If the control is virtual, we cannot use the cached viewer row object. See bug 188663.
if (isVirtual) {
viewerRowFromItem = (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 == 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 org.eclipse.jface.viewers.ColumnViewer#getColumnViewerOwner(int)
*/
protected Widget getColumnViewerOwner(int columnIndex) {
int columnCount = doGetColumnCount();
if (columnIndex < 0
|| (columnIndex > 0 && columnIndex >= columnCount)) {
return null;
}
if (columnCount == 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 != 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 IBaseLabelProvider getLabelProvider() {
return super.getLabelProvider();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.StructuredViewer#getSelectionFromWidget()
*/
protected List getSelectionFromWidget() {
if (virtualManager != null) {
return getVirtualSelection();
}
Widget[] items = doGetSelection();
ArrayList list = new ArrayList(items.length);
for (int i = 0; i < items.length; i++) {
Widget item = items[i];
Object e = item.getData();
if (e != null) {
list.add(e);
}
}
return list;
}
/**
* Get the virtual selection. Avoid calling SWT whenever possible to prevent
* extra widget creation.
*
* @return List of Object
*/
private List getVirtualSelection() {
List result = new ArrayList();
int[] selectionIndices = doGetSelectionIndices();
if (getContentProvider() instanceof ILazyContentProvider) {
ILazyContentProvider lazy = (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 != null) {
result.add(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 == null) {
// Not cached so try the item's data
Item item = doGetItem(selectionIndex);
element = item.getData();
}
if (element != null) {
result.add(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 == 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 == 0) {
// find first item > element
while (compare == 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 org.eclipse.jface.viewers.Viewer#inputChanged(java.lang.Object,
* java.lang.Object)
*/
protected void inputChanged(Object input, Object oldInput) {
getControl().setRedraw(false);
try {
preservingSelection(new 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() != null || hasFilters()) {
add(element);
return;
}
if (position == -1) {
position = doGetItemCount();
}
if (checkBusy())
return;
createItem(element, position);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object)
*/
protected void internalRefresh(Object element) {
internalRefresh(element, true);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.StructuredViewer#internalRefresh(java.lang.Object,
* boolean)
*/
protected void internalRefresh(Object element, boolean updateLabels) {
applyEditorValue();
if (element == null || equals(element, getRoot())) {
if (virtualManager == null) {
internalRefreshAll(updateLabels);
} else {
internalVirtualRefreshAll();
}
} else {
Widget w = findItem(element);
if (w != 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 (!(contentProvider instanceof ILazyContentProvider)
&& (contentProvider instanceof IStructuredContentProvider)) {
// Don't cache if the root is null but cache if it is not lazy.
if (root != 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(boolean 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 (equals(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 != null) {
virtualManager.removeIndicesFromTo(min, items.length - 1);
}
doRemove(min, items.length - 1);
}
// Workaround for 1GDGN4Q: ITPUI:WIN2000 - TableViewer icons get
// scrunched
if (doGetItemCount() == 0) {
doRemoveAll();
}
// Update items which were disassociated above
for (int i = 0; i < min; ++i) {
Item item = items[i];
if (item.getData() == 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(final Object[] elements) {
Object input = getInput();
for (int i = 0; i < elements.length; ++i) {
if (equals(elements[i], input)) {
boolean oldBusy = isBusy();
setBusy(false);
try {
setInput(null);
} finally {
setBusy(oldBusy);
}
return;
}
}
// use remove(int[]) rather than repeated TableItem.dispose() calls
// to allow SWT 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 == null && virtualManager != null) {
int index = virtualManager.find(elements[i]);
if (index != -1) {
indices[count++] = index;
}
} else if (w instanceof Item) {
Item item = (Item) w;
disassociate(item);
indices[count++] = doIndexOf(item);
}
}
if (count < indices.length) {
System.arraycopy(indices, 0, indices = new int[count], 0, count);
}
if (virtualManager != null) {
virtualManager.removeIndices(indices);
}
doRemove(indices);
// Workaround for 1GDGN4Q: ITPUI:WIN2000 - TableViewer icons get
// scrunched
if (doGetItemCount() == 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(final Object[] elements) {
assertElementsNotNull(elements);
if (checkBusy())
return;
if (elements.length == 0) {
return;
}
preservingSelection(new Runnable() {
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(new Object[] { element });
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.StructuredViewer#reveal(java.lang.Object)
*/
public void reveal(Object element) {
Assert.isNotNull(element);
Widget w = findItem(element);
if (w instanceof Item) {
doShowItem((Item) w);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.StructuredViewer#setSelectionToWidget(java.util.List,
* boolean)
*/
protected void setSelectionToWidget(List list, boolean reveal) {
if (list == null) {
doDeselectAll();
return;
}
if (virtualManager != null) {
virtualSetSelectionToWidget(list, reveal);
return;
}
// This is vital to use doSetSelection because on SWT-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;
for (int i = 0; i < size; ++i) {
Object o = list.get(i);
Widget w = findItem(o);
if (w instanceof Item) {
Item item = (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.isEmpty() ) {
int[] indices = new int[list.size()];
Iterator it = list.iterator();
Item[] items = doGetItems();
Object modelElement;
int count = 0;
while( it.hasNext() ) {
modelElement = it.next();
boolean found = false;
for (int i = 0; i < items.length && !found; i++) {
if (equals(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(List list, boolean reveal) {
int size = list.size();
int[] indices = new int[list.size()];
Item firstItem = null;
int count = 0;
HashSet virtualElements = new HashSet();
for (int i = 0; i < size; ++i) {
Object o = list.get(i);
Widget w = findItem(o);
if (w instanceof Item) {
Item item = (Item) w;
indices[count++] = doIndexOf(item);
if (firstItem == null) {
firstItem = item;
}
} else {
virtualElements.add(o);
}
}
if (getContentProvider() instanceof ILazyContentProvider) {
ILazyContentProvider provider = (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,boolean 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 == null) {
firstItem = item;
}
}
}
} else {
if (count != 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 == null) {
firstItem = item;
}
}
}
}
}
if (count < size) {
System.arraycopy(indices, 0, indices = new int[count], 0, count);
}
doDeselectAll();
doSelect(indices);
if (reveal && firstItem != 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() != null) {
disassociate(item);
}
}
}
doSetItemCount(count);
if (virtualManager != 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() != null) {
disassociate(item);
}
doClear(index);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.StructuredViewer#getRawChildren(java.lang.Object)
*/
protected Object[] getRawChildren(Object parent) {
Assert.isTrue(!(getContentProvider() instanceof ILazyContentProvider),
"Cannot get raw children with an ILazyContentProvider");//$NON-NLS-1$
return super.getRawChildren(parent);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.StructuredViewer#assertContentProviderType(org.eclipse.jface.viewers.IContentProvider)
*/
protected void assertContentProviderType(IContentProvider provider) {
Assert.isTrue(provider instanceof IStructuredContentProvider
|| provider instanceof ILazyContentProvider);
}
/**
* 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>SWT.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>SWT.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 SWT#VIRTUAL
* @see SWT#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);
}