/*******************************************************************************
* Copyright (c) 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* chris.gross@us.ibm.com - initial API and implementation
* Claes Rosell<claes.rosell@solme.se> - rowspan in bug 272384
* Stefan Widmaier<stefan.widmaier@faktorzehn.de> - rowspan in 304797
* Mirko Paturzo <mirko.paturzo@exeura.eu> - improvement (bug in 419928)
*******************************************************************************/
package org.eclipse.nebula.widgets.grid;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.TypedListener;
/**
* <p>
* NOTE: THIS WIDGET AND ITS API ARE STILL UNDER DEVELOPMENT. THIS IS A
* PRE-RELEASE ALPHA VERSION. USERS SHOULD EXPECT API CHANGES IN FUTURE
* VERSIONS.
* </p>
* Instances of this class represent a selectable user interface object that
* represents an item in a grid.
* <p>
* <dl>
* <dt><b>Styles:</b></dt>
* <dd>(none)</dd>
* <dt><b>Events:</b></dt>
* <dd>(none)</dd>
* </dl>
*
* @author chris.gross@us.ibm.com
* @author Mirko Paturzo <mirko.paturzo@exeura.eu>
*
* Mirko removed all collections, improve dispose performance, reduce
* used memory
*/
public class GridItem extends Item {
private static final int NO_ROW = -1;
/**
* List of children.
*/
private List<GridItem> children;
/**
* Default background color.
*/
@Deprecated
private Color defaultBackground;
/**
* Default font.
*/
@Deprecated
private Font defaultFont;
/**
* Default foreground color.
*/
@Deprecated
private Color defaultForeground;
/**
* The height of this <code>GridItem</code>.
*/
private int height = 1;
/**
* Is expanded?
*/
private boolean expanded = false;
/**
* True if has children.
*/
private boolean hasChildren = false;
/**
* Level of item in a tree.
*/
private int level = 0;
/**
* Parent grid instance.
*/
private final Grid parent;
/**
* Parent item (if a child item).
*/
private GridItem parentItem;
/**
* Is visible?
*/
private boolean visible = true;
/**
* Row header text.
*/
private String headerText = null;
/**
* Row header image
*/
private Image headerImage = null;
/**
* Background color of the header
*/
private Color headerBackground = null;
/**
* Foreground color of the header
*/
public Color headerForeground = null;
/**
* (SWT.VIRTUAL only) Flag that specifies whether the client has already
* been sent a SWT.SetData event.
*/
private boolean hasSetData = false;
private int row = NO_ROW;
private final Object ROW_LOCK = new Object();
/**
* Creates a new instance of this class and places the item at the end of
* the grid.
*
* @param parent
* parent grid
* @param style
* item style
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
* </ul>
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the parent</li>
* <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed
* subclass</li>
* </ul>
*/
public GridItem(Grid parent, int style) {
this(parent, style, NO_ROW);
}
/**
* Creates a new instance of this class and places the item in the grid at
* the given index.
*
* @param parent
* parent grid
* @param style
* item style
* @param index
* index where to insert item
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
* </ul>
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the parent</li>
* <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed
* subclass</li>
* </ul>
*/
public GridItem(Grid parent, int style, int index) {
super(parent, style, index);
this.parent = parent;
row = parent.newItem(this, index, true);
parent.newRootItem(this, index);
}
/**
* @return grid row index
*/
public int getRowIndex() {
synchronized (ROW_LOCK) {
if (row != NO_ROW)
return row;
}
return parent.indexOf(this);
}
void increaseRow() {
synchronized (ROW_LOCK) {
row++;
}
}
void decreaseRow() {
synchronized (ROW_LOCK) {
row--;
}
}
/**
* Creates a new instance of this class as a child node of the given
* GridItem and places the item at the end of the parents items.
*
* @param parent
* parent item
* @param style
* item style
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
* </ul>
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the parent</li>
* <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed
* subclass</li>
* </ul>
*/
public GridItem(GridItem parent, int style) {
this(parent, style, NO_ROW);
}
/**
* Creates a new instance of this class as a child node of the given Grid
* and places the item at the given index in the parent items list.
*
* @param parent
* parent item
* @param style
* item style
* @param index
* index to place item
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
* </ul>
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the parent</li>
* <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed
* subclass</li>
* </ul>
*/
public GridItem(GridItem parent, int style, int index) {
super(parent, style, index);
parentItem = parent;
this.parent = parentItem.getParent();
row = this.parent.newItem(this, index, false);
level = parentItem.getLevel() + 1;
parentItem.newItem(this, index);
parentItem.indexOf(this);
if (parent.isVisible() && parent.isExpanded()) {
setVisible(true);
} else {
setVisible(false);
}
}
/**
* {@inheritDoc}
*/
@Override
public void dispose() {
if (!parent.isDisposing()) {
parent.removeItem(this);
if (parentItem != null) {
parentItem.remove(this);
} else {
parent.removeRootItem(this);
}
if (hasChildren)
for (int i = children.size() - 1; i >= 0; i--) {
children.get(i).dispose();
}
}
if (parent.getDataVisualizer() != null) {
parent.getDataVisualizer().clearRow(this);
}
noRow();
super.dispose();
}
/**
* Adds the listener to the collection of listeners who will be notified
* when the row is resized, by sending it one of the messages defined in the
* <code>ControlListener</code> interface.
* <p>
* Clients who wish to override the standard row resize logic should use the
* untyped listener mechanisms. The untyped <code>Event</code> object passed
* to an untyped listener will have its <code>detail</code> field populated
* with the new row height. Clients may alter this value to, for example,
* enforce minimum or maximum row sizes. Clients may also set the
* <code>doit</code> field to false to prevent the entire resize operation.
*
* @param listener
* the listener which should be notified
*
* @exception IllegalArgumentException
* <ul>
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
* </ul>
* @exception SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been
* disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void addControlListener(ControlListener listener) {
checkWidget();
if (listener == null)
SWT.error(SWT.ERROR_NULL_ARGUMENT);
TypedListener typedListener = new TypedListener(listener);
addListener(SWT.Resize, typedListener);
}
/**
* Removes the listener from the collection of listeners who will be
* notified when the row is resized.
*
* @param listener
* the listener which should no longer be notified
*
* @exception IllegalArgumentException
* <ul>
* <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
* </ul>
* @exception SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been
* disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void removeControlListener(ControlListener listener) {
checkWidget();
if (listener == null)
SWT.error(SWT.ERROR_NULL_ARGUMENT);
removeListener(SWT.Resize, listener);
}
/**
* Fires the given event type on the parent Grid instance. This method
* should only be called from within a cell renderer. Any other use is not
* intended.
*
* @param eventId
* SWT event constant
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void fireEvent(int eventId) {
checkWidget();
Event e = new Event();
e.display = getDisplay();
e.widget = this;
e.item = this;
e.type = eventId;
getParent().notifyListeners(eventId, e);
}
/**
* Fires the appropriate events in response to a user checking/unchecking an
* item. Checking an item fires both a selection event (with event.detail of
* SWT.CHECK) if the checkbox is in the first column and the seperate check
* listener (all columns). This method manages that behavior. This method
* should only be called from within a cell renderer. Any other use is not
* intended.
*
* @param column
* the column where the checkbox resides
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void fireCheckEvent(int column) {
checkWidget();
Event selectionEvent = new Event();
selectionEvent.display = getDisplay();
selectionEvent.widget = this;
selectionEvent.item = this;
selectionEvent.type = SWT.Selection;
selectionEvent.detail = SWT.CHECK;
selectionEvent.index = column;
getParent().notifyListeners(SWT.Selection, selectionEvent);
}
/**
* Returns the receiver's background color.
*
* @return the background color
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public Color getBackground() {
checkWidget();
if (defaultBackground == null) {
return parent.getBackground();
}
return defaultBackground;
}
/**
* Returns the background color at the given column index in the receiver.
*
* @param index
* the column index
* @return the background color
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public Color getBackground(int index) {
checkWidget();
handleVirtual();
return parent.getDataVisualizer().getBackground(this, index);
}
/**
* Returns a rectangle describing the receiver's size and location relative
* to its parent at a column in the table.
*
* @param columnIndex
* the index that specifies the column
* @return the receiver's bounding column rectangle
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public Rectangle getBounds(int columnIndex) {
checkWidget();
// HACK: The -1000,-1000 xy coordinates below are a hack to deal with
// GridEditor issues. In
// normal SWT Table, when an editor is created on Table and its
// positioned in the header area
// the header overlays the editor. Because Grid (header and everything)
// is drawn on one
// composite, when an editor is positioned in the header area the editor
// overlays the header.
// So to fix this, when the editor is anywhere its not supposed to be
// seen (the editor
// coordinates are determined by this getBounds) we position it out in
// timbuktu.
if (!isVisible())
return new Rectangle(-1000, -1000, 0, 0);
if (!parent.isShown(this))
return new Rectangle(-1000, -1000, 0, 0);
Point origin = parent.getOrigin(parent.getColumn(columnIndex), this);
if (origin.x < 0 && parent.isRowHeaderVisible())
return new Rectangle(-1000, -1000, 0, 0);
Point cellSize = this.getCellSize(columnIndex);
return new Rectangle(origin.x, origin.y, cellSize.x, cellSize.y);
}
/**
*
* @param columnIndex
* @return width and height
*/
protected Point getCellSize(int columnIndex) {
/* width */
int width = 0;
int span = getColumnSpan(columnIndex);
int[] columnOrder = parent.getColumnOrder();
int visualColumnIndex = columnIndex;
for (int i = 0; i < columnOrder.length; i++) {
if (columnOrder[i] == columnIndex) {
visualColumnIndex = i;
break;
}
}
for (int i = 0; i <= span; i++) {
if (visualColumnIndex + i >= columnOrder.length) {
break;
}
int nextColumnIndex = columnOrder[visualColumnIndex + i];
width += parent.getColumn(nextColumnIndex).getWidth();
}
/* height */
int indexOfCurrentItem = parent.getIndexOfItem(this);
GridItem item = parent.getItem(indexOfCurrentItem);
int height = item.getHeight();
span = getRowSpan(columnIndex);
int itemCount = parent.getItemCount();
for (int i = 1; i <= span; i++) {
/* We will probably need another escape condition here */
if (itemCount <= indexOfCurrentItem + i) {
break;
}
item = parent.getItem(indexOfCurrentItem + i);
if (item.isVisible()) {
height += item.getHeight() + 1;
}
}
return new Point(width, height);
}
/**
* Returns the checked state at the first column in the receiver.
*
* @return the checked state
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public boolean getChecked() {
checkWidget();
return parent.getDataVisualizer().getChecked(this, 0);
}
/**
* Returns the checked state at the given column index in the receiver.
*
* @param index
* the column index
* @return the checked state
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public boolean getChecked(int index) {
checkWidget();
handleVirtual();
return parent.getDataVisualizer().getChecked(this, index);
}
/**
* Returns the column span for the given column index in the receiver.
*
* @param index
* the column index
* @return the number of columns spanned (0 equals no columns spanned)
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public int getColumnSpan(int index) {
checkWidget();
return parent.getDataVisualizer().getColumnSpan(this, index);
}
/**
* Returns the row span for the given column index in the receiver.
*
* @param index
* the row index
* @return the number of row spanned (0 equals no row spanned)
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public int getRowSpan(int index) {
checkWidget();
return parent.getDataVisualizer().getRowSpan(this, index);
}
/**
* Returns the font that the receiver will use to paint textual information
* for this item.
*
* @return the receiver's font
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public Font getFont() {
if (defaultFont == null) {
return parent.getFont();
}
return defaultFont;
}
/**
* Returns the font that the receiver will use to paint textual information
* for the specified cell in this item.
*
* @param index
* the column index
* @return the receiver's font
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public Font getFont(int index) {
checkWidget();
handleVirtual();
return parent.getDataVisualizer().getFont(this, index);
}
/**
* Returns the foreground color that the receiver will use to draw.
*
* @return the receiver's foreground color
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public Color getForeground() {
if (defaultForeground == null) {
return parent.getForeground();
}
return defaultForeground;
}
/**
* Returns the foreground color at the given column index in the receiver.
*
* @param index
* the column index
* @return the foreground color
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public Color getForeground(int index) {
checkWidget();
handleVirtual();
return parent.getDataVisualizer().getForeground(this, index);
}
/**
* Returns <code>true</code> if the first column in the receiver is grayed,
* and false otherwise. When the GridColumn does not have the
* <code>CHECK</code> style, return false.
*
* @return the grayed state of the checkbox
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public boolean getGrayed() {
return getGrayed(0);
}
/**
* Returns <code>true</code> if the column at the given index in the
* receiver is grayed, and false otherwise. When the GridColumn does not
* have the <code>CHECK</code> style, return false.
*
* @param index
* the column index
* @return the grayed state of the checkbox
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public boolean getGrayed(int index) {
checkWidget();
handleVirtual();
return parent.getDataVisualizer().getGrayed(this, index);
}
/**
* Returns the height of this <code>GridItem</code>.
*
* @return height of this <code>GridItem</code>
*/
public int getHeight() {
checkWidget();
return height;
}
/**
* {@inheritDoc}
*/
@Override
public Image getImage() {
checkWidget();
return parent.getDataVisualizer().getImage(this, 0);
}
/**
* Returns the image stored at the given column index in the receiver, or
* null if the image has not been set or if the column does not exist.
*
* @param index
* the column index
* @return the image stored at the given column index in the receiver
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public Image getImage(int index) {
checkWidget();
handleVirtual();
return parent.getDataVisualizer().getImage(this, index);
}
/**
* Returns the item at the given, zero-relative index in the receiver.
* Throws an exception if the index is out of range.
*
* @param index
* the index of the item to return
* @return the item at the given index
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_INVALID_RANGE - if the index is not between 0 and
* the number of elements in the list minus 1 (inclusive)</li>
* </ul>
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public GridItem getItem(int index) {
checkWidget();
if (!hasChildren)
throw new IllegalArgumentException("GridItem has no children!");
return children.get(index);
}
/**
* Returns the number of items contained in the receiver that are direct
* item children of the receiver.
*
* @return the number of items
*
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public int getItemCount() {
checkWidget();
if (!hasChildren)
return 0;
return children.size();
}
/**
* 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
*
* @exception IllegalArgumentException
* <ul>
* <li>ERROR_NULL_ARGUMENT - if the item is null</li>
* <li>ERROR_INVALID_ARGUMENT - if the item has been disposed
* </li>
* </ul>
* @exception SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been
* disposed</li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public int indexOf(GridItem item) {
checkWidget();
if (item == null)
SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (item.isDisposed())
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
if (!hasChildren)
throw new IllegalArgumentException("GridItem has no children!");
return children.indexOf(item);
}
/**
* Returns a (possibly empty) array of <code>GridItem</code>s which are the
* direct item children of the receiver.
* <p>
* 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.
* </p>
*
* @return the receiver's items
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public GridItem[] getItems() {
if (!hasChildren)
return new GridItem[0];
return children.toArray(new GridItem[children.size()]);
}
/**
* Returns the level of this item in the tree.
*
* @return the level of the item in the tree
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public int getLevel() {
checkWidget();
return level;
}
/**
* Returns the receiver's parent, which must be a <code>Grid</code>.
*
* @return the receiver's parent
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public Grid getParent() {
checkWidget();
return parent;
}
/**
* Returns the receiver's parent item, which must be a <code>GridItem</code>
* or null when the receiver is a root.
*
* @return the receiver's parent item
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public GridItem getParentItem() {
checkWidget();
return parentItem;
}
/**
* {@inheritDoc}
*/
@Override
public String getText() {
checkWidget();
return parent.getDataVisualizer().getText(this, 0);
}
/**
* Returns the text stored at the given column index in the receiver, or
* empty string if the text has not been set.
*
* @param index
* the column index
* @return the text stored at the given column index in the receiver
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public String getText(int index) {
checkWidget();
handleVirtual();
return parent.getDataVisualizer().getText(this, index);
}
/**
* Returns true if this item has children.
*
* @return true if this item has children
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public boolean hasChildren() {
checkWidget();
return hasChildren;
}
/**
* Returns <code>true</code> if the receiver is expanded, and false
* otherwise.
* <p>
*
* @return the expanded state
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public boolean isExpanded() {
checkWidget();
return expanded;
}
/**
* Sets the receiver's background color to the color specified by the
* argument, or to the default system color for the item if the argument is
* null.
*
* @param background
* the new color (or null)
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_INVALID_ARGUMENT - if the argument has been
* disposed</li>
* </ul>
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setBackground(Color background) {
checkWidget();
if (background != null && background.isDisposed()) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
for (int i = 0; i < getParent().getColumnCount(); i++) {
setBackground(i, background);
}
defaultBackground = background;
parent.redraw();
}
/**
* Sets the background color at the given column index in the receiver to
* the color specified by the argument, or to the default system color for
* the item if the argument is null.
*
* @param index
* the column index
* @param background
* the new color (or null)
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_INVALID_ARGUMENT - if the argument has been
* disposed</li>
* </ul>
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setBackground(int index, Color background) {
checkWidget();
if (background != null && background.isDisposed()) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
parent.getDataVisualizer().setBackground(this, index, background);
parent.redraw();
}
/**
* Sets the checked state at the first column in the receiver.
*
* @param checked
* the new checked state
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setChecked(boolean checked) {
checkWidget();
parent.getDataVisualizer().setChecked(this, 0, checked);
parent.redraw();
}
/**
* Sets the checked state at the given column index in the receiver.
*
* @param index
* the column index
* @param checked
* the new checked state
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setChecked(int index, boolean checked) {
checkWidget();
parent.getDataVisualizer().setChecked(this, index, checked);
parent.redraw();
}
/**
* Sets the column spanning for the column at the given index to span the
* given number of subsequent columns.
*
* @param index
* column index that should span
* @param span
* number of subsequent columns to span
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setColumnSpan(int index, int span) {
checkWidget();
parent.getDataVisualizer().setColumnSpan(this, index, span);
parent.setHasSpanning(true);
parent.redraw();
}
/**
* Sets the row spanning for the row at the given index to span the given
* number of subsequent rows.
*
* @param index
* row index that should span
* @param span
* number of subsequent rows to span
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setRowSpan(int index, int span) {
checkWidget();
parent.getDataVisualizer().setRowSpan(this, index, span);
parent.setHasSpanning(true);
parent.redraw();
}
/**
* Sets the expanded state of the receiver.
* <p>
*
* @param expanded
* the new expanded state
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setExpanded(boolean expanded) {
checkWidget();
this.expanded = expanded;
// We must unselect any items that are becoming invisible
// and thus if we change the selection we have to fire a selection event
boolean unselected = doUnselect(expanded);
this.getParent().topIndex = NO_ROW;
this.getParent().bottomIndex = NO_ROW;
this.getParent().setScrollValuesObsolete();
if (unselected) {
Event e = new Event();
e.item = this;
getParent().notifyListeners(SWT.Selection, e);
}
if (getParent().getFocusItem() != null && !getParent().getFocusItem().isVisible()) {
getParent().setFocusItem(this);
}
if (getParent().getCellSelectionEnabled()) {
getParent().updateColumnSelection();
}
}
private boolean doUnselect(boolean expanded) {
boolean unselected = false;
if (hasChildren)
for (GridItem item : children) {
item.setVisible(expanded && visible);
if (!expanded) {
if (!getParent().getCellSelectionEnabled()) {
if (getParent().isSelected(item)) {
unselected = true;
getParent().deselect(item.getRowIndex());
}
if (deselectChildren(item)) {
unselected = true;
}
} else {
if (deselectCells(item)) {
unselected = true;
}
}
}
}
return unselected;
}
private boolean deselectCells(GridItem item) {
boolean flag = false;
int index = item.getRowIndex();
GridColumn[] columns = getParent().getColumns();
for (int i = 0; i < columns.length; i++) {
Point cell = new Point(getParent().indexOf(columns[i]), index);
if (getParent().isCellSelected(cell)) {
flag = true;
getParent().deselectCell(cell);
}
}
GridItem[] kids = item.getItems();
for (int i = 0; i < kids.length; i++) {
if (deselectCells(kids[i])) {
flag = true;
}
}
return flag;
}
/**
* Deselects the given item's children recursively.
*
* @param item
* item to deselect children.
* @return true if an item was deselected
*/
private boolean deselectChildren(GridItem item) {
boolean flag = false;
GridItem[] kids = item.getItems();
for (int i = 0; i < kids.length; i++) {
if (getParent().isSelected(kids[i])) {
flag = true;
}
getParent().deselect(kids[i].getRowIndex());
if (deselectChildren(kids[i])) {
flag = true;
}
}
return flag;
}
/**
* Sets the font that the receiver will use to paint textual information for
* this item to the font specified by the argument, or to the default font
* for that kind of control if the argument is null.
*
* @param f
* the new font (or null)
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_INVALID_ARGUMENT - if the argument has been
* disposed</li>
* </ul>
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setFont(Font f) {
checkWidget();
if (f != null && f.isDisposed()) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
defaultFont = f;
parent.redraw();
}
/**
* Sets the font that the receiver will use to paint textual information for
* the specified cell in this item to the font specified by the argument, or
* to the default font for that kind of control if the argument is null.
*
* @param index
* the column index
* @param font
* the new font (or null)
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_INVALID_ARGUMENT - if the argument has been
* disposed</li>
* </ul>
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setFont(int index, Font font) {
checkWidget();
if (font != null && font.isDisposed()) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
parent.getDataVisualizer().setFont(this, index, font);
parent.redraw();
}
/**
* Sets the receiver's foreground color to the color specified by the
* argument, or to the default system color for the item if the argument is
* null.
*
* @param foreground
* the new color (or null)
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_INVALID_ARGUMENT - if the argument has been
* disposed</li>
* </ul>
* @throws SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setForeground(Color foreground) {
checkWidget();
if (foreground != null && foreground.isDisposed()) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
for (int i = 0; i < getParent().getColumnCount(); i++) {
setForeground(i, foreground);
}
defaultForeground = foreground;
parent.redraw();
}
/**
* Sets the foreground color at the given column index in the receiver to
* the color specified by the argument, or to the default system color for
* the item if the argument is null.
*
* @param index
* the column index
* @param foreground
* the new color (or null)
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_INVALID_ARGUMENT - if the argument has been
* disposed</li>
* </ul>
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setForeground(int index, Color foreground) {
checkWidget();
if (foreground != null && foreground.isDisposed()) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
parent.getDataVisualizer().setForeground(this, index, foreground);
parent.redraw();
}
/**
* Sets the grayed state of the checkbox for the first column. This state
* change only applies if the GridColumn was created with the SWT.CHECK
* style.
*
* @param grayed
* the new grayed state of the checkbox;
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setGrayed(boolean grayed) {
checkWidget();
parent.getDataVisualizer().setGrayed(this, 0, grayed);
parent.redraw();
}
/**
* Sets the grayed state of the checkbox for the given column index. This
* state change only applies if the GridColumn was created with the
* SWT.CHECK style.
*
* @param index
* the column index
* @param grayed
* the new grayed state of the checkbox;
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setGrayed(int index, boolean grayed) {
checkWidget();
parent.getDataVisualizer().setGrayed(this, index, grayed);
parent.redraw();
}
/**
* Sets the height of this <code>GridItem</code>.
*
* @param newHeight
* new height in pixels
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setHeight(int newHeight) {
checkWidget();
if (newHeight < 1)
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
height = newHeight;
parent.hasDifferingHeights = true;
if (isVisible()) {
int myIndex = this.getRowIndex();
// note: cannot use Grid#isShown() here, because that returns false
// for partially shown items
if (parent.getTopIndex() <= myIndex && myIndex <= parent.getBottomIndex())
parent.bottomIndex = NO_ROW;
}
parent.setScrollValuesObsolete();
parent.redraw();
}
/**
* Sets this <code>GridItem</code> to its preferred height.
*
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void pack() {
checkWidget();
int maxPrefHeight = 2;
GridColumn[] columns = parent.getColumns();
GC gc = new GC(parent);
for (int cnt = 0; cnt < columns.length; cnt++) {
if (!columns[cnt].isVisible())
continue; // invisible columns do not affect item/row height
GridCellRenderer renderer = columns[cnt].getCellRenderer();
renderer.setAlignment(columns[cnt].getAlignment());
renderer.setCheck(columns[cnt].isCheck());
renderer.setColumn(cnt);
renderer.setTree(columns[cnt].isTree());
renderer.setWordWrap(columns[cnt].getWordWrap());
Point size = renderer.computeSize(gc, columns[cnt].getWidth(), SWT.DEFAULT, this);
if (size != null)
maxPrefHeight = Math.max(maxPrefHeight, size.y);
}
gc.dispose();
setHeight(maxPrefHeight);
}
/**
* {@inheritDoc}
*/
@Override
public void setImage(Image image) {
parent.getDataVisualizer().setImage(this, 0, image);
parent.redraw();
}
/**
* Sets the receiver's image at a column.
*
* @param index
* the column index
* @param image
* the new image
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_INVALID_ARGUMENT - if the image has been disposed
* </li>
* </ul>
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setImage(int index, Image image) {
checkWidget();
if (image != null && image.isDisposed()) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
parent.getDataVisualizer().setImage(this, index, image);
parent.imageSetOnItem(index, this);
parent.redraw();
}
/**
* Sets the receiver's text at a column.
*
* @param index
* the column index
* @param text
* the new text
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_NULL_ARGUMENT - if the text is null</li>
* </ul>
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setText(int index, String text) {
checkWidget();
if (text == null) {
SWT.error(SWT.ERROR_NULL_ARGUMENT);
}
parent.getDataVisualizer().setText(this, index, text);
parent.redraw();
}
/**
* {@inheritDoc}
*/
@Override
public void setText(String string) {
parent.getDataVisualizer().setText(this, 0, string);
parent.redraw();
}
/**
* Removes the given child item from the list of children.
*
* @param child
* child to remove
*/
private void remove(GridItem child) {
if (!hasChildren)
throw new IllegalArgumentException("GridItem has no children!");
children.remove(child);
parent.getDataVisualizer().clearRow(child);
hasChildren = !children.isEmpty();
}
/**
* Returns true if the item is visible because its parent items are all
* expanded. This method does not determine if the item is in the currently
* visible range.
*
* @return Returns the visible.
*/
public boolean isVisible() {
return visible;
}
/**
* Creates a new child item in this item at the given index.
*
* @param item
* new child item
* @param index
* index
*/
void newItem(GridItem item, int index) {
setHasChildren(true);
if (children == null)
children = new ArrayList<GridItem>();
if (index == NO_ROW) {
children.add(item);
} else {
children.add(index, item);
}
}
/**
* Sets whether this item has children.
*
* @param hasChildren
* true if this item has children
*/
void setHasChildren(boolean hasChildren) {
this.hasChildren = hasChildren;
}
/**
* Sets the visible state of this item. The visible state is determined by
* the expansion state of all of its parent items. If all parent items are
* expanded it is visible.
*
* @param visible
* The visible to set.
*/
void setVisible(boolean visible) {
if (this.visible == visible) {
return;
}
this.visible = visible;
if (visible) {
parent.updateVisibleItems(1);
} else {
parent.updateVisibleItems(NO_ROW);
}
if (hasChildren) {
boolean childrenVisible = visible;
if (visible) {
childrenVisible = expanded;
}
for (GridItem item : children) {
item.setVisible(childrenVisible);
}
}
}
/**
* Returns the receiver's row header text. If the text is <code>null</code>
* the row header will display the row number.
*
* @return the text stored for the row header or code <code>null</code> if
* the default has to be displayed
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public String getHeaderText() {
checkWidget();
// handleVirtual();
return headerText;
}
/**
* Returns the receiver's row header image.
*
* @return the image stored for the header or <code>null</code> if none has
* to be displayed
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public Image getHeaderImage() {
checkWidget();
return headerImage;
}
/**
* Returns the receiver's row header background color
*
* @return the color or <code>null</code> if none
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public Color getHeaderBackground() {
checkWidget();
return headerBackground;
}
/**
* Returns the receiver's row header foreground color
*
* @return the color or <code>null</code> if none
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public Color getHeaderForeground() {
checkWidget();
return headerForeground;
}
/**
* Sets the receiver's row header text. If the text is <code>null</code> the
* row header will display the row number.
*
* @param text
* the new text
* @throws IllegalArgumentException
* <ul>
* <li>ERROR_NULL_ARGUMENT - if the text is null</li>
* </ul>
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setHeaderText(String text) {
checkWidget();
// if (text == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (text != headerText) {
GC gc = new GC(parent);
int oldWidth = headerText == null ? 0
: parent.getRowHeaderRenderer().computeSize(gc, SWT.DEFAULT, SWT.DEFAULT, this).x;
this.headerText = text;
int newWidth = parent.getRowHeaderRenderer().computeSize(gc, SWT.DEFAULT, SWT.DEFAULT, this).x;
gc.dispose();
parent.recalculateRowHeaderWidth(this, oldWidth, newWidth);
}
parent.redraw();
}
/**
* Sets the receiver's row header image. If the image is <code>null</code>
* none is shown in the header
*
* @param image
* the new image
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setHeaderImage(Image image) {
checkWidget();
// if (text == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (image != headerImage) {
GC gc = new GC(parent);
int oldWidth = parent.getRowHeaderRenderer().computeSize(gc, SWT.DEFAULT, SWT.DEFAULT, this).x;
int oldHeight = parent.getRowHeaderRenderer().computeSize(gc, SWT.DEFAULT, SWT.DEFAULT, this).y;
this.headerImage = image;
int newWidth = parent.getRowHeaderRenderer().computeSize(gc, SWT.DEFAULT, SWT.DEFAULT, this).x;
int newHeight = parent.getRowHeaderRenderer().computeSize(gc, SWT.DEFAULT, SWT.DEFAULT, this).y;
gc.dispose();
parent.recalculateRowHeaderWidth(this, oldWidth, newWidth);
parent.recalculateRowHeaderHeight(this, oldHeight, newHeight);
}
parent.redraw();
}
/**
* Set the new header background
*
* @param headerBackground
* the color or <code>null</code>
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setHeaderBackground(Color headerBackground) {
checkWidget();
this.headerBackground = headerBackground;
parent.redraw();
}
/**
* Set the new header foreground
*
* @param headerForeground
* the color or <code>null</code>
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setHeaderForeground(Color headerForeground) {
checkWidget();
this.headerForeground = headerForeground;
parent.redraw();
}
/**
* Returns the checkable state at the given column index in the receiver. If
* the column at the given index is not checkable then this will return
* false regardless of the individual cell's checkable state.
*
* @param index
* the column index
* @return the checked state
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public boolean getCheckable(int index) {
checkWidget();
if (!parent.getColumn(index).getCheckable())
return false;
return parent.getDataVisualizer().getCheckable(this, index);
}
/**
* Sets the checkable state at the given column index in the receiver. A
* checkbox which is uncheckable will not be modifiable by the user but
* still make be modified programmatically. If the column at the given index
* is not checkable then individual cell will not be checkable regardless.
*
* @param index
* the column index
* @param checked
* the new checked state
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setCheckable(int index, boolean checked) {
checkWidget();
parent.getDataVisualizer().setCheckable(this, index, checked);
}
/**
* Returns the tooltip for the given cell.
*
* @param index
* the column index
* @return the tooltip
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public String getToolTipText(int index) {
checkWidget();
handleVirtual();
return parent.getDataVisualizer().getToolTipText(this, index);
}
/**
* Sets the tooltip for the given column index.
*
* @param index
* the column index
* @param tooltip
* the tooltip text
* @throws org.eclipse.swt.SWTException
* <ul>
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* </li>
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
* thread that created the receiver</li>
* </ul>
*/
public void setToolTipText(int index, String tooltip) {
checkWidget();
parent.getDataVisualizer().setToolTipText(this, index, tooltip);
}
void columnAdded(int index) {
hasSetData = false;
}
private void handleVirtual() {
if ((getParent().getStyle() & SWT.VIRTUAL) != 0 && !hasSetData) {
hasSetData = true;
Event event = new Event();
event.item = this;
if (parentItem == null) {
event.index = getRowIndex();
} else {
event.index = parentItem.indexOf(this);
}
getParent().notifyListeners(SWT.SetData, event);
}
}
/**
* Sets the initial item height for this item.
*
* @param height
* initial height.
*/
void initializeHeight(int height) {
this.height = height;
}
void setHasSetData(boolean hasSetData) {
this.hasSetData = hasSetData;
}
/**
* Clears all properties of this item and resets values to their defaults.
*
* @param allChildren
* <code>true</code> if all child items should be cleared
* recursively, and <code>false</code> otherwise
*/
void clear(boolean allChildren) {
defaultForeground = null;
defaultBackground = null;
defaultFont = null;
hasSetData = false;
headerText = null;
headerImage = null;
headerBackground = null;
headerForeground = null;
// Recursively clear children if requested.
if (allChildren && hasChildren) {
for (int i = children.size() - 1; i >= 0; i--) {
children.get(i).clear(true);
}
}
}
/**
* this method call only super.dispose, nothing else..
*/
public void disposeOnly() {
if (hasChildren)
for (int i = children.size() - 1; i >= 0; i--) {
children.get(i).disposeOnly();
}
if (parent.getDataVisualizer() != null) {
parent.getDataVisualizer().clearRow(this);
}
noRow();
super.dispose();
}
private void noRow() {
synchronized (ROW_LOCK) {
row = NO_ROW;
}
}
}