org.eclipse.nebula.jface.gridviewer.GridTableViewer Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2007 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:
* [email protected] - initial API and implementation
* [email protected] - various significant contributions
* [email protected] - improve performance
*******************************************************************************/
package org.eclipse.nebula.jface.gridviewer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jface.viewers.AbstractTableViewer;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnViewerEditor;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent;
import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerRow;
import org.eclipse.nebula.jface.gridviewer.internal.CellSelection;
import org.eclipse.nebula.jface.gridviewer.internal.SelectionWithFocusRow;
// [RAP ] DataVisualizer missing
// import org.eclipse.nebula.widgets.grid.DataVisualizer;
import org.eclipse.nebula.widgets.grid.Grid;
import org.eclipse.nebula.widgets.grid.GridItem;
import org.eclipse.nebula.widgets.grid.internal.IGridAdapter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Widget;
/**
* A concrete viewer based on an Grid control.
*
* This class is not intended to be subclassed outside the viewer framework. It is designed to be
* instantiated with a pre-existing Grid control and configured with a domain-specific content
* provider, label provider, element filter (optional), and element sorter (optional).
*
* Content providers for grid table viewers must not implement the {@code
* ITreeContentProvider} interface. Instead a {@link GridTreeViewer} should be used.
*
*
* @author Unknown...
* @author Mirko Paturzo Mirko modified improve performace and reduce used
* memory fix memory leak and slow disposed object
*/
@SuppressWarnings("restriction")
public class GridTableViewer extends AbstractTableViewer {
/** This viewer's grid control. */
private final Grid grid;
private GridViewerRow cachedRow;
private CellLabelProvider rowHeaderLabelProvider;
/**
* If true, this grid viewer will ensure that the grid's rows / GridItems are always sized to
* their preferred height.
*/
private boolean autoPreferredHeight = false;
/**
* Creates a grid viewer on a newly-created grid control under the given parent. The grid control
* is created using the SWT style bits MULTI, H_SCROLL, V_SCROLL,
and
* BORDER
. The viewer has no input, no content provider, a default label provider, no
* sorter, and no filters.
*
* @param parent the parent control
*/
public GridTableViewer( Composite parent ) {
this( parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER );
}
// /**
// * Creates a grid viewer on a newly-created grid control under the given parent. The grid control
// * is created using the given SWT style bits. The viewer has no input, no content provider, a
// * default label provider, no sorter, and no filters.
// *
// * @param dataVisualizer
// * @param parent the parent control
// * @param style the SWT style bits used to create the grid.
// */
// public GridTableViewer( DataVisualizer dataVisualizer, Composite parent, int style ) {
// this( new Grid( dataVisualizer, parent, style ) );
// }
//
// /**
// * Creates a grid viewer on a newly-created grid control under the given parent. The grid control
// * is created using the SWT style bits MULTI, H_SCROLL, V_SCROLL,
and
// * BORDER
. The viewer has no input, no content provider, a default label provider, no
// * sorter, and no filters.
// *
// * @param dataVisualizer
// * @param parent the parent control
// */
// public GridTableViewer( DataVisualizer dataVisualizer, Composite parent ) {
// this( dataVisualizer, parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER );
// }
/**
* Creates a grid viewer on a newly-created grid control under the given parent. The grid control
* is created using the given SWT style bits. The viewer has no input, no content provider, a
* default label provider, no sorter, and no filters.
*
* @param parent the parent control
* @param style the SWT style bits used to create the grid.
*/
public GridTableViewer( Composite parent, int style ) {
this( new Grid( parent, style ) );
}
/**
* Creates a grid viewer on the given grid control. The viewer has no input, no content provider,
* a default label provider, no sorter, and no filters.
*
* @param grid the grid control
*/
public GridTableViewer( Grid grid ) {
this.grid = grid;
hookControl( grid );
}
/**
* Returns the underlying Grid Control.
*
* @return grid control.
*/
public Grid getGrid() {
return grid;
}
/** {@inheritDoc} */
@Override
protected ViewerRow internalCreateNewRowPart( int style, int rowIndex ) {
GridItem item;
if( rowIndex >= 0 ) {
item = new GridItem( grid, style, rowIndex );
} else {
item = new GridItem( grid, style );
}
return getViewerRowFromItem( item );
}
/** {@inheritDoc} */
@Override
protected ColumnViewerEditor createViewerEditor() {
return new GridViewerEditor( this,
new ColumnViewerEditorActivationStrategy( this ),
ColumnViewerEditor.DEFAULT );
}
/** {@inheritDoc} */
@Override
protected void doClear( int index ) {
// grid.getDataVisualizer().clearRow( grid.getItem( index ) );
}
/** {@inheritDoc} */
@Override
protected void doClearAll() {
// grid.getDataVisualizer().clearAll();
}
/**
* @see org.eclipse.jface.viewers.StructuredViewer#refresh()
*/
@Override
public void refresh() {
try {
super.refresh();
} finally {
// [RAP] refreshData missing
// grid.refreshData();
grid.getAdapter( IGridAdapter.class ).doRedraw();
}
}
/** {@inheritDoc} */
@Override
protected void doSetItemCount( int count ) {
grid.setItemCount( count );
}
/** {@inheritDoc} */
@Override
protected void doDeselectAll() {
grid.deselectAll();
}
/** {@inheritDoc} */
@Override
protected Widget doGetColumn( int index ) {
return grid.getColumn( index );
}
/** {@inheritDoc} */
@Override
protected int doGetColumnCount() {
return grid.getColumnCount();
}
/** {@inheritDoc} */
@Override
protected Item doGetItem( int index ) {
return grid.getItem( index );
}
/** {@inheritDoc} */
@Override
protected int doGetItemCount() {
return grid.getItemCount();
}
/** {@inheritDoc} */
@Override
protected Item[] doGetItems() {
return grid.getItems();
}
/** {@inheritDoc} */
@Override
protected Item[] doGetSelection() {
return grid.getSelection();
}
/** {@inheritDoc} */
@Override
protected int[] doGetSelectionIndices() {
return grid.getSelectionIndices();
}
/** {@inheritDoc} */
@Override
protected int doIndexOf( Item item ) {
// return ( ( GridItem )item ).getRowIndex();
return grid.indexOf( ( GridItem )item );
}
/** {@inheritDoc} */
@Override
protected void doRemove( int[] indices ) {
grid.remove( indices );
}
/** {@inheritDoc} */
@Override
protected void doRemove( int start, int end ) {
grid.remove( start, end );
}
/** {@inheritDoc} */
@Override
protected void doRemoveAll() {
grid.removeAll();
}
/**
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.AbstractTableViewer#handleDispose(org.eclipse.swt.events.DisposeEvent)
* fix crossed reference for GC
*/
@Override
protected void handleDispose( final DisposeEvent event ) {
super.handleDispose( event );
cachedRow = null;
rowHeaderLabelProvider = null;
getGrid().setRedraw( false );
// getGrid().disposeAllItems();
// getGrid().clearItems();
}
/** {@inheritDoc} */
@Override
protected void doSetSelection( Item[] items ) {
GridItem[] items2 = new GridItem[ items.length ];
for( int i = 0; i < items.length; i++ ) {
items2[ i ] = ( GridItem )items[ i ];
}
grid.setSelection( items2 );
grid.showSelection();
}
/** {@inheritDoc} */
@Override
protected void doSetSelection( int[] indices ) {
grid.setSelection( indices );
}
/** {@inheritDoc} */
@Override
protected void doShowItem( Item item ) {
grid.showItem( ( GridItem )item );
}
/** {@inheritDoc} */
@Override
protected void doShowSelection() {
grid.showSelection();
}
/** {@inheritDoc} */
@Override
protected Item getItemAt( Point point ) {
return grid.getItem( point );
}
/** {@inheritDoc} */
@Override
public Control getControl() {
return grid;
}
/** {@inheritDoc} */
@Override
protected ViewerRow getViewerRowFromItem( Widget item ) {
if( cachedRow == null ) {
cachedRow = new GridViewerRow( ( GridItem )item );
} else {
cachedRow.setItem( ( GridItem )item );
}
return cachedRow;
}
/**
* {@inheritDoc}
*/
@Override
protected void doResetItem( Item item ) {
GridItem gridItem = ( GridItem )item;
int columnCount = Math.max( 1, grid.getColumnCount() );
for( int i = 0; i < columnCount; i++ ) {
gridItem.setText( i, "" ); //$NON-NLS-1$
gridItem.setImage( null );
}
}
/**
* {@inheritDoc}
*/
@Override
protected void doSelect( int[] indices ) {
grid.select( indices );
}
/**
* When set to true, this grid viewer will ensure that each of the grid's items is always
* automatically sized to its preferred height. The default is false.
*
* Since this mechanism usually leads to a grid with rows of different heights and thus to a grid
* with decreased performance, it should only be applied if that is intended. To set the height of
* all items to a specific value, use {@link Grid#setItemHeight(int)} instead.
*
* When a column with activated word wrapping is resized by dragging the column resizer, the items
* are only auto-resized properly if you use {@link GridViewerColumn} to create the columns.
*
* When this method is called, existing rows are not resized to their preferred height. Therefore
* it is suggested that this method be called before rows are populated (i.e. before setInput).
*
* @param autoPreferredHeight
*/
public void setAutoPreferredHeight( boolean autoPreferredHeight ) {
this.autoPreferredHeight = autoPreferredHeight;
}
/**
* @return true if this grid viewer sizes its rows to their preferred height
* @see #setAutoPreferredHeight(boolean)
*/
public boolean getAutoPreferredHeight() {
return autoPreferredHeight;
}
/** {@inheritDoc} */
@Override
protected void doUpdateItem( Widget widget, Object element, boolean fullMap ) {
super.doUpdateItem( widget, element, fullMap );
updateRowHeader( widget );
if( autoPreferredHeight && !widget.isDisposed() ) {
( ( GridItem )widget ).pack();
}
}
private void updateRowHeader( Widget widget ) {
if( rowHeaderLabelProvider != null ) {
ViewerCell cell = getViewerRowFromItem( widget ).getCell( Integer.MAX_VALUE );
rowHeaderLabelProvider.update( cell );
}
}
/**
* Label provider used by calculate the row header text
*
* @param rowHeaderLabelProvider the provider
*/
public void setRowHeaderLabelProvider( CellLabelProvider rowHeaderLabelProvider ) {
this.rowHeaderLabelProvider = rowHeaderLabelProvider;
}
/**
* Refresh row headers only
*
* @param element the element to start or null
if all rows should be refreshed
*/
public void refreshRowHeaders( Object element ) {
boolean refresh = element == null;
for( int i = 0; i < getGrid().getItemCount(); i++ ) {
if( refresh || element.equals( getGrid().getItem( i ).getData() ) ) {
refresh = true;
updateRowHeader( getGrid().getItem( i ) );
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void editElement( Object element, int column ) {
try {
getControl().setRedraw( false );
Widget item = findItem( element );
if( item != null ) {
ViewerRow row = getViewerRowFromItem( item );
if( row != null ) {
ViewerCell cell = row.getCell( column );
if( cell != null ) {
triggerEditorActivationEvent( new ColumnViewerEditorActivationEvent( cell ) );
}
}
}
} finally {
getControl().setRedraw( true );
}
}
/**
* {@inheritDoc}
*/
@SuppressWarnings( {
"rawtypes",
"unchecked"
} )
@Override
protected void setSelectionToWidget( ISelection selection, boolean reveal ) {
if( !grid.isCellSelectionEnabled() || !( selection instanceof CellSelection ) ) {
super.setSelectionToWidget( selection, reveal );
if( selection instanceof SelectionWithFocusRow ) {
Object el = ( ( SelectionWithFocusRow )selection ).getFocusElement();
if( el != null ) {
for( int i = 0; i < grid.getItemCount(); i++ ) {
GridItem item = grid.getItem( i );
if( item.getData() == el
|| el.equals( item.getData() )
|| ( getComparer() != null && getComparer().equals( item.getData(), el ) ) )
{
grid.setFocusItem( item );
break;
}
}
}
}
} else {
CellSelection cellSelection = ( CellSelection )selection;
List l = cellSelection.toList();
ArrayList pts = new ArrayList();
for( int i = 0; i < grid.getItemCount(); i++ ) {
Iterator it = l.iterator();
Object itemObject = grid.getItem( i ).getData();
while( it.hasNext() ) {
Object checkObject = it.next();
if( itemObject == checkObject
|| ( getComparer() != null && getComparer().equals( itemObject, checkObject ) ) )
{
Iterator idxIt = cellSelection.getIndices( checkObject ).iterator();
while( idxIt.hasNext() ) {
Integer idx = ( Integer )idxIt.next();
pts.add( new Point( idx.intValue(), i ) );
}
}
}
}
Point[] tmp = new Point[ pts.size() ];
pts.toArray( tmp );
grid.setCellSelection( tmp );
if( cellSelection.getFocusElement() != null ) {
Object el = cellSelection.getFocusElement();
for( int i = 0; i < grid.getItemCount(); i++ ) {
GridItem item = grid.getItem( i );
if( item.getData() == el
|| item.getData().equals( el )
|| ( getComparer() != null && getComparer().equals( item.getData(), el ) ) )
{
grid.setFocusItem( item );
break;
}
}
}
}
}
/**
* {@inheritDoc}
*/
@Override
public ISelection getSelection() {
if( !grid.isCellSelectionEnabled() ) {
IStructuredSelection selection = ( IStructuredSelection )super.getSelection();
Object el = null;
if( grid.getFocusItem() != null && !grid.getFocusItem().isDisposed() ) {
el = grid.getFocusItem().getData();
}
return new SelectionWithFocusRow( selection.toList(), el, getComparer() );
} else {
return createCellSelection();
}
}
@SuppressWarnings( {
"unchecked",
"rawtypes"
} )
private CellSelection createCellSelection() {
Point[] ps = grid.getCellSelection();
Arrays.sort( ps, new Comparator() {
@Override
public int compare( Object arg0, Object arg1 ) {
Point a = ( Point )arg0;
Point b = ( Point )arg1;
int rv = a.y - b.y;
if( rv == 0 ) {
rv = a.x - b.x;
}
return rv;
}
} );
ArrayList objectList = new ArrayList();
ArrayList indiceLists = new ArrayList();
ArrayList indiceList = new ArrayList();
int curLine = -1;
for( int i = 0; i < ps.length; i++ ) {
if( curLine != ps[ i ].y ) {
curLine = ps[ i ].y;
indiceList = new ArrayList();
indiceLists.add( indiceList );
objectList.add( grid.getItem( curLine ).getData() );
}
indiceList.add( new Integer( ps[ i ].x ) );
}
Object focusElement = null;
if( grid.getFocusItem() != null && !grid.getFocusItem().isDisposed() ) {
focusElement = grid.getFocusItem().getData();
}
return new CellSelection( objectList, indiceLists, focusElement, getComparer() );
}
}