All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.nebula.widgets.grid.Grid Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2012, 2023 EclipseSource 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:
 *    EclipseSource - initial API and implementation
 ******************************************************************************/
package org.eclipse.nebula.widgets.grid;

import static org.eclipse.swt.internal.widgets.MarkupUtil.checkMarkupPrecondition;
import static org.eclipse.swt.internal.widgets.MarkupUtil.isMarkupEnabledFor;
import static org.eclipse.swt.internal.widgets.MarkupUtil.MarkupTarget.TEXT;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.nebula.widgets.grid.internal.IGridAdapter;
import org.eclipse.nebula.widgets.grid.internal.IScrollBarProxy;
import org.eclipse.nebula.widgets.grid.internal.NullScrollBarProxy;
import org.eclipse.nebula.widgets.grid.internal.ScrollBarProxyAdapter;
import org.eclipse.nebula.widgets.grid.internal.gridkit.GridLCA;
import org.eclipse.nebula.widgets.grid.internal.gridkit.GridThemeAdapter;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.internal.lifecycle.WidgetLCA;
import org.eclipse.rap.rwt.internal.textsize.TextSizeUtil;
import org.eclipse.rap.rwt.internal.theme.Size;
import org.eclipse.rap.rwt.internal.theme.ThemeAdapter;
import org.eclipse.rap.rwt.template.Template;
import org.eclipse.rap.rwt.theme.BoxDimensions;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.TreeListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.internal.SerializableCompatibility;
import org.eclipse.swt.internal.widgets.ICellToolTipAdapter;
import org.eclipse.swt.internal.widgets.ICellToolTipProvider;
import org.eclipse.swt.internal.widgets.ItemProvider;
import org.eclipse.swt.internal.widgets.WidgetTreeVisitor;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.TypedListener;


