Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*******************************************************************************
* Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Tom Schindl - initial API and implementation bug 154329
* - fixes in bug 170381, 198665, 200731
* Alexander Fedorov - Bug 548314
*******************************************************************************/
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.events.DisposeEvent;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Item;
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.
*
* This class is not intended to be subclassed outside of the JFace
* viewers framework.
*
*
* @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, event -> {
Item item = (Item) event.item;
final int index = doIndexOf(item);
if (index == -1) {
// Should not happen, but the spec for doIndexOf allows returning -1.
// See bug 241117.
return;
}
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 lazyProvider = (ILazyContentProvider) contentProvider;
if (!isBusy()) {
lazyProvider.updateElement(index);
} else {
// In case event is sent during doUpdateItem() we
// should run async update to avoid RuntimeException
// from ColumnViewer.checkBusy(), see bug 488484
Control control = getControl();
control.getDisplay().asyncExec(() -> {
if (!control.isDisposed()) {
lazyProvider.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 null 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();
}
@Override
protected void hookControl(Control control) {
super.hookControl(control);
initializeVirtualManager(getControl().getStyle());
}
@Override
protected void handleDispose(DisposeEvent event) {
super.handleDispose(event);
virtualManager = null;
}
/**
* 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.
*
* 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.
*
*
* @param elements
* the elements to add
*/
public void add(Object[] elements) {
assertElementsNotNull(elements);
if (checkBusy())
return;
Object[] filtered = filter(elements);
for (Object element : filtered) {
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.
*
* 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.
*
*
* @param element
* the element to add
*/
public void add(Object element) {
add(new Object[] { element });
}
@Override
protected Widget doFindInputItem(Object element) {
if (equals(element, getRoot())) {
return getControl();
}
return null;
}
@Override
protected Widget doFindItem(Object element) {
Item[] children = doGetItems();
for (Item item : children) {
Object data = item.getData();
if (data != null && equals(data, element)) {
return item;
}
}
return null;
}
@Override
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);
}
}
@Override
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
* null if the index is out of range.
*
* This method is internal to the framework.
*
*
* @param index
* the zero-based index
* @return the element at the given index, or null 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 Viewer framework
* method returns the label provider, which in the case of table viewers
* will be an instance of either ITableLabelProvider or
* ILabelProvider. If it is an
* ITableLabelProvider, then it provides a separate label
* text and image for each column. If it is an ILabelProvider,
* then it provides only the label text and image for the first column, and
* any remaining columns are blank.
*/
@Override
public IBaseLabelProvider getLabelProvider() {
return super.getLabelProvider();
}
@SuppressWarnings("rawtypes")
@Override
protected List getSelectionFromWidget() {
if (virtualManager != null) {
return getVirtualSelection();
}
Widget[] items = doGetSelection();
List