/**
 * Instances of this class implement a selectable user interface object that
 * displays a list of images and strings and issue notification when selected.
 * 

* The item children that may be added to instances of this class must be of * type {@code GridItem}. *

*
*
Styles:
*
SWT.SINGLE, SWT.MULTI, SWT.NO_FOCUS, SWT.CHECK, SWT.VIRTUAL
*
Events:
*
Selection, DefaultSelection
*
*/ @SuppressWarnings("restriction") public class Grid extends Composite { private static final int MIN_ITEM_HEIGHT = 16; private static final int GRID_WIDTH = 1; private List items = new ArrayList(); private List rootItems = new ArrayList(); private List selectedItems = new ArrayList(); private List selectedCells = new ArrayList(); private List columns = new ArrayList(); private List displayOrderedColumns = new ArrayList(); private List columnGroups = new ArrayList(); private GridItem focusItem; private GridColumn focusColumn; private GridColumn treeColumn; private GridColumn rowHeadersColumn; private boolean isInternalColumn; private boolean isTree; private boolean disposing; private boolean columnHeadersVisible; private boolean columnFootersVisible; private boolean linesVisible = true; private boolean autoHeight; private int currentVisibleItems; private int selectionType = SWT.SINGLE; private boolean selectionEnabled = true; private boolean cellSelectionEnabled; private int customItemHeight = -1; private int groupHeaderHeight; private Point itemImageSize; private Listener resizeListener; private Listener disposeListener; private boolean isTemporaryResize; private IScrollBarProxy vScroll; private IScrollBarProxy hScroll; private boolean scrollValuesObsolete; private boolean defaultRowHeadersTextObsolete; private int topIndex = -1; private int bottomIndex = -1; private boolean bottomIndexShownCompletely; private final IGridAdapter gridAdapter; boolean hasDifferingHeights; private boolean hasSpanning; LayoutCache layoutCache; /** * Constructs a new instance of this class given its parent and a style * value describing its behavior and appearance. *

* * @param parent a composite control which will be the parent of the new * instance (cannot be null) * @param style the style of control to construct * @throws IllegalArgumentException *

    *
  • ERROR_NULL_ARGUMENT - if the parent is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the parent
  • *
* @see SWT#SINGLE * @see SWT#MULTI */ public Grid( Composite parent, int style ) { super( parent, checkStyle( style ) ); if( ( style & SWT.MULTI ) != 0 ) { selectionType = SWT.MULTI; } if( getVerticalBar() != null ) { getVerticalBar().setVisible( false ); vScroll = new ScrollBarProxyAdapter( getVerticalBar() ); } else { vScroll = new NullScrollBarProxy(); } if( getHorizontalBar() != null ) { getHorizontalBar().setVisible( false ); hScroll = new ScrollBarProxyAdapter( getHorizontalBar() ); } else { hScroll = new NullScrollBarProxy(); } gridAdapter = new GridAdapter(); layoutCache = new LayoutCache(); initListeners(); createRowHeadersColumn(); } /** * {@inheritDoc} */ @Override public Point computeSize( int wHint, int hHint, boolean changed ) { checkWidget(); Point rreferredSize = null; if( wHint == SWT.DEFAULT || hHint == SWT.DEFAULT ) { rreferredSize = getTableSize(); rreferredSize.x += 2 * getBorderWidth(); rreferredSize.y += 2 * getBorderWidth(); } int width = 0; int height = 0; if( wHint == SWT.DEFAULT ) { width += rreferredSize.x; if( getVerticalBar() != null ) { width += getVerticalBar().getSize().x; } } else { width = wHint; } if( hHint == SWT.DEFAULT ) { height += rreferredSize.y; if( getHorizontalBar() != null ) { height += getHorizontalBar().getSize().y; } } else { height = hHint; } return new Point( width, height ); } /** * Adds the listener to the collection of listeners who will be notified * when the receiver's selection changes, by sending it one of the messages * defined in the {@code SelectionListener} interface. *

* Cell selection events may have Event.detail = SWT.DRAG when the * user is drag selecting multiple cells. A follow up selection event will be generated * when the drag is complete. * * @param listener the listener which should be notified * @throws IllegalArgumentException *

    *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void addSelectionListener( SelectionListener listener ) { checkWidget(); if( listener == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } TypedListener typedListener = new TypedListener( listener ); addListener( SWT.Selection, typedListener ); addListener( SWT.DefaultSelection, typedListener ); } /** * Removes the listener from the collection of listeners who will be * notified when the receiver's selection changes. * * @param listener the listener which should no longer be notified * @see SelectionListener * @see #addSelectionListener(SelectionListener) * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void removeSelectionListener( SelectionListener listener ) { checkWidget(); if( listener == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } removeListener( SWT.Selection, listener ); removeListener( SWT.DefaultSelection, listener ); } /** * Adds the listener to the collection of listeners who will be notified * when the receiver's items changes, by sending it one of the messages * defined in the {@code TreeListener} interface. * * @param listener the listener which should be notified * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the listener is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
* @see TreeListener * @see #removeTreeListener * @see org.eclipse.swt.events.TreeEvent */ public void addTreeListener( TreeListener listener ) { checkWidget(); if( listener == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } TypedListener typedListener = new TypedListener( listener ); addListener( SWT.Expand, typedListener ); addListener( SWT.Collapse, typedListener ); } /** * Removes the listener from the collection of listeners who will be * notified when the receiver's items changes. * * @param listener the listener which should no longer be notified * @see TreeListener * @see #addTreeListener(TreeListener) * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void removeTreeListener( TreeListener listener ) { checkWidget(); if( listener == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } removeListener( SWT.Expand, listener ); removeListener( SWT.Collapse, listener ); } /** * Sets the number of items contained in the receiver. * * @param count the number of items * * @exception org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
*/ public void setItemCount( int count ) { checkWidget(); int itemCount = Math.max( 0, count ); if( itemCount < items.size() ) { selectedCells.clear(); } while( itemCount < items.size() ) { int flatIndex = items.size() - 1; items.get( flatIndex ).dispose( flatIndex ); } while( itemCount > items.size() ) { new GridItem( this, null, SWT.NONE, -1 ); } redraw(); } /** * Returns the number of items contained in the receiver. * * @return the number of items * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int getItemCount() { checkWidget(); return items.size(); } /** * Returns a (possibly empty) array of {@code GridItem}s which are the * items in the receiver. *

* Note: This is not the actual structure used by the receiver to maintain * its list of items, so modifying the array will not affect the receiver. *

* * @return the items in the receiver * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridItem[] getItems() { checkWidget(); return items.toArray( new GridItem[ items.size() ] ); } /** * 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 * @throws IllegalArgumentException *
    *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the * list minus 1 (inclusive)
  • * *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridItem getItem( int index ) { checkWidget(); if( index < 0 || index >= items.size() ) { SWT.error( SWT.ERROR_INVALID_RANGE ); } return items.get( index ); } /** * Returns the item at the given point in the receiver or null if no such * item exists. The point is in the coordinate system of the receiver. * * @param point the point used to locate the item * @return the item at the given point * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the point is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridItem getItem( Point point ) { checkWidget(); if( point == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } GridItem result = null; if( point.x >= 0 && point.x <= getClientArea().width ) { Point p = new Point( point.x, point.y ); int y = 0; if( columnHeadersVisible ) { y += getHeaderHeight(); } if( p.y > y ) { int row = getTopIndex(); while( row < items.size() && y <= getClientArea().height && result == null ) { GridItem currentItem = items.get( row ); if( currentItem.isVisible() ) { int currentItemHeight = currentItem.getHeight(); if( p.y >= y && p.y < y + currentItemHeight ) { result = currentItem; } y += currentItemHeight; } row++; } } } return result; } /** * 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 * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the item is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int indexOf( GridItem item ) { checkWidget(); if( item == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } return item.getParent() == this ? items.indexOf( item ) : -1; } /** * Returns the number of root items contained in the receiver. * * @return the number of items * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int getRootItemCount() { checkWidget(); return rootItems.size(); } /** * Returns a (possibly empty) array of {@code GridItem}s which are * the root items in the receiver. *

* Note: This is not the actual structure used by the receiver to maintain * its list of items, so modifying the array will not affect the receiver. *

* * @return the root items in the receiver * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridItem[] getRootItems() { checkWidget(); return rootItems.toArray( new GridItem[ rootItems.size() ] ); } /** * TODO: JavaDoc * @param index * @return the root item */ public GridItem getRootItem( int index ) { checkWidget(); if( index < 0 || index >= rootItems.size() ) { SWT.error( SWT.ERROR_INVALID_RANGE ); } return rootItems.get( index ); } /** * Returns the next visible item in the table. * * @param item item * @return next visible item or null * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridItem getNextVisibleItem( GridItem item ) { checkWidget(); GridItem result = null; int index = items.indexOf( item ); if( index != items.size() - 1 ) { result = items.get( index + 1 ); while( result != null && !result.isVisible() ) { index++; if( index != items.size() - 1 ) { result = items.get( index + 1 ); } else { result = null; } } } return result; } /** * Returns the previous visible item in the table. Passing null for the item * will return the last visible item in the table. * * @param item item or null * @return previous visible item or if item==null last visible item * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridItem getPreviousVisibleItem( GridItem item ) { checkWidget(); GridItem result = null; int index = 0; if( item == null ) { index = items.size(); } else { index = items.indexOf( item ); } if( index > 0 ) { result = items.get( index - 1 ); while( result != null && !result.isVisible() ) { index--; if( index > 0 ) { result = items.get( index - 1 ); } else { result = null; } } } return result; } /** * Returns the number of columns contained in the receiver. If no * {@code GridColumn}s were created by the programmer, this value is * zero, despite the fact that visually, one column of items may be visible. * This occurs when the programmer uses the table like a list, adding items * but never creating a column. * * @return the number of columns * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int getColumnCount() { checkWidget(); return columns.size(); } /** * Returns an array of {@code GridColumn}s which are the columns in the * receiver. If no {@code GridColumn}s were created by the programmer, * the array is empty, despite the fact that visually, one column of items * may be visible. This occurs when the programmer uses the table like a * list, adding items but never creating a column. *

* Note: This is not the actual structure used by the receiver to maintain * its list of items, so modifying the array will not affect the receiver. *

* * @return the items in the receiver * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridColumn[] getColumns() { checkWidget(); return columns.toArray( new GridColumn[ columns.size() ] ); } /** * Returns the column at the given, zero-relative index in the receiver. * Throws an exception if the index is out of range. If no * {@code GridColumn}s were created by the programmer, this method will * throw {@code 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 * @throws IllegalArgumentException *
    *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number * of elements in the list minus 1 (inclusive)
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridColumn getColumn( int index ) { checkWidget(); if( index < 0 || index > getColumnCount() - 1 ) { SWT.error( SWT.ERROR_INVALID_RANGE ); } return columns.get( index ); } /** * Returns the column at the given point in the receiver or null if no such * column exists. The point is in the coordinate system of the receiver. * * @param point the point used to locate the column * @return the column at the given point * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the point is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridColumn getColumn( Point point ) { checkWidget(); if( point == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } GridColumn overThis = null; int x2 = 0; if ( isRowHeaderVisible() ) { if ( point.x <= rowHeadersColumn.getWidth() ) { return null; } x2 += rowHeadersColumn.getWidth(); } x2 -= hScroll.getSelection(); for( GridColumn column : displayOrderedColumns ) { if( !column.isVisible() ) { continue; } if( point.x >= x2 && point.x < x2 + column.getWidth() ) { overThis = column; break; } x2 += column.getWidth(); } if( overThis == null ) { return null; } if( hasSpanning ) { // special logic for column spanning GridItem item = getItem( point ); if( item != null ) { int displayColIndex = displayOrderedColumns.indexOf( overThis ); // track back all previous columns and check their spanning for( int i = 0; i < displayColIndex; i++ ) { if( !displayOrderedColumns.get( i ).isVisible() ) { continue; } int colIndex = indexOf( displayOrderedColumns.get( i ) ); int span = item.getColumnSpan( colIndex ); if( i + span >= displayColIndex ) { overThis = displayOrderedColumns.get( i ); break; } } } } return overThis; } /** * Searches the receiver's list starting at the first column (index 0) until * a column is found that is equal to the argument, and returns the index of * that column. If no column is found, returns -1. * * @param column the search column * @return the index of the column * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the column is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int indexOf( GridColumn column ) { checkWidget(); if( column == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } return column.getParent() == this ? columns.indexOf( column ): -1; } /** * Sets the order that the items in the receiver should be displayed in to * the given argument which is described in terms of the zero-relative * ordering of when the items were added. * * @param order the new order to display the items * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS -if not called from the thread that * created the receiver
  • *
* @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the item order is null
  • *
  • ERROR_INVALID_ARGUMENT - if the order is not the same length as the * number of items, or if an item is listed twice, or if the order splits a * column group
  • *
*/ public void setColumnOrder( int[] order ) { checkWidget(); if( order == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } if( order.length != displayOrderedColumns.size() ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } boolean[] seen = new boolean[ displayOrderedColumns.size() ]; for( int i = 0; i < order.length; i++ ) { if( order[ i ] < 0 || order[ i ] >= displayOrderedColumns.size() ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } if( seen[ order[ i ] ] ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } seen[ order[ i ] ] = true; } if( columnGroups.size() != 0 ) { GridColumnGroup currentGroup = null; int columnsInGroup = 0; for( int i = 0; i < order.length; i++ ) { GridColumn column = getColumn( order[ i ] ); if( currentGroup != null ) { if( column.getColumnGroup() != currentGroup && columnsInGroup > 0 ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } else { columnsInGroup--; if( columnsInGroup <= 0 ) { currentGroup = null; } } } else if( column.getColumnGroup() != null ) { currentGroup = column.getColumnGroup(); columnsInGroup = currentGroup.getColumns().length - 1; } } } GridColumn[] columns = getColumns(); int[] oldOrder = getColumnOrder(); displayOrderedColumns.clear(); for( int i = 0; i < order.length; i++ ) { displayOrderedColumns.add( columns[ order[ i ] ] ); } for( int i = 0; i < order.length; i++ ) { if( oldOrder[ i ] != order[ i ] ) { columns[ order[ i ] ].fireMoved(); } } updatePrimaryCheckColumn(); } /** * Returns an array of zero-relative integers that map the creation order of * the receiver's items to the order in which they are currently being * displayed. *

* Specifically, the indices of the returned array represent the current * visual order of the items, and the contents of the array represent the * creation order of the items. *

*

* Note: This is not the actual structure used by the receiver to maintain * its list of items, so modifying the array will not affect the receiver. *

* * @return the current visual order of the receiver's items * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int[] getColumnOrder() { checkWidget(); int[] result = new int[ columns.size() ]; for( int i = 0; i < result.length; i++ ) { GridColumn column = displayOrderedColumns.get( i ); result[ i ] = columns.indexOf( column ); } return result; } /** * Returns the next visible column in the table. * * @param column column * @return next visible column or null * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridColumn getNextVisibleColumn( GridColumn column ) { checkWidget(); GridColumn result = null; int index = displayOrderedColumns.indexOf( column ); if( index != displayOrderedColumns.size() - 1 ) { result = displayOrderedColumns.get( index + 1 ); while( result != null && !result.isVisible() ) { index++; if( index != displayOrderedColumns.size() - 1 ) { result = displayOrderedColumns.get( index + 1 ); } else { result = null; } } } return result; } /** * Returns the previous visible column in the table. * * @param column column * @return previous visible column or null * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridColumn getPreviousVisibleColumn( GridColumn column ) { checkWidget(); GridColumn result = null; int index = 0; if( column == null ) { index = displayOrderedColumns.size(); } else { index = displayOrderedColumns.indexOf( column ); } if( index > 0 ) { result = displayOrderedColumns.get( index - 1 ); while( result != null && !result.isVisible() ) { index--; if( index > 0 ) { result = displayOrderedColumns.get( index - 1 ); } else { result = null; } } } return result; } /** * Returns the number of column groups contained in the receiver. * * @return the number of column groups * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int getColumnGroupCount() { checkWidget(); return columnGroups.size(); } /** * Returns an array of {@code GridColumnGroup}s which are the column groups in the * receiver. *

* Note: This is not the actual structure used by the receiver to maintain * its list of items, so modifying the array will not affect the receiver. *

* * @return the column groups in the receiver * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridColumnGroup[] getColumnGroups() { checkWidget(); return columnGroups.toArray( new GridColumnGroup[ columnGroups.size() ] ); } /** * Returns the column group 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 column group to return * @return the column group at the given index * @throws IllegalArgumentException *
    *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number * of elements in the list minus 1 (inclusive)
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridColumnGroup getColumnGroup( int index ) { checkWidget(); if( index < 0 || index >= columnGroups.size() ) { SWT.error( SWT.ERROR_INVALID_RANGE ); } return columnGroups.get( index ); } /** * 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 SWT.VIRTUAL style, * these attributes are requested again as needed. * * @param index the index of the item to clear * @param allChildren true if all child items of the indexed item should be * cleared recursively, and false otherwise * * @exception IllegalArgumentException
    *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
  • *
* @exception org.eclipse.swt.SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
* * @see SWT#VIRTUAL * @see SWT#SetData */ public void clear( int index, boolean allChildren ) { checkWidget(); if( index < 0 || index >= items.size() ) { SWT.error( SWT.ERROR_INVALID_RANGE ); } items.get( index ).clear( allChildren ); redraw(); } /** * Clears the items in the receiver which are between the given * zero-relative start and end indices (inclusive). The text, icon * and other attributes of the items are set to their default values. * If the table was created with the SWT.VIRTUAL style, * these attributes are requested again as needed. * * @param start the start index of the item to clear * @param end the end index of the item to clear * @param allChildren true if all child items of the range of items should be * cleared recursively, and false otherwise * * @exception IllegalArgumentException
    *
  • ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)
  • *
* @exception org.eclipse.swt.SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
* * @see SWT#VIRTUAL * @see SWT#SetData */ public void clear( int start, int end, boolean allChildren ) { checkWidget(); if( start <= end ) { if( !( 0 <= start && start <= end && end < items.size() ) ) { SWT.error( SWT.ERROR_INVALID_RANGE ); } for( int i = start; i <= end; i++ ) { items.get( i ).clear( allChildren ); } redraw(); } } /** * Clears the items at the given zero-relative indices 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 SWT.VIRTUAL style, * these attributes are requested again as needed. * * @param indices the array of indices of the items * @param allChildren true if all child items of the indexed items should be * cleared recursively, and false otherwise * * @exception IllegalArgumentException
    *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)
  • *
  • ERROR_NULL_ARGUMENT - if the indices array is null
  • *
* @exception org.eclipse.swt.SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
* * @see SWT#VIRTUAL * @see SWT#SetData */ public void clear( int[] indices, boolean allChildren ) { checkWidget(); if( indices == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } if( indices.length > 0 ) { for( int i = 0; i < indices.length; i++ ) { if( !isValidItemIndex( indices[ i ] ) ) { SWT.error( SWT.ERROR_INVALID_RANGE ); } } for( int i = 0; i < indices.length; i++ ) { items.get( indices[ i ] ).clear( allChildren ); } redraw(); } } /** * 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 SWT.VIRTUAL style, these * attributes are requested again as needed. * * @param allChildren true if all child items of each item should be * cleared recursively, and false otherwise * * @exception org.eclipse.swt.SWTException
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
* * @see SWT#VIRTUAL * @see SWT#SetData */ public void clearAll( boolean allChildren ) { checkWidget(); int itemsCount = items.size(); if( itemsCount > 0 ) { // [if] Note: The parameter allChildren has no effect as all items (not only rootItems) // are cleared clear( 0, itemsCount - 1, allChildren ); itemImageSize = null; setCellToolTipsEnabled( false ); layoutCache.invalidateItemHeight(); } } /** * Enables selection highlighting if the argument is true. * * @param selectionEnabled the selection enabled state * * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void setSelectionEnabled( boolean selectionEnabled ) { checkWidget(); if( !selectionEnabled ) { selectedItems.clear(); } this.selectionEnabled = selectionEnabled; } /** * Returns true if selection is enabled, false otherwise. * * @return the selection enabled state * * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public boolean getSelectionEnabled() { checkWidget(); return selectionEnabled; } /** * Returns true if the cells are selectable in the reciever. * * @return cell selection enablement status. * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the * receiver
  • *
* * @since 3.13 */ public boolean getCellSelectionEnabled() { checkWidget(); return cellSelectionEnabled; } /** * Sets whether cells are selectable in the receiver. *

* Note: Using markup in the cell text will require data-cell-index attribute to be added * to the HTML element that points to the cell column index. Row header column (visible or not) * always has index 0. *

* * @param cellSelection the cellSelection to set * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the * receiver
  • *
* * @since 3.13 */ public void setCellSelectionEnabled( boolean cellSelection ) { checkWidget(); if( cellSelection ) { if( ( getStyle() & SWT.SINGLE ) == 0 ) { // To keep compatibility, one can selected multiple cells selectionType = SWT.MULTI; } selectedItems.clear(); } else { selectedCells.clear(); } cellSelectionEnabled = cellSelection; } /** * Returns true if the cells are selectable in the reciever. * * @return cell selection enablement status. * * @since 3.13 */ public boolean isCellSelectionEnabled() { return cellSelectionEnabled; } /** * Selects the item at the given zero-relative index in the receiver. If the * item at the index was already selected, it remains selected. Indices that * are out of range are ignored. *

* If cell selection is enabled, selects all cells at the given index. * * @param index the index of the item to select * @throws org.eclipse.swt.SWTException *

    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void select( int index ) { checkWidget(); if( selectionEnabled && isValidItemIndex( index ) ) { if( !cellSelectionEnabled && selectionType == SWT.SINGLE ) { selectedItems.clear(); } internalSelect( index ); } } /** * Selects the items in the range specified by the given zero-relative * indices in the receiver. The range of indices is inclusive. The current * selection is not cleared before the new items are selected. *

* If an item in the given range is not selected, it is selected. If an item * in the given range was already selected, it remains selected. Indices * that are out of range are ignored and no items will be selected if start * is greater than end. If the receiver is single-select and there is more * than one item in the given range, then all indices are ignored. *

* If cell selection is enabled, all cells within the given range are selected. * * @param start the start of the range * @param end the end of the range * @throws org.eclipse.swt.SWTException *

    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
* @see Grid#setSelection(int,int) */ public void select( int start, int end ) { checkWidget(); if( selectionEnabled && !( selectionType == SWT.SINGLE && start != end ) ) { if( !cellSelectionEnabled && selectionType == SWT.SINGLE ) { selectedItems.clear(); } for( int index = Math.max( 0, start ); index <= Math.min( items.size() - 1, end ); index++ ) { internalSelect( 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. *

* 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. *

* If cell selection is enabled, all cells within the given indices are * selected. * * @param indices the array of indices for the items to select * @throws IllegalArgumentException *

    *
  • ERROR_NULL_ARGUMENT - if the array of indices is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
* @see Grid#setSelection(int[]) */ public void select( int[] indices ) { checkWidget(); if( indices == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } if( selectionEnabled && !( selectionType == SWT.SINGLE && indices.length > 1 ) ) { if( !cellSelectionEnabled && selectionType == SWT.SINGLE ) { selectedItems.clear(); } for( int i = 0; i < indices.length; i++ ) { internalSelect( indices[ i ] ); } } } /** * Selects all of the items in the receiver. *

* If the receiver is single-select, do nothing. If cell selection is enabled, * all cells are selected. * * @throws org.eclipse.swt.SWTException *

    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void selectAll() { checkWidget(); if( selectionEnabled && selectionType != SWT.SINGLE ) { if( cellSelectionEnabled ) { selectAllCells(); } else { selectedItems.clear(); selectedItems.addAll( items ); } } } /** * Selects the given cell. Invalid cells are ignored. * * @param cell * point whose x value is a column index and y value is an item * index * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the item is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public void selectCell( Point cell ) { checkWidget(); if( cellSelectionEnabled ) { if( cell == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } addToCellSelection( cell ); } } /** * Selects the given cells. Invalid cells are ignored. * * @param cells * an arry of points whose x value is a column index and y value is * an item index * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the set of cells or an individual * cell is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public void selectCells( Point[] cells ) { checkWidget(); if( cellSelectionEnabled ) { if( cells == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } for( Point cell : cells ) { if( cell == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } } for( Point cell : cells ) { addToCellSelection( cell ); } } } /** * Selects all cells in the receiver. * * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public void selectAllCells() { checkWidget(); internalSelectAll(); } /** * Selects all cells in the given column in the receiver. * * @param col * * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public void selectColumn( int col ) { checkWidget(); selectCells( getCells( getColumn( col ) ) ); } /** * Selects all cells in the given column group in the receiver. * * @param colGroup * the column group * * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public void selectColumnGroup( int colGroup ) { selectColumnGroup( getColumnGroup( colGroup ) ); } /** * Selects all cells in the given column group in the receiver. * * @param colGroup * the column group * * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public void selectColumnGroup( GridColumnGroup colGroup ) { checkWidget(); selectCells( getCells( colGroup ) ); } /** * Deselects the item at the given zero-relative index in the receiver. If * the item at the index was already deselected, it remains deselected. * Indices that are out of range are ignored. *

* If cell selection is enabled, all cells in the specified item are deselected. * * @param index the index of the item to deselect * @throws org.eclipse.swt.SWTException *

    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void deselect( int index ) { checkWidget(); if( isValidItemIndex( index ) ) { internalDeselect( index ); } } /** * Deselects the items at the given zero-relative indices in the receiver. * If the item at the given zero-relative index in the receiver is selected, * it is deselected. If the item at the index was not selected, it remains * deselected. The range of the indices is inclusive. Indices that are out * of range are ignored. *

* If cell selection is enabled, all cells in the given range are deselected. * * @param start the start index of the items to deselect * @param end the end index of the items to deselect * @throws org.eclipse.swt.SWTException *

    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void deselect( int start, int end ) { checkWidget(); for( int index = Math.max( 0, start ); index <= Math.min( items.size() - 1, end ); index++ ) { internalDeselect( index ); } } /** * Deselects the items at the given zero-relative indices in the receiver. * If the item at the given zero-relative index in the receiver is selected, * it is deselected. If the item at the index was not selected, it remains * deselected. Indices that are out of range and duplicate indices are * ignored. *

* If cell selection is enabled, all cells in the given items are deselected. * * @param indices the array of indices for the items to deselect * @throws IllegalArgumentException *

    *
  • ERROR_NULL_ARGUMENT - if the set of indices is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void deselect( int[] indices ) { checkWidget(); if( indices == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } for( int i = 0; i < indices.length; i++ ) { internalDeselect( indices[ i ] ); } } /** * Deselects all selected items in the receiver. If cell selection is enabled, * all cells are deselected. * * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void deselectAll() { checkWidget(); internalDeselectAll(); } /** * Deselects the given cell in the receiver. If the given cell is already * deselected it remains deselected. Invalid cells are ignored. * * @param cell * cell to deselect. * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the cell is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public void deselectCell( Point cell ) { checkWidget(); if( cell == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } selectedCells.remove( cell ); } /** * Deselects the given cells. Invalid cells are ignored. * * @param cells * the cells to deselect. * * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the set of cells or any cell is * null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public void deselectCells( Point[] cells ) { checkWidget(); if( cells == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } for( Point cell : cells ) { if( cell == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } } for( Point cell : cells ) { selectedCells.remove( cell ); } } /** * Deselects all selected cells in the receiver. * * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public void deselectAllCells() { checkWidget(); selectedCells.clear(); } /** * Selects the item at the given zero-relative index in the receiver. The * current selection is first cleared, then the new item is selected. *

* If cell selection is enabled, all cells within the item at the given index * are selected. * * @param index the index of the item to select * @throws org.eclipse.swt.SWTException *

    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void setSelection( int index ) { checkWidget(); if( selectionEnabled && isValidItemIndex( index ) ) { internalDeselectAll(); internalSelect( index ); } } /** * Selects the items in the range specified by the given zero-relative * indices in the receiver. The range of indices is inclusive. The current * selection is cleared before the new items are selected. *

* Indices that are out of range are ignored and no items will be selected * if start is greater than end. If the receiver is single-select and there * is more than one item in the given range, then all indices are ignored. *

* If cell selection is enabled, all cells within the given range are selected. * * @param start the start index of the items to select * @param end the end index of the items to select * @throws org.eclipse.swt.SWTException *

    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
* @see Grid#deselectAll() * @see Grid#select(int,int) */ public void setSelection( int start, int end ) { checkWidget(); if( selectionEnabled && !( selectionType == SWT.SINGLE && start != end ) ) { internalDeselectAll(); for( int index = Math.max( 0, start ); index <= Math.min( items.size() - 1, end ); index++ ) { internalSelect( index ); } } } /** * Selects the items at the given zero-relative indices in the receiver. The * current selection is cleared before the new items are 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. *

* If cell selection is enabled, all cells within the given indices are selected. * * @param indices the indices of the items to select * @throws IllegalArgumentException *

    *
  • ERROR_NULL_ARGUMENT - if the array of indices is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
* @see Grid#deselectAll() * @see Grid#select(int[]) */ public void setSelection( int[] indices ) { checkWidget(); if( indices == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } if( selectionEnabled && !( selectionType == SWT.SINGLE && indices.length > 1 ) ) { internalDeselectAll(); for( int i = 0; i < indices.length; i++ ) { internalSelect( indices[ i ] ); } } } /** * Sets the receiver's selection to be the given array of items. The current * selection is cleared before the new items are selected. *

* 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. If cell selection is enabled, all cells within the given items * are selected. * * @param items the array of items * @throws IllegalArgumentException *

    *
  • ERROR_NULL_ARGUMENT - if the array of items is null
  • *
  • ERROR_INVALID_ARGUMENT - if one of the items has been disposed
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
* @see Grid#deselectAll() * @see Grid#select(int[]) * @see Grid#setSelection(int[]) */ public void setSelection( GridItem[] items ) { checkWidget(); if( items == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } if( selectionEnabled && !( selectionType == SWT.SINGLE && items.length > 1 ) ) { internalDeselectAll(); for( GridItem item : items ) { if( item != null ) { if( item.isDisposed() ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } internalSelect( this.items.indexOf( item ) ); } } } } /** * Returns a array of {@code GridItem}s that are currently selected in the * receiver. The order of the items is unspecified. An empty array indicates * that no items are selected. *

* Note: This is not the actual structure used by the receiver to maintain * its selection, so modifying the array will not affect the receiver. *

* If cell selection is enabled, any items which contain at least one selected * cell are returned. * * @return an array representing the selection * @throws org.eclipse.swt.SWTException *

    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridItem[] getSelection() { checkWidget(); if( cellSelectionEnabled ) { List items = new ArrayList<>(); int itemCount = getItemCount(); for( Point cell : selectedCells ) { if( cell.y >= 0 && cell.y < itemCount ) { GridItem item = getItem( cell.y ); if( !items.contains( item ) ) { items.add( item ); } } } return items.toArray( new GridItem[] {} ); } return selectedItems.toArray( new GridItem[ selectedItems.size() ] ); } /** * Returns the number of selected items contained in the receiver. If cell selection * is enabled, the number of items with at least one selected cell are returned. * * @return the number of selected items * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int getSelectionCount() { checkWidget(); if( cellSelectionEnabled ) { List items = new ArrayList<>(); for( Point cell : selectedCells ) { GridItem item = getItem( cell.y ); if( !items.contains( item ) ) { items.add( item ); } } return items.size(); } return selectedItems.size(); } /** * Returns the number of selected cells contained in the receiver. * * @return the number of selected cells * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public int getCellSelectionCount() { checkWidget(); return selectedCells.size(); } /** * Selects the selection to the given cell. The existing selection is cleared * before selecting the given cell. * * @param cell * point whose x value is a column index and y value is an item * index * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the item is null
  • *
  • ERROR_INVALID_ARGUMENT - if the cell is invalid
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public void setCellSelection( Point cell ) { checkWidget(); if( cellSelectionEnabled ) { if( cell == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } if( !isValidCell( cell ) ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } selectedCells.clear(); addToCellSelection( cell ); } } /** * Selects the selection to the given set of cell. The existing selection is * cleared before selecting the given cells. * * @param cells * point array whose x values is a column index and y value is an * item index * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the cell array or an individual cell * is null
  • *
  • ERROR_INVALID_ARGUMENT - if the a cell is invalid
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public void setCellSelection( Point[] cells ) { checkWidget(); if( cellSelectionEnabled ) { if( cells == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } for( Point cell : cells ) { if( cell == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } if( !isValidCell( cell ) ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } } selectedCells.clear(); for( Point cell : cells ) { addToCellSelection( cell ); } } } /** * Returns an array of cells that are currently selected in the receiver. The order of the items * is unspecified. An empty array indicates that no items are selected. *

* Note: This is not the actual structure used by the receiver to maintain its selection, so * modifying the array will not affect the receiver. *

* * @return an array representing the cell selection * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the * receiver
  • *
* * @since 3.13 */ public Point[] getCellSelection() { checkWidget(); return selectedCells.toArray( new Point[ selectedCells.size() ] ); } /** * Returns the zero-relative index of the item which is currently selected * in the receiver, or -1 if no item is selected. If cell selection is enabled, * returns the index of first item that contains at least one selected cell. * * @return the index of the selected item * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int getSelectionIndex() { checkWidget(); int result = -1; if( cellSelectionEnabled ) { if( selectedCells.size() != 0 ) { result = selectedCells.get( 0 ).y; } } else { if( selectedItems.size() != 0 ) { result = items.indexOf( selectedItems.get( 0 ) ); } } return result; } /** * 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. *

* Note: This is not the actual structure used by the receiver to maintain * its selection, so modifying the array will not affect the receiver. *

* If cell selection is enabled, returns the indices of any items which * contain at least one selected cell. * * @return the array of indices of the selected items * @throws org.eclipse.swt.SWTException *

    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int[] getSelectionIndices() { checkWidget(); int[] result = new int[ 0 ]; if( cellSelectionEnabled ) { List selectedRows = new ArrayList(); for( Point cell : selectedCells ) { GridItem item = getItem( cell.y ); if( !selectedRows.contains( item ) ) { selectedRows.add( item ); } } result = new int[ selectedRows.size() ]; for( int i = 0; i < result.length; i++ ) { GridItem item = selectedRows.get( i ); result[ i ] = items.indexOf( item ); } } else { result = new int[ selectedItems.size() ]; for( int i = 0; i < result.length; i++ ) { GridItem item = selectedItems.get( i ); result[ i ] = items.indexOf( item ); } } return result; } /** * Returns {@code true} if the item is selected, and {@code false} * otherwise. Indices out of range are ignored. If cell selection is * enabled, returns true if the item at the given index contains at * least one selected cell. * * @param index the index of the item * @return the visibility state of the item at the index * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public boolean isSelected( int index ) { checkWidget(); boolean result = false; if( isValidItemIndex( index ) ) { if( cellSelectionEnabled ) { for( Point cell : selectedCells ) { if( cell.y == index ) { result = true; } } } else { result = isSelected( items.get( index ) ); } } return result; } /** * Returns true if the given item is selected. If cell selection is enabled, * returns true if the given item contains at least one selected cell. * * @param item item * @return true if the item is selected. * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the item is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public boolean isSelected( GridItem item ) { checkWidget(); if( item == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } boolean result = false; if( cellSelectionEnabled ) { int index = items.indexOf( item ); if( index != -1 ) { for( Point cell : selectedCells ) { if( cell.y == index ) { result = true; } } } } else { result = selectedItems.contains( item ); } return result; } /** * Returns true if the given cell is selected. * * @param cell * cell * @return true if the cell is selected. * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the cell is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public boolean isCellSelected( Point cell ) { checkWidget(); if( cell == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } return selectedCells.contains( cell ); } /** * Returns the cell at the given point in the receiver or null if no such cell * exists. The point is in the coordinate system of the receiver. * * @param point * the point used to locate the cell * @return the cell at the given point * @throws IllegalArgumentException *
    *
  • ERROR_NULL_ARGUMENT - if the point is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public Point getCell( Point point ) { checkWidget(); if( point == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } if( point.x < 0 || point.x > getClientArea().width ) { return null; } GridItem item = getItem( point ); GridColumn column = getColumn( point ); if( item != null && column != null ) { return new Point( indexOf( column ), indexOf( item ) ); } return null; } /** * Removes the item from the receiver at the given zero-relative index. * * @param index the index for the item * @throws IllegalArgumentException *
    *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number * of elements in the list minus 1 (inclusive)
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void remove( int index ) { checkWidget(); if( index < 0 || index > items.size() - 1 ) { SWT.error( SWT.ERROR_INVALID_RANGE ); } items.get( index ).dispose( index ); } /** * 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 * @throws IllegalArgumentException *
    *
  • ERROR_INVALID_RANGE - if either the start or end are not between 0 * and the number of elements in the list minus 1 (inclusive)
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void remove( int start, int end ) { checkWidget(); for( int i = end; i >= start; i-- ) { if( i < 0 || i > items.size() - 1 ) { SWT.error( SWT.ERROR_INVALID_RANGE ); } items.get( i ).dispose( i ); } } /** * Removes the items from the receiver's list at the given zero-relative * indices. * * @param indices the array of indices of the items * @throws IllegalArgumentException *
    *
  • ERROR_INVALID_RANGE - if the index is not between 0 and the number * of elements in the list minus 1 (inclusive)
  • *
  • ERROR_NULL_ARGUMENT - if the indices array is null
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void remove( int[] indices ) { checkWidget(); if( indices == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } GridItem[] removeThese = new GridItem[ indices.length ]; for( int i = 0; i < indices.length; i++ ) { int index = indices[ i ]; if( isValidItemIndex( index ) ) { removeThese[ i ] = items.get( index ); } else { SWT.error( SWT.ERROR_INVALID_RANGE ); } } for( int i = 0; i < removeThese.length; i++ ) { removeThese[ i ].dispose(); } } /** * Removes all of the items from the receiver. * * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void removeAll() { checkWidget(); while( items.size() > 0 ) { int flatIndex = items.size() - 1; items.get( flatIndex ).dispose( flatIndex ); } } /** * Marks the receiver's header as visible if the argument is {@code true}, * and marks it invisible otherwise. * * @param show the new visibility state * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void setHeaderVisible( boolean show ) { checkWidget(); if( columnHeadersVisible != show ) { columnHeadersVisible = show; layoutCache.invalidateHeaderHeight(); scheduleRedraw(); } } /** * Returns {@code true} if the receiver's header is visible, and * {@code false} otherwise. * * @return the receiver's header's visibility state * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public boolean getHeaderVisible() { checkWidget(); return columnHeadersVisible; } /** * Returns the height of the column headers. If this table has column * groups, the returned value includes the height of group headers. * * @return height of the column header row * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int getHeaderHeight() { checkWidget(); if( !layoutCache.hasHeaderHeight() ) { layoutCache.headerHeight = computeHeaderHeight(); } return layoutCache.headerHeight; } /** * Marks the receiver's footer as visible if the argument is {@code true}, * and marks it invisible otherwise. * * @param show the new visibility state * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void setFooterVisible( boolean show ) { checkWidget(); if( columnFootersVisible != show ) { columnFootersVisible = show; layoutCache.invalidateFooterHeight(); scheduleRedraw(); } } /** * Returns {@code true} if the receiver's footer is visible, and {@code false} otherwise * @return the receiver's footer's visibility state * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public boolean getFooterVisible() { checkWidget(); return columnFootersVisible; } /** * Returns the height of the column footers. * * @return height of the column footer row * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int getFooterHeight() { checkWidget(); if( !layoutCache.hasFooterHeight() ) { layoutCache.footerHeight = computeFooterHeight(); } return layoutCache.footerHeight; } /** * Returns the height of the column group headers. * * @return height of column group headers * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int getGroupHeaderHeight() { checkWidget(); if( !layoutCache.hasHeaderHeight() ) { layoutCache.headerHeight = computeHeaderHeight(); } return groupHeaderHeight; } /** * Sets the line visibility. * * @param linesVisible The linesVisible to set. * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void setLinesVisible( boolean linesVisible ) { checkWidget(); this.linesVisible = linesVisible; } /** * Returns true if the lines are visible. * * @return Returns the linesVisible. * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public boolean getLinesVisible() { checkWidget(); return linesVisible; } /** * Sets the focused item to the given item. * * @param item item to focus. * @throws IllegalArgumentException *
    *
  • ERROR_INVALID_ARGUMENT - if item is disposed
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void setFocusItem( GridItem item ) { checkWidget(); if( item == null || item.isDisposed() || item.getParent() != this || !item.isVisible() ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } focusItem = item; } /** * Returns the current item in focus. * * @return item in focus or {@code null}. * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public GridItem getFocusItem() { checkWidget(); return focusItem; } /** * Sets the focused column to the given column. Column focus is only applicable * when cell selection is enabled. * * @param column * column to focus. * @throws IllegalArgumentException *
    *
  • ERROR_INVALID_ARGUMENT - if item is disposed
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public void setFocusColumn( GridColumn column ) { checkWidget(); if( column == null || column.isDisposed() || column.getParent() != this || !column.isVisible() ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } if( isCellSelectionEnabled() ) { focusColumn = column; } } /** * Returns the current column in focus. * Column focus is only applicable when cell selection is enabled. * * @return column in focus or {@code null}. * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
* * @since 3.13 */ public GridColumn getFocusColumn() { checkWidget(); return isCellSelectionEnabled() ? focusColumn : null; } /** * Returns the current cell in focus. If cell selection is disabled, this method * returns null. * * @return cell in focus or {@code null}. x represents the column and y the row * the cell is in * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.13 */ public Point getFocusCell() { checkWidget(); if( !cellSelectionEnabled ) { return null; } int x = -1; int y = -1; if( focusColumn != null ) { x = indexOf( focusColumn ); } if( focusItem != null ) { y = indexOf( focusItem ); } return new Point( x, y ); } /** * Sets the default height for this Grid's items. When * this method is called, all existing items are resized * to the specified height and items created afterwards will be * initially sized to this height. *

* As long as no default height was set by the client through this method, * the preferred height of the first item in this Grid is * used as a default for all items (and is returned by {@link #getItemHeight()}). * * @param height default height in pixels * @throws IllegalArgumentException *

    *
  • ERROR_INVALID_ARGUMENT - if the height is < 1
  • *
* @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
* * @see GridItem#getHeight() */ public void setItemHeight( int height ) { checkWidget(); if( height < 1 ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } if( customItemHeight != height ) { customItemHeight = height; hasDifferingHeights = false; scheduleRedraw(); } } /** * Returns the default height of the items * in this Grid. See {@link #setItemHeight(int)} * for details. * * @return default height of items * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
* @see #setItemHeight(int) */ public int getItemHeight() { checkWidget(); if( customItemHeight == -1 ) { if( !layoutCache.hasItemHeight() ) { layoutCache.itemHeight = computeItemHeight(); } return layoutCache.itemHeight; } return customItemHeight; } @Override public void setFont( Font font ) { super.setFont( font ); layoutCache.invalidateItemHeight(); scheduleRedraw(); } /** * Sets the zero-relative index of the item which is currently at the top of * the receiver. This index can change when items are scrolled or new items * are added and removed. * * @param index the index of the top item * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void setTopIndex( int index ) { checkWidget(); if( isValidItemIndex( index ) ) { updateScrollBars(); GridItem item = items.get( index ); if( item.isVisible() && vScroll.getVisible() ) { int vScrollAmount = 0; for( int i = 0; i < index; i++ ) { if( items.get( i ).isVisible() ) { vScrollAmount++; } } vScroll.setSelection( vScrollAmount ); invalidateTopBottomIndex(); redraw(); } } } /** * Returns the zero-relative index of the item which is currently at the top * of the receiver. This index can change when items are scrolled or new * items are added or removed. * * @return the index of the top item * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public int getTopIndex() { checkWidget(); if( topIndex == -1 ) { updateScrollBars(); if( vScroll.getVisible() ) { int firstVisibleIndex = vScroll.getSelection(); if( isTree ) { Iterator iterator = items.iterator(); int row = firstVisibleIndex + 1; while( row > 0 && iterator.hasNext() ) { GridItem item = iterator.next(); if( item.isVisible() ) { row--; if( row == 0 ) { firstVisibleIndex = items.indexOf( item ); } } } } topIndex = firstVisibleIndex; } else { topIndex = 0; } } return topIndex; } /** * 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 * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
  • ERROR_INVALID_ARGUMENT - if 'item' is not contained in the receiver
  • *
*/ public void showItem( GridItem item ) { checkWidget(); if( item == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } if( item.isDisposed() ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } if( item.getParent() == this ) { int visibleGridHeight = getVisibleGridHeight(); if( visibleGridHeight >= 1 ) { updateScrollBars(); GridItem parent = item.getParentItem(); while( parent != null ) { if( !parent.isExpanded() ) { parent.setExpanded( true ); parent.fireEvent( SWT.Expand ); } parent = parent.getParentItem(); } if( !isShown( item ) ) { setTopIndex( items.indexOf( item ) ); } } } } /** * Shows the column. If the column is already showing in the receiver, this * method simply returns. Otherwise, the columns are scrolled until the * column is visible. * * @param column the column to be shown * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void showColumn( GridColumn column ) { checkWidget(); if( column == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } if( column.isDisposed() ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } if( column.getParent() == this ) { updateScrollBars(); if( !column.isVisible() ) { GridColumnGroup group = column.getColumnGroup(); group.setExpanded( !group.getExpanded() ); if( group.getExpanded() ) { group.notifyListeners( SWT.Expand, new Event() ); } else { group.notifyListeners( SWT.Collapse, new Event() ); } } if( hScroll.getVisible() ) { int offset = hScroll.getSelection(); int x = getColumnHeaderXPosition( column ); if( x < 0 || x + column.getWidth() > getClientArea().width ) { if( x >= 0 && column.getWidth() <= getClientArea().width ) { x -= getClientArea().width - column.getWidth(); } hScroll.setSelection( offset + x ); } } } } /** * 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. * * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that * created the receiver
  • *
*/ public void showSelection() { checkWidget(); GridItem item = null; if( cellSelectionEnabled ) { if( selectedCells.size() != 0 ) { Point cell = selectedCells.get( 0 ); item = getItem( cell.y ); showItem( item ); GridColumn column = getColumn( cell.x ); showColumn( column ); } } else { if( selectedItems.size() != 0 ) { item = selectedItems.get( 0 ); showItem( item ); } } } /** * Sets the value of the auto-height feature. When enabled, this feature resizes the height of * rows to reflect the content of cells with word-wrapping enabled. Cell word-wrapping is enabled * via the GridColumn.setWordWrap(boolean) method. If column headers have word-wrapping enabled, * this feature will also resize the height of the column headers as necessary. * * @param autoHeight Set to true to enable this feature, false (default) otherwise. */ public void setAutoHeight( boolean autoHeight ) { checkWidget(); if( this.autoHeight != autoHeight ) { this.autoHeight = autoHeight; layoutCache.invalidateHeaderHeight(); layoutCache.invalidateFooterHeight(); scheduleRedraw(); } } /** * Returns the value of the auto-height feature, which resizes row heights and column header * heights based on word-wrapped content. * * @return Returns whether or not the auto-height feature is enabled. * @see #setAutoHeight(boolean) */ public boolean isAutoHeight() { checkWidget(); return autoHeight; } /** * Recalculate the height of the header * * @since 3.4 */ public void recalculateHeader() { int previous = getHeaderHeight(); layoutCache.headerHeight = computeHeaderHeight(); if( previous != layoutCache.headerHeight ) { scrollValuesObsolete = true; scheduleRedraw(); } } /** * Marks the receiver's row header as visible if the argument is {@code true}, * and marks it invisible otherwise. * * @param show * the new visibility state * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.14 */ public void setRowHeaderVisible( boolean show ) { setRowHeaderVisible( show, 10 ); } /** * Marks the receiver's row header as visible if the argument is {@code true}, * and marks it invisible otherwise. * * @param show * the new visibility state * @param minWidth * the minimun width of the row column * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.14 */ public void setRowHeaderVisible( boolean show, int minWidth ) { checkWidget(); if( rowHeadersColumn != null ) { if( show ) { rowHeadersColumn.setMinimumWidth( Math.max( 10, minWidth ) ); } else { rowHeadersColumn.setMinimumWidth( 0 ); rowHeadersColumn.setWidth( 0 ); } } } /** * Sets the row header width to the specified value. This automatically disables * the auto width feature of the grid. * * @param width * the width of the row header * @see #getItemHeaderWidth() * * @since 3.14 */ public void setItemHeaderWidth( int width ) { checkWidget(); if( rowHeadersColumn != null ) { rowHeadersColumn.setWidth( width ); } } /** * Returns the row header width or 0 if row headers are not visible. * * @return the width of the row headers * @throws org.eclipse.swt.SWTException *
    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.14 */ public int getItemHeaderWidth() { checkWidget(); return rowHeadersColumn != null ? rowHeadersColumn.getWidth() : 0; } /** * Returns {@code true} if the receiver's row header is visible, and * {@code false} otherwise. *

* * @return the receiver's row header's visibility state * @throws org.eclipse.swt.SWTException *

    *
  • ERROR_WIDGET_DISPOSED - if the receiver has been * disposed
  • *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread * that created the receiver
  • *
* * @since 3.14 */ public boolean isRowHeaderVisible() { checkWidget(); return rowHeadersColumn != null && rowHeadersColumn.getWidth() > 0; } /** * Sets the value of the word-wrap feature for row headers. When enabled, this * feature will word-wrap the contents of row headers. * * @param enabled * Set to true to enable this feature, false (default) otherwise. * @see #isWordWrapHeader() * * @since 3.14 */ public void setWordWrapHeader( boolean enabled ) { checkWidget(); if( rowHeadersColumn != null ) { rowHeadersColumn.setWordWrap( enabled ); } } /** * Returns the value of the row header word-wrap feature, which word-wraps the * content of row headers. * * @return Returns whether or not the row header word-wrap feature is enabled. * @see #setWordWrapHeader(boolean) * * @since 3.14 */ public boolean isWordWrapHeader() { checkWidget(); return rowHeadersColumn != null ? rowHeadersColumn.getWordWrap() : false; } @Override @SuppressWarnings("unchecked") public T getAdapter( Class adapter ) { if( adapter == ItemProvider.class || adapter == IGridAdapter.class || adapter == ICellToolTipAdapter.class ) { return ( T )gridAdapter; } if( adapter == WidgetLCA.class ) { return ( T )GridLCA.INSTANCE; } return super.getAdapter( adapter ); } @Override public void setData( String key, Object value ) { if( !RWT.MARKUP_ENABLED.equals( key ) || !isMarkupEnabledFor( this ) ) { checkMarkupPrecondition( key, TEXT, () -> items.size() == 0 ); if( RWT.ROW_TEMPLATE.equals( key ) && value instanceof Template ) { rowHeadersColumn = null; } super.setData( key, value ); } } int newItem( GridItem item, int index, boolean root ) { int row = 0; GridItem parentItem = item.getParentItem(); if( !isTree && parentItem != null ) { isTree = true; } int flatIndex = index; // Have to convert indexes, this method needs a flat index, the method is called with indexes // that are relative to the level if( root && index != -1 ) { if( index >= rootItems.size() ) { flatIndex = -1; } else { flatIndex = items.indexOf( rootItems.get( index ) ); } } else if( !root ) { if( index >= parentItem.getItemCount() || index == -1 ) { GridItem rightMostDescendent = parentItem; while( rightMostDescendent.hasChildren() ) { int lastChildIndex = rightMostDescendent.getItemCount() - 1; rightMostDescendent = rightMostDescendent.getItem( lastChildIndex ); } flatIndex = items.indexOf( rightMostDescendent ) + 1; } else { flatIndex = items.indexOf( parentItem.getItem( index ) ); } } if( flatIndex == -1 ) { items.add( item ); row = items.size() - 1; } else { items.add( flatIndex, item ); row = flatIndex; } updateVisibleItems( 1 ); scheduleRedraw(); return row; } void removeItem( int index ) { GridItem item = items.remove( index ); if( !disposing ) { selectedItems.remove (item ); Point[] cells = getCells( item ); for( int i = 0; i < cells.length; i++ ) { selectedCells.remove( cells[ i ] ); } if( focusItem == item ) { focusItem = null; } if( item.isVisible() ) { updateVisibleItems( -1 ); } scheduleRedraw(); } } void newRootItem( GridItem item, int index ) { if( index == -1 || index >= rootItems.size() ) { rootItems.add( item ); item.index = rootItems.size() - 1; } else { rootItems.add( index, item ); item.index = index; } adjustItemIndices( item.index + 1 ); } void removeRootItem( int index ) { rootItems.remove( index ); adjustItemIndices( index ); } private void adjustItemIndices( int start ) { for( int i = start; i < rootItems.size(); i++ ) { rootItems.get( i ).index = i; } } void newColumn( GridColumn column, int index ) { if( !isInternalColumn ) { if( index == -1 ) { columns.add( column ); displayOrderedColumns.add( column ); } else { columns.add( index, column ); displayOrderedColumns.add( index, column ); } updatePrimaryCheckColumn(); for( GridItem item : items ) { item.columnAdded( index ); } if( column.isCheck() ) { layoutCache.invalidateItemHeight(); } layoutCache.invalidateHeaderHeight(); layoutCache.invalidateFooterHeight(); scheduleRedraw(); } } void removeColumn( GridColumn column ) { int index = columns.indexOf( column ); if( cellSelectionEnabled ) { List removeSelectedCells = new ArrayList<>(); for( Point cell : selectedCells ) { if( cell.x == index ) { removeSelectedCells.add( cell ); } } if( removeSelectedCells.size() > 0 ) { selectedCells.removeAll( removeSelectedCells ); } for( Point cell : selectedCells ) { if( cell.x >= index ) { cell.x-- ; } } } columns.remove( index ); displayOrderedColumns.remove( column ); if( focusColumn == column ) { focusColumn = null; } updatePrimaryCheckColumn(); for( GridItem item : items ) { item.columnRemoved( index ); } if( column.isCheck() ) { layoutCache.invalidateItemHeight(); } layoutCache.invalidateHeaderHeight(); layoutCache.invalidateFooterHeight(); scheduleRedraw(); } void newColumnGroup( GridColumnGroup group ) { columnGroups.add( group ); if( columnGroups.size() == 1 ) { layoutCache.invalidateHeaderHeight(); } scheduleRedraw(); } void removeColumnGroup( GridColumnGroup group ) { columnGroups.remove( group ); if( columnGroups.size() == 0 ) { layoutCache.invalidateHeaderHeight(); } scheduleRedraw(); } boolean isDisposing() { return disposing; } void updateVisibleItems( int amount ) { currentVisibleItems += amount; } GridColumn[] getColumnsInOrder() { checkWidget(); return displayOrderedColumns.toArray( new GridColumn[ columns.size() ] ); } void imageSetOnItem( Image image ) { if( image != null && itemImageSize == null ) { Rectangle imageBounds = image.getBounds(); itemImageSize = new Point( imageBounds.width, imageBounds.height ); layoutCache.invalidateItemHeight(); scheduleRedraw(); } } int getMaxContentWidth( GridColumn column ) { doRedraw(); return getMaxInnerWidth( getRootItems(), columns.indexOf( column ) ); } int getBottomIndex() { checkWidget(); if( bottomIndex == -1 ) { int topIndex = getTopIndex(); int visibleGridHeight = getVisibleGridHeight(); if( items.size() == 0 ) { bottomIndex = 0; } else if( visibleGridHeight < 1 ) { bottomIndex = topIndex; } else { RowRange range = getRowRange( topIndex, visibleGridHeight, false, false ); bottomIndex = range.endIndex; bottomIndexShownCompletely = range.height <= visibleGridHeight; } } return bottomIndex; } Point getOrigin( GridColumn column, GridItem item ) { int x = column.getLeft() - hScroll.getSelection(); int y = 0; if( item != null ) { if( columnHeadersVisible ) { y += getHeaderHeight(); } int topIndex = getTopIndex(); int itemIndex = items.indexOf( item ); if( itemIndex == -1 ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } while( topIndex != itemIndex ) { if( topIndex < itemIndex ) { GridItem currentItem = items.get( topIndex ); if( currentItem.isVisible() ) { y += currentItem.getHeight(); } topIndex++; } else if( topIndex > itemIndex ) { topIndex--; GridItem currentItem = items.get( topIndex ); if( currentItem.isVisible() ) { y -= currentItem.getHeight(); } } } } return new Point( x, y ); } boolean isShown( GridItem item ) { checkWidget(); boolean result = false; if( item.isVisible() ) { int itemIndex = items.indexOf( item ); if( itemIndex == -1 ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } int firstVisibleIndex = getTopIndex(); int lastVisibleIndex = getBottomIndex(); result = ( itemIndex >= firstVisibleIndex && itemIndex < lastVisibleIndex ) || ( itemIndex == lastVisibleIndex && bottomIndexShownCompletely ); } return result; } private void doRedraw() { if( isVirtual() && items.size() > 0 ) { for( int index = getTopIndex(); index <= getBottomIndex(); index++ ) { GridItem item = items.get( index ); if( item.isVisible() ) { item.ensureItemData(); item.handleVirtual(); } } } updateDefaultRowHeadersText(); updateScrollBars(); } boolean isVirtual() { return ( getStyle() & SWT.VIRTUAL ) != 0; } private void updateDefaultRowHeadersText() { if( isRowHeaderVisible() && defaultRowHeadersTextObsolete ) { int rowCounter = 1; for( int index = 0; index < items.size(); index++ ) { GridItem item = items.get( index ); if( item.isVisible() ) { item.setDefaultHeaderText( Integer.toString( rowCounter++ ) ); } } defaultRowHeadersTextObsolete = false; } } void updateScrollBars() { if( scrollValuesObsolete ) { Point preferredSize = getTableSize(); Rectangle clientArea = getScrollableArea(); for( int doublePass = 1; doublePass <= 2; doublePass++ ) { if( preferredSize.y > clientArea.height ) { vScroll.setVisible( true ); } else { vScroll.setVisible( false ); vScroll.setValues( 0, 0, 1, 1, 1, 1 ); } if( preferredSize.x > clientArea.width ) { hScroll.setVisible( true ); } else { hScroll.setVisible( false ); hScroll.setValues( 0, 0, 1, 1, 1, 1 ); } clientArea = getScrollableArea(); } if( vScroll.getVisible() ) { int max = currentVisibleItems; int thumb = 1; int visibleGridHeight = getVisibleGridHeight(); if( !hasDifferingHeights ) { thumb = visibleGridHeight / getItemHeight(); } else if( visibleGridHeight >= 1 ) { RowRange range = getRowRange( -1, visibleGridHeight, true, true ); max -= range.rows - 1; } int selection = Math.min( vScroll.getSelection(), max ); vScroll.setValues( selection, 0, max, thumb, 1, thumb ); } if( hScroll.getVisible() ) { int hiddenArea = preferredSize.x - clientArea.width; int selection = Math.min( hScroll.getSelection(), hiddenArea ); hScroll.setValues( selection, 0, preferredSize.x, clientArea.width, 5, clientArea.width ); } scrollValuesObsolete = false; } } private Rectangle getScrollableArea() { Rectangle clientArea = getClientArea(); clientArea.width -= getItemHeaderWidth(); return clientArea; } protected IScrollBarProxy getHorizontalScrollBarProxy() { checkWidget(); return hScroll; } protected IScrollBarProxy getVerticalScrollBarProxy() { checkWidget(); return vScroll; } private void initListeners() { resizeListener = new Listener() { @Override public void handleEvent( Event event ) { onResize(); } }; addListener( SWT.Resize, resizeListener ); disposeListener = new Listener() { @Override public void handleEvent( Event event ) { onDispose( event ); } }; addListener( SWT.Dispose, disposeListener ); } private void onResize() { if( TextSizeUtil.isTemporaryResize() ) { isTemporaryResize = true; layoutCache.invalidateHeaderHeight(); layoutCache.invalidateFooterHeight(); layoutCache.invalidateItemHeight(); } else { if( isTemporaryResize) { isTemporaryResize = false; repackColumns(); } scheduleRedraw(); } } private void onDispose( Event event ) { // We only want to dispose of our items and such *after* anybody else who may have been // listening to the dispose has had a chance to do whatever. removeListener( SWT.Resize, resizeListener ); removeListener( SWT.Dispose, disposeListener ); notifyListeners( SWT.Dispose, event ); event.type = SWT.None; disposing = true; for( GridItem item : items ) { item.dispose(); } for( GridColumn column : columns ) { column.dispose(); } for( GridColumnGroup group : columnGroups ) { group.dispose(); } if( rowHeadersColumn != null ) { rowHeadersColumn.dispose(); } } void setCellToolTipsEnabled( boolean enabled ) { setData( ICellToolTipProvider.ENABLE_CELL_TOOLTIP, Boolean.valueOf( enabled ) ); } private Point getTableSize() { int width = 0; int height = 0; if( columnHeadersVisible ) { height += getHeaderHeight(); } if( columnFootersVisible ) { height += getFooterHeight(); } height += getGridHeight(); for( GridColumn column : columns ) { if( column.isVisible() ) { width += column.getWidth(); } } return new Point( width, height ); } private int getGridHeight() { int result = 0; if( hasDifferingHeights ) { for( GridItem item : items ) { if( item.isVisible() ) { result += item.getHeight(); } } } else { result = currentVisibleItems * getItemHeight(); } return result; } private int getVisibleGridHeight() { int headerHeight = columnHeadersVisible ? getHeaderHeight() : 0; int footerHeight = columnFootersVisible ? getFooterHeight() : 0; return getClientArea().height - headerHeight - footerHeight; } private static int getMaxInnerWidth( GridItem[] items, int index ) { int maxInnerWidth = 0; for( GridItem item : items ) { if( item.isResolved() ) { maxInnerWidth = Math.max( maxInnerWidth, item.getPreferredWidth( index ) ); if( item.isExpanded() ) { int innerWidth = getMaxInnerWidth( item.getItems(), index ); maxInnerWidth = Math.max( maxInnerWidth, innerWidth ); } } } return maxInnerWidth; } private void internalSelect( int index ) { if( isValidItemIndex( index ) ) { GridItem item = items.get( index ); if( cellSelectionEnabled ) { selectCells( getCells( item ) ); } else if( !selectedItems.contains( item ) ) { selectedItems.add( item ); } } } private void internalSelectAll() { for( int i = 0; i < items.size(); i++ ) { GridItem item = items.get( i ); if( item.isVisible() ) { internalSelect( i ); } } } private void internalDeselect( int index ) { if( isValidItemIndex( index ) ) { GridItem item = items.get( index ); if( cellSelectionEnabled ) { deselectCells( getCells( item ) ); } else if( selectedItems.contains( item ) ) { selectedItems.remove( item ); } } } private void internalDeselectAll() { if( cellSelectionEnabled ) { selectedCells.clear(); } else { selectedItems.clear(); } } private Point[] getCells( GridItem item ) { List cells = new ArrayList<>(); int itemIndex = items.indexOf( item ); int span = 0; for( GridColumn nextCol : displayOrderedColumns ) { if( span > 0 ) { span-- ; continue; } if( !nextCol.isVisible() ) { continue; } span = item.getColumnSpan( indexOf( nextCol ) ); cells.add( new Point( indexOf( nextCol ), itemIndex ) ); } return cells.toArray( new Point[ 0 ] ); } private Point[] getCells( GridColumn col ) { List cells = new ArrayList<>(); int colIndex = indexOf( col ); int columnAtPosition = 0; for( GridColumn nextCol : displayOrderedColumns ) { if( !nextCol.isVisible() ) { continue; } if( nextCol == col ) { break; } columnAtPosition++ ; } GridItem item = null; if( getItemCount() > 0 ) { item = getItem( 0 ); } while( item != null ) { // is cell spanned int position = -1; boolean spanned = false; for( GridColumn nextCol : displayOrderedColumns ) { if( !nextCol.isVisible() ) { continue; } if( nextCol == col ) { break; } int span = item.getColumnSpan( indexOf( nextCol ) ); if( position + span >= columnAtPosition ) { spanned = true; break; } } if( !spanned && item.getColumnSpan( colIndex ) == 0 ) { cells.add( new Point( colIndex, indexOf( item ) ) ); } item = getNextVisibleItem( item ); } return cells.toArray( new Point[ 0 ] ); } private Point[] getCells( GridColumnGroup colGroup ) { List cells = new ArrayList<>(); for( GridColumn col : colGroup.getColumns() ) { for( Point cell : getCells( col ) ) { cells.add( cell ); } } return cells.toArray( new Point[ 0 ] ); } private void addToCellSelection( Point newCell ) { if( newCell.x < 0 || newCell.x >= columns.size() ) { return; } if( newCell.y < 0 || newCell.y >= items.size() ) { return; } Iterator it = selectedCells.iterator(); boolean found = false; while( it.hasNext() ) { Point p = it.next(); if( newCell.equals( p ) ) { found = true; break; } } if( !found ) { if( selectionType == SWT.SINGLE && selectedCells.size() > 0 ) { return; } selectedCells.add( newCell ); } } private void updatePrimaryCheckColumn() { if( ( getStyle() & SWT.CHECK ) == SWT.CHECK ) { for( GridColumn column : columns ) { column.setTableCheck( false ); } if( treeColumn != null ) { treeColumn.setTableCheck( true ); } else if( displayOrderedColumns.size() > 0 ) { displayOrderedColumns.get( 0 ).setTableCheck( true ); } } } private int computeItemHeight() { int result = Math.max( getItemImageSize().y, TextSizeUtil.getCharHeight( getFont() ) ); if( hasCheckBoxes() ) { result = Math.max( getCheckBoxImageOuterSize().height, result ); } BoxDimensions cellPadding = getCellPadding(); result += cellPadding.top + cellPadding.bottom; result += GRID_WIDTH; result = Math.max( result, MIN_ITEM_HEIGHT ); return result; } private int computeHeaderHeight() { int result = 0; groupHeaderHeight = 0; if( columnHeadersVisible ) { int columnHeaderHeight = 0; for( int i = 0; i < getColumnCount(); i++ ) { GridColumn column = columns.get( i ); Font font = column.getHeaderFont(); String text = column.getText(); Image image = column.getImage(); int wrapWidth = autoHeight && column.getHeaderWordWrap() ? column.getHeaderWrapWidth() : 0; int computedHeight = computeColumnHeight( font, text, image, 0, wrapWidth ); columnHeaderHeight = Math.max( columnHeaderHeight, computedHeight ); } for( int i = 0; i < getColumnGroupCount(); i++ ) { GridColumnGroup group = columnGroups.get( i ); Font font = group.getHeaderFont(); String text = group.getText(); Image image = group.getImage(); int chevronHeight = group.getChevronHeight(); int wrapWidth = autoHeight && group.getHeaderWordWrap() ? group.getHeaderWrapWidth() : 0; int computedHeight = computeColumnHeight( font, text, image, chevronHeight, wrapWidth ); groupHeaderHeight = Math.max( groupHeaderHeight, computedHeight ); } result = columnHeaderHeight + groupHeaderHeight; } return result; } private int computeFooterHeight() { int result = 0; if( columnFootersVisible ) { int columnFooterHeight = 0; for( int i = 0; i < getColumnCount(); i++ ) { GridColumn column = columns.get( i ); Font font = column.getFooterFont(); String text = column.getFooterText(); Image image = column.getFooterImage(); int wrapWidth = autoHeight && column.getHeaderWordWrap() ? column.getFooterWrapWidth() : 0; int computedHeight = computeColumnHeight( font, text, image, 0, wrapWidth ); columnFooterHeight= Math.max( columnFooterHeight, computedHeight ); } result = columnFooterHeight; } return result; } private int computeColumnHeight( Font font, String text, Image image, int minHeight, int wrapWidth ) { int result = minHeight; int textHeight = 0; if( text.contains( "\n" ) || wrapWidth > 0 ) { textHeight = TextSizeUtil.textExtent( font, text, wrapWidth ).y; } else { textHeight = TextSizeUtil.getCharHeight( font ); } result = Math.max( result, textHeight ); int imageHeight = image == null ? 0 : image.getBounds().height; result = Math.max( result, imageHeight ); BoxDimensions headerPadding = getHeaderPadding(); result += headerPadding.top + headerPadding.bottom; result += getThemeAdapter().getHeaderBorderBottomWidth( this ); return result; } private void repackColumns() { for( int i = 0; i < getColumnCount(); i++ ) { columns.get( i ).repack(); } } private int getColumnHeaderXPosition( GridColumn column ) { int result = -1; if( column.isVisible() ) { result = column.getLeft() - hScroll.getSelection(); } return result; } private int getCellLeft( int index ) { return getColumn( index ).getLeft(); } private int getCellWidth( int index ) { GridColumn column = getColumn( index ); return column.isVisible() ? column.getWidth() : 0; } private int getCheckBoxOffset( int index ) { int result = -1; BoxDimensions padding = getCellPadding(); if( isColumnCentered( index ) && !isTreeColumn( index ) && !hasColumnImages( index ) && !hasColumnTexts( index ) ) { result = ( getCellWidth( index ) - getCheckBoxImageSize().width ) / 2; result = Math.max( result, padding.left ); } if( result == -1 ) { result = getCheckBoxMargin().left; if( !isTreeColumn( index ) ) { result += padding.left; } } return result; } private int getCheckBoxWidth( int index ) { return getColumn( index ).isCheck() ? getCheckBoxImageSize().width : 0; } private int getImageOffset( int index ) { int result = 0; if( !isTreeColumn( index ) ) { result += getCellPadding().left; } if( getColumn( index ).isCheck() ) { result += getCheckBoxImageOuterSize().width; } return result; } private int getImageWidth( int index ) { if( hasColumnImages( index ) ) { int availableWidth = getCellWidth( index ); if( !isTreeColumn( index ) ) { availableWidth -= getCellPadding().left; } availableWidth = Math.max( 0, availableWidth ); return Math.min( getItemImageSize().x, availableWidth ); } return 0; } private int getTextOffset( int index ) { int result = getImageOffset( index ); if( hasColumnImages( index ) ) { result += getItemImageSize().x; result += getCellSpacing(); } return result; } private int getTextWidth( int index ) { return Math.max( 0, getCellWidth( index ) - getTextOffset( index ) - getCellPadding().right ); } private int getRowHeaderImageOffset() { return getCellPadding().left; } private int getRowHeaderImageWidth() { if( hasColumnImages( Integer.MIN_VALUE ) ) { int availableWidth = Math.max( 0, getItemHeaderWidth() - getCellPadding().left ); return Math.min( getItemImageSize().x, availableWidth ); } return 0; } private int getRowHeaderTextOffset() { int result = getRowHeaderImageOffset(); if( hasColumnImages( Integer.MIN_VALUE ) ) { result += getItemImageSize().x; result += getCellSpacing(); } return result; } private int getRowHeaderTextWidth() { return Math.max( 0, getItemHeaderWidth() - getRowHeaderTextOffset() - getCellPadding().right ); } Point getItemImageSize() { Point result = new Point( 0, 0 ); if( itemImageSize != null ) { result.x = itemImageSize.x; result.y = itemImageSize.y; } return result; } boolean hasColumnImages( int index ) { if( index == Integer.MIN_VALUE ) { return rowHeadersColumn != null && rowHeadersColumn.imageCount > 0; } return getColumn( index ).imageCount > 0; } boolean hasColumnTexts( int index ) { if( index == Integer.MIN_VALUE ) { return rowHeadersColumn != null && rowHeadersColumn.textCount > 0; } return getColumn( index ).textCount > 0; } private boolean hasCheckBoxes() { boolean result = ( getStyle() & SWT.CHECK ) != 0; for( int i = 0; i < getColumnCount() && !result; i++ ) { GridColumn column = columns.get( i ); if( column.isCheck() ) { result = true; } } return result; } Size getCheckBoxImageOuterSize() { Size imageSize = getCheckBoxImageSize(); BoxDimensions margin = getCheckBoxMargin(); int width = imageSize.width + margin.left + margin.right; int height = imageSize.height + margin.top + margin.bottom; return new Size( width, height ); } void setTreeColumn( GridColumn column ) { treeColumn = column; updatePrimaryCheckColumn(); } boolean isTreeColumn( int index ) { boolean result = false; if( isTree && index < columns.size() ) { if( treeColumn != null ) { result = columns.get( index ) == treeColumn; } else { result = index == getColumnOrder()[ 0 ]; } } return result; } private boolean isColumnCentered( int index ) { return getColumn( index ).getAlignment() == SWT.CENTER; } private Size getCheckBoxImageSize() { if( !layoutCache.hasCheckBoxImageSize() ) { layoutCache.checkBoxImageSize = getThemeAdapter().getCheckBoxImageSize( this ); } return layoutCache.checkBoxImageSize; } private BoxDimensions getCheckBoxMargin() { if( !layoutCache.hasCheckBoxMargin() ) { layoutCache.checkBoxMargin = getThemeAdapter().getCheckBoxMargin( this ); } return layoutCache.checkBoxMargin; } BoxDimensions getCellPadding() { if( !layoutCache.hasCellPadding() ) { layoutCache.cellPadding = getThemeAdapter().getCellPadding( this ); } return layoutCache.cellPadding; } BoxDimensions getHeaderPadding() { if( !layoutCache.hasHeaderPadding() ) { layoutCache.headerPadding = getThemeAdapter().getHeaderPadding( this ); } return layoutCache.headerPadding; } int getIndentationWidth() { if( !isTree ) { return 0; } if( !layoutCache.hasIndentationWidth() ) { layoutCache.indentationWidth = getThemeAdapter().getIndentationWidth( this ); } return layoutCache.indentationWidth; } int getCellSpacing() { if( !layoutCache.hasCellSpacing() ) { layoutCache.cellSpacing = getThemeAdapter().getCellSpacing( this ); } return layoutCache.cellSpacing; } private GridThemeAdapter getThemeAdapter() { return ( GridThemeAdapter )getAdapter( ThemeAdapter.class ); } private static int checkStyle( int style ) { int mask = SWT.BORDER | SWT.LEFT_TO_RIGHT // | SWT.RIGHT_TO_LEFT | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.MULTI | SWT.NO_FOCUS | SWT.CHECK | SWT.VIRTUAL; int result = style & mask; result |= SWT.DOUBLE_BUFFERED; // TODO: [if] Remove it when cell selection is implemented result |= SWT.FULL_SELECTION; return result; } private RowRange getRowRange( int start, int availableHeight, boolean forceEndCompletelyInside, boolean inverse ) { RowRange result = new RowRange(); int startIndex = start; if( startIndex == -1 ) { if( inverse ) { startIndex = items.size(); } do { startIndex += inverse ? -1 : 1; } while( isValidItemIndex( startIndex ) && !items.get( startIndex ).isVisible() ); if( !isValidItemIndex( startIndex ) ) { result = null; } } if( result != null ) { if( startIndex < 0 || startIndex >= items.size() || !items.get( startIndex ).isVisible() ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } if( availableHeight <= 0 ) { result.startIndex = startIndex; result.endIndex = startIndex; result.rows = 0; result.height = 0; } else if( isTree || hasDifferingHeights ) { int otherIndex = startIndex; int consumedItems = 0; int consumedHeight = 0; consumedItems++; consumedHeight += items.get( otherIndex ).getHeight(); boolean abort = false; while( consumedHeight + 1 <= availableHeight && !abort ) { int nextIndex = otherIndex; GridItem nextItem; do { nextIndex += inverse ? -1 : 1; if( isValidItemIndex( nextIndex ) ) { nextItem = items.get( nextIndex ); } else { nextItem = null; } } while( nextItem != null && !nextItem.isVisible() ); if( nextItem == null || forceEndCompletelyInside && !( consumedHeight + nextItem.getHeight() <= availableHeight ) ) { abort = true; } else { consumedItems++; consumedHeight += nextItem.getHeight(); otherIndex = nextIndex; } } result.startIndex = !inverse ? startIndex : otherIndex; result.endIndex = !inverse ? otherIndex : startIndex; result.rows = consumedItems; result.height = consumedHeight; } else { int availableRows = availableHeight / getItemHeight(); if( !forceEndCompletelyInside && availableRows * getItemHeight() < availableHeight ) { availableRows++; } int otherIndex = startIndex + ( ( availableRows - 1 ) * ( inverse ? -1 : 1 ) ); otherIndex = Math.max( otherIndex, 0 ); otherIndex = Math.min( otherIndex, items.size() - 1 ); result.startIndex = !inverse ? startIndex : otherIndex; result.endIndex = !inverse ? otherIndex : startIndex; result.rows = result.endIndex - result.startIndex + 1; result.height = getItemHeight() * result.rows; } } return result; } private boolean isValidItemIndex( int index ) { return index >= 0 && index < items.size(); } private boolean isValidCell( Point cell ) { if( cell.x < 0 || cell.x >= columns.size() ) { return false; } if( cell.y < 0 || cell.y >= items.size() ) { return false; } return true; } int internalIndexOf( GridItem item ) { return items.indexOf( item ); } void scheduleRedraw() { invalidateScrollBars(); invalidateTopBottomIndex(); redraw(); } void invalidateTopBottomIndex() { topIndex = -1; bottomIndex = -1; } void invalidateScrollBars() { scrollValuesObsolete = true; } void invalidateDefaultRowHeadersText() { defaultRowHeadersTextObsolete = true; redraw(); } void setHasSpanning( boolean hasSpanning ) { this.hasSpanning = hasSpanning; } boolean isRowHeadersColumn( GridColumn column ) { return column != null && column == rowHeadersColumn; } GridColumn getRowHeadersColumn() { return rowHeadersColumn; } private void createRowHeadersColumn() { isInternalColumn = true; rowHeadersColumn = new GridColumn( this, SWT.NONE ); rowHeadersColumn.setMoveable( false ); rowHeadersColumn.setMinimumWidth( 0 ); rowHeadersColumn.setWidth( 0 ); isInternalColumn = false; } private boolean isFixedColumn( GridColumn column ) { int fixedColumns = getFixedColumns(); if( fixedColumns <= 0 ) { return false; } else if( isRowHeadersColumn( column ) ) { return true; } int[] columnOrder = getColumnOrder(); int visualIndex = -1; for( int i = 0; i < columnOrder.length && visualIndex == -1; i++ ) { if( indexOf( column ) == columnOrder[ i ] ) { visualIndex = i; } } return visualIndex < fixedColumns - 1; } private int getFixedColumns() { if( !( getData( RWT.ROW_TEMPLATE ) instanceof Template ) ) { Object fixedColumns = getData( RWT.FIXED_COLUMNS ); if( fixedColumns instanceof Integer ) { return ( ( Integer )fixedColumns ).intValue() + 1; } return 1; } return -1; } //////////////// // Inner classes private static class RowRange { public int startIndex; public int endIndex; public int rows; public int height; } private final class GridAdapter implements IGridAdapter, ICellToolTipAdapter, ItemProvider, SerializableCompatibility { private String toolTipText; private ICellToolTipProvider provider; public GridAdapter() { provider = new CellToolTipProvider(); } @Override public void invalidateTopIndex() { invalidateTopBottomIndex(); redraw(); } @Override public int getIndentationWidth() { return Grid.this.getIndentationWidth(); } @Override public int getCellLeft( int index ) { return Grid.this.getCellLeft( index ); } @Override public int getCellWidth( int index ) { return Grid.this.getCellWidth( index ); } @Override public int getCheckBoxOffset( int index ) { return Grid.this.getCheckBoxOffset( index ); } @Override public int getCheckBoxWidth( int index ) { return Grid.this.getCheckBoxWidth( index ); } @Override public int getImageOffset( int index ) { return Grid.this.getImageOffset( index ); } @Override public int getImageWidth( int index ) { return Grid.this.getImageWidth( index ); } @Override public int getTextOffset( int index ) { return Grid.this.getTextOffset( index ); } @Override public int getTextWidth( int index ) { return Grid.this.getTextWidth( index ); } @Override public int getRowHeaderImageOffset() { return Grid.this.getRowHeaderImageOffset(); } @Override public int getRowHeaderImageWidth() { return Grid.this.getRowHeaderImageWidth(); } @Override public int getRowHeaderTextOffset() { return Grid.this.getRowHeaderTextOffset(); } @Override public int getRowHeaderTextWidth() { return Grid.this.getRowHeaderTextWidth(); } @Override public int getItemIndex( GridItem item ) { return item.index; } @Override public ICellToolTipProvider getCellToolTipProvider() { return provider; } @Override public void setCellToolTipProvider( ICellToolTipProvider provider ) { this.provider = provider; } @Override public String getCellToolTipText() { return toolTipText; } @Override public void setCellToolTipText( String toolTipText ) { this.toolTipText = toolTipText; } @Override public void doRedraw() { Grid.this.doRedraw(); } @Override public void provideItems( WidgetTreeVisitor visitor ) { for( GridColumnGroup columnGroup : columnGroups ) { visitor.visit( columnGroup ); } if( rowHeadersColumn != null ) { visitor.visit( rowHeadersColumn ); } for( GridColumn column : columns ) { visitor.visit( column ); } if( isVirtual() ) { for( GridItem item : items ) { if( item.isResolved() ) { visitor.visit( item ); } } } else { for( GridItem item : items ) { visitor.visit( item ); } } } @Override public int getFixedColumns() { return Grid.this.getFixedColumns(); } @Override public boolean isFixedColumn( GridColumn column ) { return Grid.this.isFixedColumn( column ); } @Override public int getTreeColumn() { int offset = rowHeadersColumn != null ? 1 : 0; if( treeColumn != null ) { return indexOf( treeColumn ) + offset; } else if( getColumnCount() > 0 ) { return getColumnOrder()[ 0 ] + offset; } return -1; } @Override public int getSelectionType() { return selectionType; } @Override public GridColumn getRowHeadersColumn() { return Grid.this.getRowHeadersColumn(); } } private final class CellToolTipProvider implements ICellToolTipProvider, SerializableCompatibility { @Override public void getToolTipText( Item item, int columnIndex ) { String toolTipText = ( ( GridItem )item ).getToolTipText( columnIndex ); getAdapter( ICellToolTipAdapter.class ).setCellToolTipText( toolTipText ); } } static final class LayoutCache implements SerializableCompatibility { private static final int UNKNOWN = -1; int headerHeight = UNKNOWN; int footerHeight = UNKNOWN; int itemHeight = UNKNOWN; int cellSpacing = UNKNOWN; int indentationWidth = UNKNOWN; BoxDimensions cellPadding; BoxDimensions headerPadding; BoxDimensions checkBoxMargin; Size checkBoxImageSize; public boolean hasHeaderPadding() { return headerPadding != null; } public void invalidateHeaderPadding() { headerPadding = null; } public boolean hasHeaderHeight() { return headerHeight != UNKNOWN; } public void invalidateHeaderHeight() { headerHeight = UNKNOWN; } public boolean hasFooterHeight() { return footerHeight != UNKNOWN; } public void invalidateFooterHeight() { footerHeight = UNKNOWN; } public boolean hasItemHeight() { return itemHeight != UNKNOWN; } public void invalidateItemHeight() { itemHeight = UNKNOWN; } public boolean hasCellSpacing() { return cellSpacing != UNKNOWN; } public void invalidateCellSpacing() { cellSpacing = UNKNOWN; } public boolean hasIndentationWidth() { return indentationWidth != UNKNOWN; } public void invalidateIndentationWidth() { indentationWidth = UNKNOWN; } public boolean hasCellPadding() { return cellPadding != null; } public void invalidateCellPadding() { cellPadding = null; } public boolean hasCheckBoxMargin() { return checkBoxMargin != null; } public void invalidateCheckBoxMargin() { checkBoxMargin = null; } public boolean hasCheckBoxImageSize() { return checkBoxImageSize != null; } public void invalidateCheckBoxImageSize() { checkBoxImageSize = null; } public void invalidateAll() { invalidateHeaderPadding(); invalidateHeaderHeight(); invalidateFooterHeight(); invalidateItemHeight(); invalidateCellSpacing(); invalidateCellPadding(); invalidateCheckBoxMargin(); invalidateCheckBoxImageSize(); invalidateIndentationWidth(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy