| /******************************************************************************* |
| * Copyright (c) 2000, 2003 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.swt.widgets; |
| |
| |
| import org.eclipse.swt.events.*; |
| import org.eclipse.swt.graphics.*; |
| import org.eclipse.swt.*; |
| import java.util.Enumeration; |
| import java.util.Vector; |
| |
| /** |
| * Instances of this class implement a selectable user interface |
| * object that displays a list of images and strings and issue |
| * notificiation when selected. |
| * <p> |
| * The item children that may be added to instances of this class |
| * must be of type <code>TableItem</code>. |
| * </p><p> |
| * Note that although this class is a subclass of <code>Composite</code>, |
| * it does not make sense to add <code>Control</code> children to it, |
| * or set a layout on it. |
| * </p><p> |
| * <dl> |
| * <dt><b>Styles:</b></dt> |
| * <dd>SINGLE, MULTI, CHECK, FULL_SELECTION, HIDE_SELECTION</dd> |
| * <dt><b>Events:</b></dt> |
| * <dd>Selection, DefaultSelection</dd> |
| * </dl> |
| * <p> |
| * Note: Only one of the styles SINGLE, and MULTI may be specified. |
| * </p><p> |
| * IMPORTANT: This class is <em>not</em> intended to be subclassed. |
| * </p> |
| */ |
| public class Table extends SelectableItemWidget { |
| private static final int COLUMN_RESIZE_OFFSET = 7; // offset from the start and end of each |
| // column at which the resize cursor is displayed |
| // if the mouse is in the column header |
| static final String DOT_STRING = "..."; // used to indicate truncated item labels |
| |
| private Header tableHeader; |
| private Vector items; |
| private Vector columns; |
| private boolean drawGridLines = false; |
| private boolean firstColumnImage = false; // true if any item in the first column has an image |
| private int columnResizeX; // last position of the cursor in a column resize operation |
| private Cursor columnResizeCursor; // cursor displayed when a column resize is in progress. |
| // Need to keep reference to the cursor in order to dispose it. |
| private boolean isColumnResizeCursor = false; // set to true if the column resize cursor is active |
| private TableColumn resizeColumn; // column that is currently being resized |
| private TableColumn fillColumn; // column used to fill up space that is not used |
| // by user defined columns |
| private TableColumn defaultColumn; // Default column that is created as soon as the table is created. |
| // Fix for 1FUSJY5 |
| private int fontHeight; // font height, avoid use GC.stringExtend for each pain |
| |
| private boolean ignoreRedraw; |
| |
| /** |
| * Constructs a new instance of this class given its parent |
| * and a style value describing its behavior and appearance. |
| * <p> |
| * The style value is either one of the style constants defined in |
| * class <code>SWT</code> which is applicable to instances of this |
| * class, or must be built by <em>bitwise OR</em>'ing together |
| * (that is, using the <code>int</code> "|" operator) two or more |
| * of those <code>SWT</code> style constants. The class description |
| * lists the style constants that are applicable to the class. |
| * Style bits are also inherited from superclasses. |
| * </p> |
| * |
| * @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 |
| * |
| * @exception IllegalArgumentException <ul> |
| * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> |
| * </ul> |
| * @exception 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> |
| * |
| * @see SWT#SINGLE |
| * @see SWT#MULTI |
| * @see SWT#CHECK |
| * @see SWT#FULL_SELECTION |
| * @see SWT#HIDE_SELECTION |
| * @see Widget#checkSubclass |
| * @see Widget#getStyle |
| */ |
| public Table(Composite parent, int style) { |
| // use NO_REDRAW_RESIZE to avoid flashing during widget resize redraw |
| super(parent, checkStyle(style| SWT.NO_REDRAW_RESIZE)); |
| } |
| |
| /** |
| * Add 'column' to the receiver. |
| * @param column - new table column that should be added to |
| * the receiver |
| */ |
| void addColumn(TableColumn column) { |
| int index = column.getIndex(); |
| |
| getColumnVector().insertElementAt(column, index); |
| // has the column been inserted (vs. appended)? |
| if (index < getColumnCount() - 1) { |
| reindexColumns(index + 1); |
| } |
| // is there more than one user created column? |
| // There always is the data and visual of the default column |
| // so we don't need to create those for the first user column |
| int columnCount = getColumnCount(); |
| if (columnCount > 1) { |
| insertColumnData(column); |
| Enumeration items = getItemVector ().elements (); |
| while (items.hasMoreElements()) { |
| TableItem item = (TableItem)items.nextElement(); |
| Color [] cellBackground = item.cellBackground; |
| if (cellBackground != null) { |
| Color [] temp = new Color [columnCount]; |
| System.arraycopy (cellBackground, 0, temp, 0, index); |
| System.arraycopy (cellBackground, index, temp, index+1, columnCount - index - 1); |
| item.cellBackground = temp; |
| } |
| Color [] cellForeground = item.cellForeground; |
| if (cellForeground != null) { |
| Color [] temp = new Color [columnCount]; |
| System.arraycopy (cellForeground, 0, temp, 0, index); |
| System.arraycopy (cellForeground, index, temp, index+1, columnCount - index - 1); |
| item.cellForeground = temp; |
| } |
| Font [] cellFont = item.cellFont; |
| if (cellFont != null) { |
| Font [] temp = new Font [columnCount]; |
| System.arraycopy (cellFont, 0, temp, 0, index); |
| System.arraycopy (cellFont, index, temp, index+1, columnCount - index - 1); |
| item.cellFont = temp; |
| } |
| } |
| |
| } |
| else { // first user created column |
| setContentWidth(0); // pretend it's ground zero for column resizings |
| redraw(); // redraw the table and header. The default column |
| getHeader().redraw(); // won't be drawn anymore, because there now is a user created table. |
| } |
| insertColumnVisual(column); |
| } |
| /** |
| * Add 'item' to the receiver. |
| * @param item - new table item that should be added to |
| * the receiver |
| * @param index - position the new item should be inserted at |
| */ |
| void addItem(TableItem item, int index) { |
| Vector items = getItemVector(); |
| |
| if (index < 0 || index > getItemCount()) { |
| error(SWT.ERROR_INVALID_RANGE); |
| } |
| addingItem(item, index); |
| item.setIndex(index); |
| if (index < items.size()) { |
| for (int i = index; i < items.size(); i++) { |
| TableItem anItem = (TableItem) items.elementAt(i); |
| anItem.setIndex(anItem.getIndex() + 1); |
| } |
| items.insertElementAt(item, index); |
| } |
| else { |
| items.addElement(item); |
| } |
| addedItem(item, index); |
| } |
| /** |
| * 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</code> |
| * interface. |
| * <p> |
| * When <code>widgetSelected</code> is called, the item field of the event object is valid. |
| * If the reciever has <code>SWT.CHECK</code> style set and the check selection changes, |
| * the event object detail field contains the value <code>SWT.CHECK</code>. |
| * <code>widgetDefaultSelected</code> is typically called when an item is double-clicked. |
| * The item field of the event object is valid for default selection, but the detail field is not used. |
| * </p> |
| * |
| * @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> |
| * |
| * @see SelectionListener |
| * @see #removeSelectionListener |
| * @see SelectionEvent |
| */ |
| public void addSelectionListener (SelectionListener listener) { |
| checkWidget(); |
| if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); |
| TypedListener typedListener = new TypedListener(listener); |
| addListener(SWT.Selection,typedListener); |
| addListener(SWT.DefaultSelection,typedListener); |
| } |
| static int checkStyle (int style) { |
| return checkBits (style, SWT.SINGLE, SWT.MULTI, 0, 0, 0, 0); |
| } |
| protected void checkSubclass () { |
| if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS); |
| } |
| public void clear (int index) { |
| checkWidget (); |
| if (!(0 <= index && index < getItemCount())) { |
| error(SWT.ERROR_INVALID_RANGE); |
| } |
| TableItem item = (TableItem) getVisibleItem(index); |
| item.clear(); |
| int y = getRedrawY(item); |
| redraw(0, y, getClientArea().width, getItemHeight(), false); |
| } |
| public void clear (int start, int end) { |
| checkWidget (); |
| if (start > end) return; |
| if (!(0 <= start && start <= end && end < getItemCount())) { |
| error(SWT.ERROR_INVALID_RANGE); |
| } |
| if (start == 0 && end == getItemCount() - 1) { |
| clearAll(); |
| } else { |
| for (int i=start; i<=end; i++) { |
| clear(i); |
| } |
| } |
| } |
| public void clear (int [] indices) { |
| checkWidget (); |
| if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); |
| if (indices.length == 0) return; |
| for (int i=0; i<indices.length; i++) { |
| if (!(0 <= indices [i] && indices [i] < getItemCount())) { |
| error(SWT.ERROR_INVALID_RANGE); |
| } |
| } |
| for (int i=0; i<indices.length; i++) { |
| clear(indices [i]); |
| } |
| } |
| public void clearAll () { |
| checkWidget (); |
| for (int i=0; i<getItemCount(); i++) { |
| TableItem item = (TableItem) getVisibleItem(i); |
| item.clear(); |
| } |
| redraw(); |
| } |
| /** |
| * The width of 'column' is about to change. |
| * Adjust the position of all columns behind it. |
| */ |
| void columnChange(TableColumn column, Rectangle newBounds) { |
| Rectangle columnBounds = column.getBounds(); |
| Rectangle clientArea = getClientArea(); |
| int oldXPosition = columnBounds.x + columnBounds.width; |
| int newXPosition = newBounds.x + newBounds.width; |
| int widthChange = newBounds.width - columnBounds.width; |
| int headerHeight = getHeaderHeight(); |
| int columnIndex = column.getIndex(); |
| |
| if (widthChange != 0) { |
| getHeader().widthChange(columnIndex, widthChange); |
| if (columnIndex != TableColumn.FILL) { |
| if (getLinesVisible() == true) { |
| oldXPosition -= getGridLineWidth(); // include vertical grid line when scrolling resized column. |
| newXPosition -= getGridLineWidth(); |
| } |
| scroll( // physically move all following columns |
| newXPosition, headerHeight, // destination x, y |
| oldXPosition, headerHeight, // source x, y |
| clientArea.width, clientArea.height, true); |
| } |
| column.internalSetBounds(newBounds); |
| if (columnIndex != TableColumn.FILL) { |
| resetTableItems(columnIndex); |
| moveColumns(columnIndex + 1, widthChange); // logically move all following columns (set their bounds) |
| setContentWidth(getContentWidth() + widthChange); // set the width of the receiver's content |
| claimRightFreeSpace(); |
| resizeRedraw(column, columnBounds.width, newBounds.width); |
| } |
| } |
| } |
| /** |
| * The mouse pointer was double clicked on the receiver. |
| * Handle the event according to the position of the mouse click |
| * and the modifier key that was pressed, if any. |
| * @param event - the mouse event |
| */ |
| void columnMouseDoubleClick(Event event) { |
| int itemHeight = getItemHeight(); |
| int itemIndex; |
| TableItem hitItem; |
| TableColumn hitColumn = getColumnAtX (event.x); |
| Event columnDblClickEvent; |
| boolean isFullSelection = (getStyle () & SWT.FULL_SELECTION) != 0; |
| |
| if (isFocusControl () == false) { |
| forceFocus (); |
| } |
| if (hitColumn != null) { |
| itemIndex = (event.y - getHeaderHeight()) / itemHeight + getTopIndex(); |
| hitItem = (TableItem) getVisibleItem(itemIndex); |
| if (hitItem != null && |
| (hitColumn.getIndex() == TableColumn.FIRST || isFullSelection)) { |
| if (hitItem.isSelectionHit(event.x) == true) { |
| columnDblClickEvent = new Event(); |
| columnDblClickEvent.item = hitItem; |
| notifyListeners(SWT.DefaultSelection, columnDblClickEvent); |
| } |
| } |
| } |
| } |
| /** |
| * The mouse pointer was pressed down on the receiver. |
| * Handle the event according to the position of the mouse click |
| * and the modifier key that was pressed, if any. |
| * @param event - the mouse event |
| */ |
| void columnMouseDown(Event event) { |
| int itemHeight = getItemHeight(); |
| int itemIndex; |
| TableItem hitItem; |
| TableColumn hitColumn = getColumnAtX (event.x); |
| |
| if (isFocusControl () == false) { |
| forceFocus (); |
| } |
| if (hitColumn != null) { |
| itemIndex = (event.y - getHeaderHeight()) / itemHeight + getTopIndex(); |
| hitItem = (TableItem) getVisibleItem(itemIndex); |
| if (hitItem != null) { |
| if (hitItem.isSelectionHit(event.x) == true) { |
| doMouseSelect(hitItem, itemIndex, event.stateMask, event.button); |
| } |
| else |
| if (hitItem.isCheckHit(new Point(event.x, event.y)) == true) { |
| // only react to button one clicks. fixes bug 6770 |
| if (event.button != 1) { |
| return; |
| } |
| doCheckItem(hitItem); |
| } |
| } |
| } |
| } |
| /** |
| * The mouse pointer was moved over the receiver. |
| * Reset the column resize cursor if it was active. |
| * @param event - the mouse event |
| */ |
| void columnMouseMove(Event event) { |
| if (isColumnResizeStarted() == false) { |
| setColumnResizeCursor(false); |
| } |
| } |
| public Point computeSize(int wHint, int hHint, boolean changed) { |
| checkWidget(); |
| Point size = super.computeSize(wHint, hHint, changed); |
| Point headerSize; |
| GC gc; |
| final int WidthCalculationCount = Math.min(getItemCount(), 50); // calculate item width for the first couple of items only |
| TableItem item; |
| Image itemImage; |
| String itemText; |
| int width; |
| int newItemWidth = 0; |
| |
| if (getHeaderVisible() == true && hHint == SWT.DEFAULT) { |
| headerSize = getHeader().computeSize(SWT.DEFAULT, SWT.DEFAULT, false); |
| size.y += headerSize.y; |
| } |
| if (getContentWidth() == 0 && WidthCalculationCount > 0) { |
| gc = new GC(this); |
| for (int i = 0; i < WidthCalculationCount; i++) { |
| item = getItem(i); |
| if (item == null) { |
| break; // no more items |
| } |
| itemImage = item.getImage(); |
| itemText = item.getText(); |
| width = 0; |
| if (itemImage != null) { |
| width += itemImage.getBounds().width; |
| } |
| if (itemText != null) { |
| gc.setFont(item.getFont()); |
| width += gc.stringExtent(itemText).x; |
| } |
| newItemWidth = Math.max(newItemWidth, width); |
| } |
| if (newItemWidth > 0) { |
| size.x = newItemWidth; |
| } |
| gc.dispose(); |
| } |
| return size; |
| } |
| /** |
| * 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. |
| * |
| * @param indices the array of indices for the items to deselect |
| * |
| * @exception IllegalArgumentException <ul> |
| * <li>ERROR_NULL_ARGUMENT - if the set of indices 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 deselect(int indices[]) { |
| checkWidget(); |
| SelectableItem item = null; |
| |
| if (indices == null) { |
| error(SWT.ERROR_NULL_ARGUMENT); |
| } |
| for (int i = 0; i < indices.length; i++) { |
| item = getVisibleItem(indices[i]); |
| if (item != null) { |
| deselect(item); |
| } |
| } |
| if (item != null) { |
| setLastSelection(item, false); |
| } |
| } |
| /** |
| * 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. |
| * |
| * @param index the index of the item to deselect |
| * |
| * @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 deselect(int index) { |
| checkWidget(); |
| SelectableItem item = getVisibleItem(index); |
| |
| if (item != null) { |
| deselect(item); |
| setLastSelection(item, false); |
| } |
| } |
| /** |
| * 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. |
| * |
| * @param start the start index of the items to deselect |
| * @param end the end index of the items to deselect |
| * |
| * @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 deselect(int start, int end) { |
| checkWidget(); |
| SelectableItem item = null; |
| |
| for (int i=start; i<=end; i++) { |
| item = getVisibleItem(i); |
| if (item != null) { |
| deselect(item); |
| } |
| } |
| if (item != null) { |
| setLastSelection(item, false); |
| } |
| } |
| /** |
| * Deselects all selected items in the receiver. |
| * |
| * @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 deselectAll() { |
| checkWidget(); |
| |
| deselectAllExcept((SelectableItem) null); |
| } |
| /** |
| * Free resources. |
| */ |
| void doDispose() { |
| Vector items = getItemVector(); |
| |
| super.doDispose(); |
| for (int i = items.size() - 1; i >= 0; i--) { |
| ((TableItem) items.elementAt(i)).dispose(); |
| } |
| setItemVector(null); |
| items = getColumnVector(); |
| while (items.size() > 0) { // TableColumn objects are removed from vector during dispose() |
| ((TableColumn) items.lastElement()).dispose(); |
| } |
| resizeColumn = null; |
| fillColumn = null; |
| defaultColumn = null; |
| if (columnResizeCursor != null) { |
| columnResizeCursor.dispose(); |
| } |
| } |
| /** |
| * Draw a line tracking the current position of a column |
| * resize operation. |
| * @param xPosition - x coordinate to draw the line at |
| */ |
| void drawColumnResizeLine(int xPosition) { |
| GC gc = new GC(this); |
| int lineHeight = getClientArea().height; |
| int lineWidth = getGridLineWidth(); |
| |
| redraw(getColumnResizeX() - lineWidth, 0, 1, lineHeight, false); |
| setColumnResizeX(xPosition); |
| gc.drawLine(xPosition - lineWidth, 0, xPosition - lineWidth, lineHeight); |
| gc.dispose(); |
| } |
| /** |
| * Draw the grid lines for the receiver. |
| * @param event - Paint event triggering the drawing operation. |
| * @param drawColumns - The table columns for which the grid |
| * lines should be drawn. |
| */ |
| void drawGridLines(Event event, Enumeration drawColumns) { |
| GC gc = event.gc; |
| Color oldForeground = getForeground(); |
| Rectangle columnBounds; |
| TableColumn column; |
| int lineWidth = getGridLineWidth(); |
| int itemHeight = getItemHeight(); |
| int headerHeight = getHeaderHeight(); |
| int lineXPosition; |
| int lineYPosition = headerHeight + ((event.y-headerHeight) / itemHeight) * itemHeight; |
| int lineYStopPosition = event.y + event.height; |
| |
| gc.setForeground(display.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW)); |
| // Draw the horizontal lines |
| if (itemHeight > 0) { |
| while (lineYPosition < lineYStopPosition) { |
| gc.drawLine( |
| event.x, lineYPosition + itemHeight - lineWidth, |
| event.x + event.width, lineYPosition + itemHeight - lineWidth); |
| lineYPosition += itemHeight; |
| } |
| } |
| // Draw the vertical lines at the right border of each column except the fill column |
| while (drawColumns.hasMoreElements() == true) { |
| column = (TableColumn) drawColumns.nextElement(); |
| if (column.getIndex() != TableColumn.FILL) { |
| columnBounds = column.getBounds(); |
| lineXPosition = columnBounds.x + columnBounds.width - lineWidth; |
| gc.drawLine( |
| lineXPosition, event.y, |
| lineXPosition, event.y + event.height); |
| } |
| } |
| gc.setForeground(oldForeground); |
| } |
| |
| /** |
| * If the receiver has input focus draw a rectangle enclosing |
| * the label of 'item' to indicate the input focus. |
| * The rectangle is drawn in either the first column or in all columns |
| * for full row select. |
| * @param item - item for which the selection state should be drawn |
| * @param gc - GC to draw on. |
| */ |
| void drawSelectionFocus(TableItem item, GC gc) { |
| Point extent = item.getSelectionExtent(); |
| Point position = new Point( |
| item.getImageStopX(TableColumn.FIRST) + getHorizontalOffset(), |
| getRedrawY(item)); |
| |
| gc.drawFocus(position.x, position.y, extent.x, extent.y); |
| } |
| |
| /** |
| * Returns an array containing the receiver's children. |
| * <p> |
| * Note: This is not the actual structure used by the receiver |
| * to maintain its list of children, so modifying the array will |
| * not affect the receiver. |
| * </p> |
| * |
| * @return an array of children |
| * |
| * @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 Control [] getChildren() { |
| checkWidget(); |
| Control[] controls = _getChildren(); |
| if (tableHeader == null) return controls; |
| Control[] result = new Control[controls.length - 1]; |
| // remove the Header from the returned set of children |
| int index = 0; |
| for (int i = 0; i < controls.length; i++) { |
| if (controls[i] != tableHeader) { |
| result[index++] = controls[i]; |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * 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>TableColumn</code>s were created by the programmer, |
| * this method will throw <code>ERROR_INVALID_RANGE</code> despite |
| * the fact that a single column of data may be visible in the table. |
| * This occurs when the programmer uses the table like a list, adding |
| * items but never creating a column. |
| * |
| * @param index the index of the column to return |
| * @return the column at the given index |
| * |
| * @exception IllegalArgumentException <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> |
| * @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 TableColumn getColumn(int index) { |
| checkWidget(); |
| Vector columns = getColumnVector(); |
| |
| if (columns == null) error(SWT.ERROR_CANNOT_GET_ITEM); |
| if (index < 0 || index >= columns.size()) { |
| error(SWT.ERROR_INVALID_RANGE); |
| } |
| |
| return (TableColumn) columns.elementAt(index); |
| } |
| /** |
| * Return the column located at 'xPosition' in the widget. |
| * Return null if xPosition is outside the widget. |
| * @param xPosition - position of the desired column |
| */ |
| TableColumn getColumnAtX(int xPosition) { |
| Enumeration columns = internalGetColumnVector().elements(); |
| TableColumn column; |
| TableColumn hitColumn = null; |
| Rectangle bounds; |
| |
| while (columns.hasMoreElements() == true && hitColumn == null) { |
| column = (TableColumn) columns.nextElement(); |
| bounds = column.getBounds(); |
| if ((xPosition >= bounds.x) && |
| (xPosition <= bounds.x + bounds.width)) { |
| hitColumn = column; |
| } |
| } |
| if (hitColumn == null) { |
| column = getFillColumn(); |
| bounds = column.getBounds(); |
| if ((xPosition >= bounds.x) && |
| (xPosition <= bounds.x + bounds.width)) { |
| hitColumn = column; |
| } |
| } |
| return hitColumn; |
| } |
| /** |
| * Returns the number of columns contained in the receiver. |
| * If no <code>TableColumn</code>s were created by the programmer, |
| * this value is zero, despite the fact that visually, one column |
| * of items is 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 |
| * |
| * @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> |
| * @exception SWTError <ul> |
| * <li>ERROR_CANNOT_GET_COUNT - if the operation fails because of an operating system failure</li> |
| * </ul> |
| */ |
| public int getColumnCount() { |
| checkWidget(); |
| Vector columns = getColumnVector(); |
| int count = 0; |
| |
| if (columns != null) { |
| count = columns.size(); |
| } |
| return count; |
| } |
| /** Replace CURSOR_SIZEWE with real column resize cursor |
| * (no standard cursor-have to load from file) |
| * Answer the cursor displayed during a column resize |
| * operation. |
| * Lazy initialize the cursor since it may never be needed. |
| */ |
| Cursor getColumnResizeCursor() { |
| if (columnResizeCursor == null) { |
| columnResizeCursor = new Cursor(display, SWT.CURSOR_SIZEWE); |
| } |
| return columnResizeCursor; |
| } |
| /** |
| * Answer the current position of the mouse cursor during |
| * a column resize operation. |
| */ |
| int getColumnResizeX() { |
| return columnResizeX; |
| } |
| /** |
| * Returns an array of <code>TableColumn</code>s which are the |
| * columns in the receiver. If no <code>TableColumn</code>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. |
| * <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 items in the receiver |
| * |
| * @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 TableColumn [] getColumns() { |
| checkWidget(); |
| Vector columns = getColumnVector(); |
| TableColumn columnArray[] = new TableColumn[columns.size()]; |
| |
| columns.copyInto(columnArray); |
| return columnArray; |
| } |
| /** |
| * Answer a Vector containing all columns of receiver except |
| * the fill column to the right of all content columns. |
| */ |
| Vector getColumnVector() { |
| return columns; |
| } |
| /** |
| * Return the default column that is created as soon as the table |
| * is created. |
| * Fix for 1FUSJY5 |
| */ |
| TableColumn getDefaultColumn() { |
| return defaultColumn; |
| } |
| /** |
| * Answer the column used to occupy any space left to the |
| * right of all the user created columns. |
| */ |
| TableColumn getFillColumn() { |
| return fillColumn; |
| } |
| /** |
| * Returns the width in pixels of a grid line. |
| * |
| * @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 getGridLineWidth () { |
| checkWidget(); |
| |
| return 1; |
| } |
| /** |
| * Answer the table header widget. |
| */ |
| Header getHeader() { |
| return tableHeader; |
| } |
| /** |
| * Returns the height of the receiver's header |
| * |
| * @return the height of the header or zero if the header is not visible |
| * |
| * @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> |
| * |
| * @since 2.0 |
| */ |
| public int getHeaderHeight() { |
| checkWidget(); |
| Header header = getHeader(); |
| int height = 0; |
| |
| if (header.getVisible() == true) { |
| height = header.getBounds().height; |
| } |
| return height; |
| } |
| /** |
| * Returns <code>true</code> if the receiver's header is visible, |
| * and <code>false</code> otherwise. |
| * <p> |
| * If one of the receiver's ancestors is not visible or some |
| * other condition makes the receiver not visible, this method |
| * may still indicate that it is considered visible even though |
| * it may not actually be showing. |
| * </p> |
| * |
| * @return the receiver's header's visibility state |
| * |
| * @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 boolean getHeaderVisible() { |
| checkWidget(); |
| |
| return getHeader().getVisible(); |
| } |
| /** |
| * Answer the image extent of 'item'. Use the image of any column. |
| */ |
| Point getImageExtent(SelectableItem item) { |
| Image image = null; |
| Rectangle imageBounds; |
| Point imageExtent = null; |
| int columnCount = internalGetColumnCount(); |
| |
| for (int i = 0; i < columnCount && image == null; i++) { |
| image = ((TableItem) item).getImage(i); |
| } |
| if (image != null) { |
| imageBounds = image.getBounds(); |
| imageExtent = new Point(imageBounds.width, imageBounds.height); |
| } |
| return imageExtent; |
| } |
| /** |
| * Answer the index of 'item' in the receiver. |
| */ |
| int getIndex(SelectableItem item) { |
| int index = -1; |
| |
| if (item != null && item.getSelectableParent() == this) { |
| index = ((TableItem) item).getIndex(); |
| } |
| return index; |
| } |
| /** |
| * Returns the item at the given, zero-relative index in the |
| * receiver. Throws an exception if the index is out of range. |
| * |
| * @param index the index of the item to return |
| * @return the item at the given index |
| * |
| * @exception IllegalArgumentException <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> |
| * @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 TableItem getItem(int index) { |
| checkWidget(); |
| |
| if (!(0 <= index && index < getItemCount())) { |
| error(SWT.ERROR_INVALID_RANGE); |
| } |
| return (TableItem) getVisibleItem(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 |
| * |
| * @exception IllegalArgumentException <ul> |
| * <li>ERROR_NULL_ARGUMENT - if the point 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 TableItem getItem(Point point) { |
| checkWidget(); |
| if (point == null) error(SWT.ERROR_NULL_ARGUMENT); |
| TableColumn column = getColumnAtX(point.x); |
| if ((style & SWT.FULL_SELECTION) == 0) { |
| if (column != null && column.getIndex() != 0) { |
| return null; |
| } |
| } |
| TableItem item = null; |
| int headerHeight = getHeaderHeight(); |
| if (column != null && column.getIndex() != TableColumn.FILL && point.y - headerHeight > 0) { |
| int itemIndex = (point.y - headerHeight) / getItemHeight() + getTopIndex(); |
| item = (TableItem) getVisibleItem(itemIndex); |
| if ((style & SWT.FULL_SELECTION) == 0) { |
| if (item != null) { |
| Point itemSize = item.getItemExtent(column); |
| if (point.x - column.getBounds().x > itemSize.x) { |
| item = null; |
| } |
| } |
| } |
| } |
| return item; |
| } |
| /** |
| * Returns the number of items contained in the receiver. |
| * |
| * @return the number of items |
| * |
| * @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 getItemCount() { |
| checkWidget(); |
| |
| return getItemVector().size(); |
| } |
| /** |
| * Answer the number of items that can be displayed in the |
| * client area of the receiver without truncating any items. |
| */ |
| int getItemCountWhole() { |
| int clientAreaHeight = Math.max(0, getClientArea().height - getHeaderHeight()); |
| |
| return clientAreaHeight / getItemHeight(); |
| } |
| /** |
| * Returns the height of the area which would be used to |
| * display <em>one</em> of the items in the receiver's. |
| * |
| * @return the height of one item |
| * |
| * @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 getItemHeight() { |
| checkWidget(); |
| |
| return super.getItemHeight(); |
| } |
| /** |
| * Answer the number of pixels that should be added to the item height. |
| */ |
| int getItemPadding() { |
| return getGridLineWidth() + display.textHighlightThickness + 1; |
| } |
| /** |
| * Returns an array of <code>TableItem</code>s which are the items |
| * in 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 items in the receiver |
| * |
| * @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 TableItem [] getItems() { |
| checkWidget(); |
| Vector items = getItemVector(); |
| TableItem itemArray[] = new TableItem[items.size()]; |
| |
| items.copyInto(itemArray); |
| return itemArray; |
| } |
| /** |
| * Answer all items of the receiver. |
| */ |
| Vector getItemVector() { |
| return items; |
| } |
| /** |
| * Returns <code>true</code> if the receiver's lines are visible, |
| * and <code>false</code> otherwise. |
| * <p> |
| * If one of the receiver's ancestors is not visible or some |
| * other condition makes the receiver not visible, this method |
| * may still indicate that it is considered visible even though |
| * it may not actually be showing. |
| * </p> |
| * |
| * @return the visibility state of the lines |
| * |
| * @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 boolean getLinesVisible() { |
| checkWidget(); |
| |
| return drawGridLines; |
| } |
| /** |
| * Answer a Vector containing the columns that need repainting |
| * based on the 'paintArea'. |
| * @param paintArea - invalidated rectangle that needs repainting |
| */ |
| Vector getPaintColumns(Rectangle paintArea) { |
| Enumeration columns = internalGetColumnVector().elements(); |
| Vector paintColumns = new Vector(); |
| TableColumn column; |
| Rectangle columnBounds; |
| int paintAreaRightBorder = paintArea.x + paintArea.width; |
| |
| while (columns.hasMoreElements() == true) { |
| column = (TableColumn) columns.nextElement(); |
| columnBounds = column.getBounds(); |
| if ((columnBounds.x + columnBounds.width >= paintArea.x) && // does the paintArea overlap the current column? |
| (columnBounds.x <= paintAreaRightBorder)) { |
| paintColumns.addElement(column); |
| } |
| } |
| return paintColumns; |
| } |
| /** |
| * Return the width of the widest item in the column identified by 'columnIndex' |
| * @param columnIndex - index of the column whose preferred width should be |
| * calculated |
| */ |
| int getPreferredColumnWidth(int columnIndex) { |
| Enumeration tableItems = getItemVector().elements(); |
| TableItem tableItem; |
| int width = 0; |
| int headerWidth; |
| |
| if (columnIndex != TableColumn.FILL) { |
| if ((parent.getStyle() & SWT.VIRTUAL) == 0) { |
| while (tableItems.hasMoreElements() == true) { |
| tableItem = (TableItem) tableItems.nextElement(); |
| width = Math.max(width, tableItem.getPreferredWidth(columnIndex)); |
| } |
| } |
| headerWidth = getHeader().getPreferredWidth(columnIndex); |
| if (width < headerWidth) { |
| width = headerWidth; |
| } |
| } |
| return width; |
| } |
| /** |
| * Answer the position in the receiver where 'item' is drawn |
| * @return the y coordinate at which 'item' is drawn. |
| * Return -1 if 'item' is not an item of the receiver |
| */ |
| int getRedrawY(SelectableItem item) { |
| int redrawY = super.getRedrawY(item); |
| |
| if (redrawY != -1) { |
| redrawY += getHeaderHeight(); |
| } |
| return redrawY; |
| } |
| /** |
| * Answer the column that is being resized or null if no |
| * resize operation is in progress. |
| */ |
| TableColumn getResizeColumn() { |
| return resizeColumn; |
| } |
| /** |
| * Return the positions at which the column identified by 'columnIndex' |
| * must be redrawn. |
| * These positions may be different for each item since each item may |
| * have a different label |
| * @param columnIndex - the column index |
| * @param columnWidth - width of the column |
| * @return the positions at which the column must be redrawn. |
| * Each item in the widget client area is represented by a slot in |
| * the array. The item at position 'topIndex' is the first item in |
| * the array. |
| */ |
| int [] getResizeRedrawX(int columnIndex, int columnWidth) { |
| int topIndex = getTopIndex(); |
| int bottomIndex = getBottomIndex(); |
| int resizeRedrawX[]; |
| TableItem item; |
| |
| bottomIndex = Math.min(bottomIndex, getItemCount()); |
| resizeRedrawX = new int[bottomIndex-topIndex+1]; |
| for (int i = topIndex; i < bottomIndex; i++) { |
| item = (TableItem) getVisibleItem(i); |
| resizeRedrawX[i-topIndex] = item.getDotStartX(columnIndex, columnWidth); |
| } |
| return resizeRedrawX; |
| } |
| /** |
| * Returns an array of <code>TableItem</code>s that are currently |
| * selected in the receiver. An empty array indicates that no |
| * items are selected. |
| * <p> |
| * Note: This is not the actual structure used by the receiver |
| * to maintain its selection, so modifying the array will |
| * not affect the receiver. |
| * </p> |
| * @return an array representing the selection |
| * |
| * @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 TableItem [] getSelection() { |
| checkWidget(); |
| Vector selectionVector = getSelectionVector(); |
| TableItem[] selectionArray = new TableItem[selectionVector.size()]; |
| |
| selectionVector.copyInto(selectionArray); |
| sort(selectionArray, 0, selectionArray.length); |
| return selectionArray; |
| } |
| |
| /** |
| * Returns the number of selected items contained in the receiver. |
| * |
| * @return the number of selected items |
| * |
| * @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 getSelectionCount() { |
| checkWidget(); |
| |
| return super.getSelectionCount(); |
| } |
| |
| int getFontHeight(){ |
| return fontHeight; |
| } |
| /** |
| * Answer the size of the full row selection rectangle for 'item'. |
| */ |
| Point getFullSelectionExtent(TableItem item) { |
| TableColumn lastColumn = (TableColumn) internalGetColumnVector().lastElement(); |
| Point selectionExtent = null; |
| Rectangle columnBounds; |
| int xPosition = item.getImageStopX(TableColumn.FIRST); |
| int gridLineWidth = getGridLineWidth(); |
| |
| if (lastColumn != null) { |
| columnBounds = lastColumn.getBounds(); |
| selectionExtent = new Point( |
| columnBounds.x - getHorizontalOffset() + columnBounds.width - xPosition - gridLineWidth, |
| getItemHeight()); |
| if (getLinesVisible() == true) { |
| selectionExtent.y -= gridLineWidth; |
| } |
| } |
| return selectionExtent; |
| } |
| /** |
| * Returns the zero-relative index of the item which is currently |
| * selected in the receiver, or -1 if no item is selected. |
| * |
| * @return the index of the selected item |
| * |
| * @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 getSelectionIndex() { |
| checkWidget(); |
| int index = -1; |
| |
| if (getSelectionCount() > 0) { |
| index = getIndex(getSelection()[0]); |
| } |
| return index; |
| } |
| /** |
| * Returns the zero-relative indices of the items which are currently |
| * selected in the receiver. The array is empty if no items are selected. |
| * <p> |
| * Note: This is not the actual structure used by the receiver |
| * to maintain its selection, so modifying the array will |
| * not affect the receiver. |
| * </p> |
| * @return the array of indices of the selected items |
| * |
| * @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 [] getSelectionIndices() { |
| checkWidget(); |
| TableItem[] items = getSelection(); |
| int indices[] = new int[items.length]; |
| |
| for (int i = 0; i < items.length; i++) { |
| indices[i] = getIndex(items[i]); |
| } |
| return indices; |
| } |
| /** |
| * 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 |
| * |
| * @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 getTopIndex() { |
| checkWidget(); |
| |
| return super.getTopIndex(); |
| } |
| /** |
| * Answer the index of 'item' in the receiver. |
| * Answer -1 if the item is not visible. |
| * The returned index must refer to a visible item. |
| * Note: |
| * Visible in this context does not neccessarily mean that the |
| * item is displayed on the screen. It only means that the item |
| * would be displayed if it is located inside the receiver's |
| * client area. |
| * Every item in a table widget should be visible. |
| */ |
| int getVisibleIndex(SelectableItem item) { |
| return getIndex(item); |
| } |
| /** |
| * Answer the SelectableItem located at 'itemIndex' in the receiver. |
| * @param itemIndex - location of the SelectableItem object to return |
| */ |
| SelectableItem getVisibleItem(int itemIndex) { |
| Vector items = getItemVector(); |
| TableItem item = null; |
| |
| if ((items != null) && (itemIndex >= 0) && (itemIndex < items.size())) { |
| item = (TableItem) items.elementAt(itemIndex); |
| } |
| return item; |
| } |
| /** |
| * Answer the y coordinate at which 'item' is drawn. |
| * @param item - SelectableItem for which the paint position |
| * should be returned |
| * @return the y coordinate at which 'item' is drawn. |
| * Return -1 if 'item' is null or outside the client area |
| */ |
| int getVisibleRedrawY(SelectableItem item) { |
| int redrawY = -1; |
| int index = getTopIndex(); |
| int bottomIndex = getBottomIndex(); |
| |
| if (item == null) { |
| return redrawY; |
| } |
| while (index < bottomIndex && item.equals(getVisibleItem(index)) == false) { |
| index++; |
| } |
| if (index < bottomIndex) { |
| redrawY = getRedrawY(item); |
| } |
| return redrawY; |
| } |
| /** |
| * Handle the events the receiver is listening to. |
| */ |
| void handleEvents(Event event) { |
| switch (event.type) { |
| case SWT.MouseMove: |
| if (event.widget == tableHeader) { |
| headerMouseMove(event); |
| } |
| else { |
| columnMouseMove(event); |
| } |
| break; |
| case SWT.MouseDown: |
| if (event.widget == tableHeader) { |
| headerMouseDown(event); |
| } |
| else { |
| columnMouseDown(event); |
| } |
| break; |
| case SWT.MouseDoubleClick: |
| if (event.widget == tableHeader) { |
| headerMouseDoubleClick(event); |
| } else { |
| columnMouseDoubleClick(event); |
| } |
| break; |
| case SWT.MouseUp: |
| mouseUp(event); |
| break; |
| case SWT.Paint: |
| paint(event); |
| break; |
| default: |
| super.handleEvents(event); |
| } |
| } |
| /** |
| * Answer true if any item in the first column has an image. |
| * Answer false otherwise. |
| */ |
| boolean hasFirstColumnImage() { |
| return firstColumnImage; |
| } |
| /** |
| * The mouse pointer was pressed down on the receiver's header |
| * widget. Start a column resize operation if apropriate. |
| * @param event - the mouse event that occured over the header |
| * widget |
| */ |
| void headerMouseDown(Event event) { |
| TableColumn column = getColumnAtX(event.x); |
| |
| // only react to button one clicks. fixes bug 6770 |
| if (event.button != 1) { |
| return; |
| } |
| if (isColumnResize(event) == true) { |
| startColumnResize(event); |
| } |
| else |
| if (column != null) { |
| column.notifyListeners(SWT.Selection, new Event()); |
| } |
| } |
| void headerMouseDoubleClick(Event event) { |
| if (event.button != 1) return; |
| TableColumn column = getColumnAtX(event.x); |
| if (column != null) { |
| column.notifyListeners(SWT.DefaultSelection, new Event()); |
| } |
| } |
| /** |
| * The mouse pointer was moved over the receiver's header widget. |
| * If a column is currently being resized a vertical line indicating |
| * the new position of the resized column is drawn. |
| * Otherwise, if no column resize operation is in progress, the |
| * column resize cursor is displayed when the mouse is near the border |
| * of a column. |
| */ |
| void headerMouseMove(Event event) { |
| if (isColumnResizeStarted() == false) { // only check whether cursor is in resize |
| setColumnResizeCursor(isColumnResize(event)); // area if no resize operation is in progress |
| } |
| else |
| if (event.x >= getResizeColumn().getBounds().x) { |
| drawColumnResizeLine(event.x); |
| update(); // looks better if resize line is drawn immediately |
| } |
| } |
| /** |
| * 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 |
| * |
| * @exception IllegalArgumentException <ul> |
| * <li>ERROR_NULL_ARGUMENT - if the string 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 int indexOf(TableColumn column) { |
| checkWidget(); |
| |
| if (column == null) { |
| error(SWT.ERROR_NULL_ARGUMENT); |
| } |
| return internalGetColumnVector().indexOf(column); |
| } |
| /** |
| * 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 string 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 int indexOf(TableItem item) { |
| checkWidget(); |
| if (item == null) { |
| error(SWT.ERROR_NULL_ARGUMENT); |
| } |
| return getIndex(item); |
| } |
| /** |
| * Initialize the receiver. Create a header widget and an empty column. |
| */ |
| void initialize() { |
| columns = new Vector(); |
| setItemVector(new Vector()); |
| GC gc = new GC(this); |
| Point extent = gc.stringExtent("String"); |
| fontHeight = extent.y; |
| gc.dispose(); |
| tableHeader = new Header(this); |
| tableHeader.setVisible(false); // SWT table header is invisible by default, too |
| fillColumn = TableColumn.createFillColumn(this); |
| setColumnPosition(fillColumn); |
| defaultColumn = TableColumn.createDefaultColumn(this); // Create the default column. Fix for 1FUSJY5 |
| super.initialize(); |
| } |
| /** |
| * Insert the new column 'column' into the table data at position |
| * 'index'. |
| */ |
| void insertColumnData(TableColumn column) { |
| Enumeration tableItems = getItemVector().elements(); |
| TableItem tableItem; |
| |
| while (tableItems.hasMoreElements() == true ) { |
| tableItem = (TableItem) tableItems.nextElement(); |
| tableItem.insertColumn(column); |
| } |
| } |
| /** |
| * Insert the new column 'column'. |
| * Set the position and move the following columns to the right. |
| */ |
| void insertColumnVisual(TableColumn column) { |
| Rectangle columnBounds = column.getBounds(); |
| Rectangle previousColumnBounds; |
| int index = column.getIndex(); |
| |
| if (index > 0) { |
| previousColumnBounds = getColumn(index - 1).getBounds(); |
| columnBounds.x = previousColumnBounds.x + previousColumnBounds.width; |
| } |
| else { |
| columnBounds.x = 0; |
| } |
| column.setBounds(columnBounds); |
| setColumnPosition(column); |
| } |
| /** |
| * Set event listeners for the receiver. |
| */ |
| void installListeners() { |
| Header tableHeader = getHeader(); |
| Listener listener = getListener(); |
| |
| super.installListeners(); |
| tableHeader.addListener(SWT.MouseMove, listener); |
| tableHeader.addListener(SWT.MouseDown, listener); |
| tableHeader.addListener(SWT.MouseDoubleClick, listener); |
| tableHeader.addListener(SWT.MouseUp, listener); |
| |
| addListener(SWT.MouseMove, listener); |
| addListener(SWT.MouseDown, listener); |
| addListener(SWT.MouseDoubleClick, listener); |
| addListener(SWT.MouseUp, listener); |
| addListener(SWT.Paint, listener); |
| } |
| /** |
| * Answer the TableColumn at 'index'. |
| * If the user has not created any columns the default column is |
| * returned if index is 0. |
| * Fix for 1FUSJY5 |
| */ |
| TableColumn internalGetColumn(int index) { |
| Vector columns = internalGetColumnVector(); |
| |
| if (columns == null) error(SWT.ERROR_CANNOT_GET_ITEM); |
| if (index < 0 || index >= columns.size()) { |
| error(SWT.ERROR_INVALID_RANGE); |
| } |
| |
| return (TableColumn) columns.elementAt(index); |
| |
| } |
| /** |
| * Answer the number of columns in the receiver. |
| * If the user has not created any columns, 1 is returned since there |
| * always is a default column. |
| * Fix for 1FUSJY5 |
| */ |
| int internalGetColumnCount() { |
| Vector columns = internalGetColumnVector(); |
| int count = 0; |
| |
| if (columns != null) { |
| count = columns.size(); |
| } |
| return count; |
| } |
| /** |
| * Return a Vector containing all columns of the receiver except |
| * the fill column to the right of all content columns. |
| * Return a Vector containing the default column if the user has |
| * not created any columns. |
| * Fix for 1FUSJY5 |
| */ |
| Vector internalGetColumnVector() { |
| Vector internalColumnVector; |
| TableColumn defaultColumn; |
| |
| if (columns.isEmpty() == false) { |
| internalColumnVector = columns; |
| } |
| else { |
| internalColumnVector = new Vector(1); |
| defaultColumn = getDefaultColumn(); |
| if (defaultColumn != null) { |
| internalColumnVector.addElement(defaultColumn); |
| } |
| } |
| return internalColumnVector; |
| } |
| /** |
| * Answer whether the mouse pointer is at a position that can |
| * start a column resize operation. A column resize can be |
| * started if the mouse pointer is at either the left or right |
| * border of a column. |
| * @param event - mouse event specifying the location of the |
| * mouse pointer. |
| */ |
| boolean isColumnResize(Event event) { |
| TableColumn hotColumn = getColumnAtX(event.x); |
| if (hotColumn == null) return false; |
| Rectangle bounds = hotColumn.getBounds(); |
| int hotColumnIndex = hotColumn.getIndex(); |
| int columnX = event.x - bounds.x; |
| boolean isColumnResize = false; |
| |
| if (columnX <= COLUMN_RESIZE_OFFSET && // mouse over left side of column? and |
| hotColumnIndex != TableColumn.FIRST) { // it's not the first column) |
| if (hotColumnIndex == TableColumn.FILL) { |
| hotColumn = (TableColumn) internalGetColumnVector().lastElement(); |
| } |
| else { |
| hotColumn = internalGetColumn(hotColumnIndex - 1); |
| } |
| isColumnResize = hotColumn.getResizable(); // check whether left column can be resized |
| } |
| else |
| if (columnX >= bounds.width - COLUMN_RESIZE_OFFSET && // mouse over right side of column and |
| hotColumn != getFillColumn()) { // column is a real one (not the right hand fill column)? |
| isColumnResize = hotColumn.getResizable(); // check whether column under cursor can be resized |
| } |
| return isColumnResize; |
| } |
| /** |
| * Answer whether a column of the receiver is being resized. |
| */ |
| boolean isColumnResizeStarted() { |
| return (getResizeColumn() != null); |
| } |
| /** |
| * Returns <code>true</code> if the item is selected, |
| * and <code>false</code> otherwise. Indices out of |
| * range are ignored. |
| * |
| * @param index the index of the item |
| * @return the visibility state of the item at the index |
| * |
| * @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 boolean isSelected(int index) { |
| checkWidget(); |
| TableItem item = getItem(index); |
| |
| return (item != null && item.isSelected() == true); |
| } |
| /** |
| * 'changedItem' has changed. Update the default column width. |
| * @param changedItem - the item that has changed |
| */ |
| void itemChanged(SelectableItem changedItem, int repaintStartX, int repaintWidth) { |
| // call super.itemChanged first to make sure that table image size is |
| // calculated if necessary. Fixes 1FYPBBG. |
| super.itemChanged(changedItem, repaintStartX, repaintWidth); |
| // remember if any item ever had an image in the first column. |
| if (firstColumnImage == false && changedItem.getImage() != null) { |
| firstColumnImage = true; |
| redraw (); |
| } |
| setFirstColumnWidth((TableItem) changedItem); |
| } |
| /** |
| * A mouse button was released. |
| * Update the display if a column has been resized. |
| * @param event - the mouse event for the button up action |
| */ |
| void mouseUp(Event event) { |
| TableColumn resizeColumn = getResizeColumn(); |
| Rectangle oldColumnBounds; |
| int resizeXPosition; |
| int widthChange; |
| if (isColumnResizeStarted() == true) { |
| oldColumnBounds = resizeColumn.getBounds(); |
| resizeXPosition = getColumnResizeX(); |
| widthChange = resizeXPosition - (oldColumnBounds.x + oldColumnBounds.width); |
| if (widthChange >= 0) { |
| redraw(resizeXPosition - getGridLineWidth(), 0, 1, getClientArea().height, false); // remove resize line |
| update(); // to avoid cheese caused by scrolling the resize line |
| } |
| if (widthChange != 0) { |
| resizeColumn.setWidth(oldColumnBounds.width + widthChange); |
| } |
| setResizeColumn(null); |
| } |
| } |
| /** |
| * Adjust the position of all columns starting at 'startIndex'. |
| * @param startIndex - index at which the column move should begin |
| * If this is the index of the fill column all columns are moved, |
| * including the fill column |
| * @param moveDistance - distance that the columns should be moved. |
| * < 0 = columns are going to be moved left. |
| * > 0 = columns are going to be moved right. |
| */ |
| void moveColumns(int startIndex, int moveDistance) { |
| Vector columns = internalGetColumnVector(); |
| TableColumn moveColumn; |
| Rectangle columnBounds; |
| |
| if (startIndex == TableColumn.FILL) { |
| moveColumn = getFillColumn(); |
| columnBounds = moveColumn.getBounds(); |
| columnBounds.x += moveDistance; |
| moveColumn.setBounds(columnBounds); |
| startIndex = 0; // continue with first data column |
| } |
| for (int i = startIndex; i < columns.size(); i++) { |
| moveColumn = (TableColumn) columns.elementAt(i); |
| columnBounds = moveColumn.getBounds(); |
| columnBounds.x += moveDistance; |
| moveColumn.setBounds(columnBounds); |
| } |
| } |
| /** |
| * Adjust the y position of all columns including the fill column. |
| */ |
| void moveColumnsVertical() { |
| Enumeration columns = internalGetColumnVector().elements(); |
| TableColumn column; |
| |
| setColumnPosition(getFillColumn()); |
| while (columns.hasMoreElements() == true) { |
| column = (TableColumn) columns.nextElement(); |
| setColumnPosition(column); |
| } |
| } |
| /** |
| * A paint event has occurred. Paint the invalidated items. |
| * @param event - paint event specifying the invalidated area. |
| */ |
| void paint(Event event) { |
| int visibleRange[]; |
| int headerHeight = getHeaderHeight(); |
| Vector paintColumns = getPaintColumns(event.getBounds()); |
| TableItem focusItem = null; |
| |
| if (paintColumns.size() > 0) { |
| event.y -= headerHeight; |
| visibleRange = getIndexRange(event.getBounds()); |
| event.y += headerHeight; |
| // When the top index is > 0 and the receiver is resized |
| // higher so that the top index becomes 0 the invalidated |
| // rectangle doesn't start below the header widget but at |
| // y position 0. Subtraction of the header height (it is |
| // not above the receiver but on top) causes event.y and |
| // subsequently visibleRange[0] to be negative. |
| // Hack to prevent visibleRange[0] from becoming negative. |
| // Need to find out why the invalidated area starts at 0 |
| // in the first place. |
| if (visibleRange[0] < 0) { |
| visibleRange[0] = 0; |
| } |
| // |
| visibleRange[1] = Math.min(visibleRange[1], getItemCount()-1-getTopIndex()); |
| focusItem = paintItems(event, visibleRange[0], visibleRange[1], paintColumns); |
| } |
| if (getLinesVisible() == true) { |
| drawGridLines(event, paintColumns.elements()); |
| } |
| if (focusItem != null) { |
| // draw focus on top of drawing grid lines so that focus rectangle |
| // is not obscured by grid. Fixes 1G5X20B |
| drawSelectionFocus(focusItem, event.gc); |
| } |
| } |
| |
| /** |
| * Paint items of the receiver starting at index 'topPaintIndex' and |
| * ending at 'bottomPaintIndex'. |
| * @param event - holds the GC to draw on and the clipping rectangle |
| * @param topPaintIndex - index of the first item to draw |
| * @param bottomPaintIndex - index of the last item to draw |
| * @param paintColumns - the table columns that should be painted |
| * @return the item that has focus if it was among the rendered items. |
| * null if the focus item was not rendered or if no item has focus (ie. |
| * because the widget does not have focus) |
| */ |
| TableItem paintItems(Event event, int topPaintIndex, int bottomPaintIndex, Vector paintColumns) { |
| Enumeration columns; |
| TableColumn column; |
| TableItem paintItem; |
| TableItem focusItem = null; |
| Point selectionExtent; |
| GC gc = event.gc; |
| Color selectionColor = display.getSystemColor(SWT.COLOR_LIST_SELECTION); |
| int paintXPosition; |
| int paintYPosition; |
| |
| topPaintIndex += getTopIndex(); |
| bottomPaintIndex += getTopIndex(); |
| |
| if ((getStyle () & SWT.VIRTUAL) != 0) { |
| for (int i = topPaintIndex; i <= bottomPaintIndex; i++) { |
| paintItem = (TableItem) getVisibleItem(i); |
| if (!paintItem.cached) { |
| Event dataEvent = new Event(); |
| dataEvent.item = paintItem; |
| ignoreRedraw = true; |
| sendEvent(SWT.SetData, dataEvent); |
| if (isDisposed()) return null; |
| //widget could be disposed at this point |
| ignoreRedraw = false; |
| calculateItemHeight(paintItem); |
| paintItem.cached = true; |
| } |
| } |
| } |
| |
| for (int i = topPaintIndex; i <= bottomPaintIndex; i++) { |
| paintItem = (TableItem) getVisibleItem(i); |
| paintXPosition = paintItem.getSelectionX(); |
| paintYPosition = getRedrawY(paintItem); |
| |
| if (paintItem.isSelected() == true) { |
| if ((style & SWT.HIDE_SELECTION) == 0 || isFocusControl()) { |
| selectionExtent = paintItem.getSelectionExtent(); |
| gc.setBackground(selectionColor); |
| gc.fillRectangle(paintXPosition, paintYPosition, selectionExtent.x, selectionExtent.y); |
| } |
| } |
| columns = paintColumns.elements(); |
| while (columns.hasMoreElements() == true) { |
| column = (TableColumn) columns.nextElement(); |
| paintSubItem(event, paintItem, column, paintYPosition); |
| } |
| if (hasFocus(paintItem)) { |
| focusItem = paintItem; |
| } |
| } |
| return focusItem; |
| } |
| |
| /** |
| * Paint the table item 'paintItem' in 'column' at y position |
| * 'paintYPosition' of the receiver. |
| * @param event - holds the GC to draw on and the clipping |
| * rectangle. |
| * @param paintItem - the item to draw |
| * @param column - column to draw 'paintItem' in |
| * @param paintYPosition - y position in the receiver to draw |
| * 'paintItem' at. |
| */ |
| void paintSubItem(Event event, TableItem paintItem, TableColumn column, int paintYPosition) { |
| Rectangle columnBounds = column.getBounds(); |
| Point paintPosition; |
| int gridLineWidth = getGridLineWidth(); |
| int itemDrawStopX = columnBounds.x + columnBounds.width - gridLineWidth; |
| int clipX; |
| |
| if (event.x + event.width > itemDrawStopX) { // does the invalidated area stretch past the current column's right border? |
| clipX = Math.max(columnBounds.x, event.x); |
| event.gc.setClipping( // clip the drawing area |
| clipX, event.y, |
| Math.max(0, itemDrawStopX - clipX), event.height); |
| } |
| paintPosition = new Point(columnBounds.x, paintYPosition); |
| paintItem.paint(event.gc, paintPosition, column); |
| if (event.x + event.width > itemDrawStopX) { |
| event.gc.setClipping(event.x, event.y, event.width, event.height); // restore original clip rectangle |
| } |
| } |
| /** |
| * Reindex all columns starting at 'startIndex'. |
| * Reindexing is necessary when a new column has been inserted. |
| */ |
| void reindexColumns(int startIndex) { |
| Vector columns = getColumnVector(); |
| TableColumn column; |
| |
| for (int i = startIndex; i < getColumnCount(); i++) { |
| column = (TableColumn) columns.elementAt(i); |
| column.setIndex(i); |
| } |
| } |
| /** |
| * Removes the items from the receiver's list at the given |
| * zero-relative indices. |
| * |
| * @param indices the array of indices of the items |
| * |
| * @exception IllegalArgumentException <ul> |
| * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the list minus 1 (inclusive)</li> |
| * <li>ERROR_NULL_ARGUMENT - if the indices array 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> |
| * @exception SWTError <ul> |
| * <li>ERROR_ITEM_NOT_REMOVED - if the operation fails because of an operating system failure</li> |
| * </ul> |
| */ |
| public void remove(int indices[]) { |
| checkWidget(); |
| if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); |
| if (indices.length == 0) return; |
| int [] newIndices = new int [indices.length]; |
| System.arraycopy (indices, 0, newIndices, 0, indices.length); |
| sort (newIndices); |
| int start = newIndices [newIndices.length - 1], end = newIndices [0]; |
| int count = getItemCount(); |
| if (!(0 <= start && start <= end && end < count)) { |
| error (SWT.ERROR_INVALID_RANGE); |
| } |
| int last = -1; |
| for (int i = 0; i < newIndices.length; i++) { |
| int index = newIndices[i]; |
| if (index != last) { |
| SelectableItem item = getVisibleItem(index); |
| if (item != null) { |
| item.dispose(); |
| } else { |
| error(SWT.ERROR_ITEM_NOT_REMOVED); |
| } |
| last = index; |
| } |
| } |
| } |
| public void redraw () { |
| checkWidget(); |
| if (ignoreRedraw) return; |
| super.redraw(); |
| } |
| public void redraw (int x, int y, int width, int height, boolean all) { |
| checkWidget(); |
| if (ignoreRedraw) return; |
| super.redraw(x, y, width, height, all); |
| } |
| /** |
| * Removes the item from the receiver at the given |
| * zero-relative index. |
| * |
| * @param index the index for the item |
| * |
| * @exception 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> |
| * @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> |
| * @exception SWTError <ul> |
| * <li>ERROR_ITEM_NOT_REMOVED - if the operation fails because of an operating system failure</li> |
| * </ul> |
| */ |
| public void remove(int index) { |
| checkWidget(); |
| SelectableItem item = getVisibleItem(index); |
| |
| if (item != null) { |
| item.dispose(); |
| } |
| else { |
| if (0 <= index && index < getItemVector().size()) { |
| error(SWT.ERROR_ITEM_NOT_REMOVED); |
| } |
| else { |
| error(SWT.ERROR_INVALID_RANGE); |
| } |
| } |
| } |
| /** |
| * Removes the items from the receiver which are |
| * between the given zero-relative start and end |
| * indices (inclusive). |
| * |
| * @param start the start of the range |
| * @param end the end of the range |
| * |
| * @exception IllegalArgumentException <ul> |
| * <li>ERROR_INVALID_RANGE - if either the start or end are not between 0 and the number of elements in the list minus 1 (inclusive)</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> |
| * @exception SWTError <ul> |
| * <li>ERROR_ITEM_NOT_REMOVED - if the operation fails because of an operating system failure</li> |
| * </ul> |
| */ |
| public void remove(int start, int end) { |
| checkWidget(); |
| if (start > end) return; |
| if (!(0 <= start && start <= end && end < getItemCount())) { |
| error (SWT.ERROR_INVALID_RANGE); |
| } |
| for (int i = end; i >= start; i--) { |
| SelectableItem item = getVisibleItem(i); |
| if (item != null) { |
| item.dispose(); |
| } else { |
| error(SWT.ERROR_ITEM_NOT_REMOVED); |
| } |
| } |
| } |
| /** |
| * Removes all of the items from the receiver. |
| * <p> |
| * @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 removeAll() { |
| checkWidget(); |
| Vector items = getItemVector(); |
| |
| setRedraw(false); |
| setRemovingAll(true); |
| for (int i = items.size() - 1; i >= 0; i--) { |
| ((TableItem) items.elementAt(i)).dispose(); |
| } |
| setItemVector(new Vector()); |
| reset(); |
| calculateVerticalScrollbar(); |
| setRemovingAll(false); |
| setRedraw(true); |
| } |
| /** |
| * Remove 'column' from the receiver. |
| */ |
| void removeColumn(TableColumn column) { |
| int index = column.getIndex(); |
| int columnWidth = column.getWidth(); |
| int columnCount; |
| |
| if (isRemovingAll() == true) { |
| getColumnVector().removeElementAt(index); |
| } |
| else { |
| getColumnVector().removeElementAt(index); |
| columnCount = getColumnCount(); |
| // Never remove the data of the last user created column. |
| // SWT for Windows does the same. |
| if (columnCount > 0) { |
| removeColumnData(column); |
| removeColumnVisual(column); |
| Enumeration items = getItemVector ().elements (); |
| while (items.hasMoreElements()) { |
| TableItem item = (TableItem)items.nextElement(); |
| Color [] cellBackground = item.cellBackground; |
| if (cellBackground != null) { |
| Color [] temp = new Color [columnCount]; |
| System.arraycopy (cellBackground, 0, temp, 0, index); |
| System.arraycopy (cellBackground, index + 1, temp, index, columnCount - index); |
| item.cellBackground = temp; |
| } |
| Color [] cellForeground = item.cellForeground; |
| if (cellForeground != null) { |
| Color [] temp = new Color [columnCount]; |
| System.arraycopy (cellForeground, 0, temp, 0, index); |
| System.arraycopy (cellForeground, index + 1, temp, index, columnCount - index); |
| item.cellForeground = temp; |
| } |
| Font [] cellFont = item.cellFont; |
| if (cellFont != null) { |
| Font [] temp = new Font [columnCount]; |
| System.arraycopy (cellFont, 0, temp, 0, index); |
| System.arraycopy (cellFont, index + 1, temp, index, columnCount - index); |
| item.cellFont = temp; |
| } |
| } |
| } |
| else { |
| redraw(); |
| getHeader().redraw(); |
| } |
| if (index < columnCount) { // is there a column after the removed one? |
| reindexColumns(index); |
| } |
| // last user created column is about to be removed. |
| if (columnCount == 0) { |
| TableColumn defaultColumn = getDefaultColumn(); |
| defaultColumn.pack(); // make sure the default column has the right size... |
| setColumnPosition(defaultColumn); // ...and is at the right position |
| } |
| // Fixes for 1G1L0UT |
| // Reduce the content width by the width of the removed column |
| setContentWidth(getContentWidth() - columnWidth); |
| // claim free space |
| claimRightFreeSpace(); |
| // |
| } |
| } |
| /** |
| * Remove the column 'column' from the table data. |
| */ |
| void removeColumnData(TableColumn column) { |
| Enumeration tableItems = getItemVector().elements(); |
| TableItem tableItem; |
| |
| while (tableItems.hasMoreElements() == true ) { |
| tableItem = (TableItem) tableItems.nextElement(); |
| tableItem.removeColumn(column); |
| } |
| } |
| /** |
| * Remove the column 'column'. |
| * Set the position of the following columns. |
| */ |
| void removeColumnVisual(TableColumn column) { |
| int columnWidth = column.getWidth(); |
| |
| // move following columns to the left |
| moveColumns(column.getIndex(), columnWidth * -1); |
| redraw(); |
| getHeader().redraw(); |
| } |
| /** |
| * 'item' has been removed from the receiver. |
| * Update the display and the scroll bars. |
| */ |
| void removedItem(SelectableItem item) { |
| int oldHeight = getItemHeight(); |
| super.removedItem (item); |
| if (getItemCount() == 0 && drawGridLines && oldHeight != getItemHeight()) { |
| redraw(); |
| } |
| } |
| /** |
| * Remove 'item' from the receiver. |
| * @param item - item that should be removed from the receiver |
| */ |
| void removeItem(TableItem item) { |
| if (isRemovingAll() == true) return; |
| |
| Vector items = getItemVector(); |
| int index = items.indexOf(item); |
| if (index != -1) { |
| removingItem(item); |
| items.removeElementAt(index); |
| for (int i = index; i < items.size(); i++) { |
| TableItem anItem = (TableItem) items.elementAt(i); |
| anItem.setIndex(anItem.getIndex() - 1); |
| } |
| removedItem(item); |
| } |
| } |
| /** |
| * 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 |
| * |
| * @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> |
| * |
| * @see SelectionListener |
| * @see #addSelectionListener |
| */ |
| public void removeSelectionListener(SelectionListener listener) { |
| checkWidget(); |
| if (listener == null) { |
| error(SWT.ERROR_NULL_ARGUMENT); |
| } |
| removeListener(SWT.Selection, listener); |
| removeListener(SWT.DefaultSelection, listener); |
| } |
| /** |
| * Reset cached data of column at 'columnIndex' for the items of the receiver. |
| * @param columnIndex - index of the column for which the item data should be |
| * reset. |
| */ |
| void resetTableItems(int columnIndex) { |
| Enumeration tableItems = getItemVector().elements(); |
| TableItem tableItem; |
| |
| while (tableItems.hasMoreElements() == true ) { |
| tableItem = (TableItem) tableItems.nextElement(); |
| tableItem.reset(columnIndex); |
| } |
| } |
| /** |
| * The receiver has been resized. Resize the fill column |
| * and the header widget. |
| */ |
| void resize(Event event) { |
| TableColumn fillColumn = getFillColumn(); |
| Rectangle fillColumnBounds; |
| |
| super.resize(event); |
| // the x position may change in super.resize. |
| // get the column bounds after calling super.resize. Fixes 1G7ALGG |
| fillColumnBounds = fillColumn.getBounds(); |
| fillColumnBounds.width = Math.max(0, getClientArea().width - getContentWidth()); |
| fillColumn.setBounds(fillColumnBounds); |
| resizeHeader(); |
| } |
| /** |
| * Resize the header widget to occupy the whole width of the |
| * receiver. |
| */ |
| void resizeHeader() { |
| Header tableHeader = getHeader(); |
| Point size = tableHeader.getSize(); |
| |
| size.x = Math.max(getContentWidth(), getClientArea().width); |
| tableHeader.setSize(size); |
| } |
| /** |
| * Redraw 'column' after its width has been changed. |
| * @param column - column whose width has changed. |
| * @param oldColumnWidth - column width before resize |
| * @param oldColumnWidth - column width after resize |
| */ |
| void resizeRedraw(TableColumn column, int oldColumnWidth, int newColumnWidth) { |
| Rectangle columnBounds = column.getBounds(); |
| int columnIndex = column.getIndex(); |
| int oldRedrawStartX[] = getResizeRedrawX(columnIndex, oldColumnWidth); |
| int newRedrawStartX[] = getResizeRedrawX(columnIndex, newColumnWidth); |
| int itemHeight = getItemHeight(); |
| int widthChange = newColumnWidth - oldColumnWidth; |
| int topIndex = getTopIndex(); |
| |
| for (int i = 0; i < newRedrawStartX.length; i++) { |
| if (newRedrawStartX[i] != oldRedrawStartX[i]) { |
| if (widthChange > 0) { |
| newRedrawStartX[i] = oldRedrawStartX[i]; |
| } |
| redraw( |
| columnBounds.x + newRedrawStartX[i], columnBounds.y + itemHeight * (i + topIndex), |
| columnBounds.width - newRedrawStartX[i], itemHeight, false); |
| } |
| } |
| } |
| /** |
| * Scroll horizontally by 'numPixel' pixel. |
| * @param numPixel - the number of pixel to scroll |
| * < 0 = columns are going to be moved left. |
| * > 0 = columns are going to be moved right. |
| */ |
| void scrollHorizontal(int numPixel) { |
| Rectangle clientArea = getClientArea(); |
| |
| scroll( |
| numPixel, 0, // destination x, y |
| 0, 0, // source x, y |
| clientArea.width, clientArea.height, true); |
| getHeader().scroll( |
| numPixel, 0, // destination x, y |
| 0, 0, // source x, y |
| clientArea.width, clientArea.height, true); |
| moveColumns(TableColumn.FILL, numPixel); |
| } |
| /** |
| * Scroll vertically by 'scrollIndexCount' items. |
| * @param scrollIndexCount - the number of items to scroll. |
| * scrollIndexCount > 0 = scroll up. scrollIndexCount < 0 = scroll down |
| */ |
| void scrollVertical(int scrollIndexCount) { |
| int scrollAmount = scrollIndexCount * getItemHeight(); |
| int headerHeight = getHeaderHeight(); |
| int destY; |
| int sourceY; |
| boolean scrollUp = scrollIndexCount < 0; |
| Rectangle clientArea = getClientArea(); |
| |
| if (scrollIndexCount == 0) { |
| return; |
| } |
| if (scrollUp == true) { |
| destY = headerHeight - scrollAmount; |
| sourceY = headerHeight; |
| } |
| else { |
| destY = headerHeight; |
| sourceY = destY + scrollAmount; |
| } |
| scroll( |
| 0, destY, // destination x, y |
| 0, sourceY, // source x, y |
| clientArea.width, clientArea.height, true); |
| } |
| /** |
| * Scroll items down to make space for a new item added to |
| * the receiver at position 'index'. |
| * @param index - position at which space for one new item |
| * should be made. This index is relative to the first item |
| * of the receiver. |
| */ |
| void scrollVerticalAddingItem(int index) { |
| int itemHeight = getItemHeight(); |
| int sourceY = getHeaderHeight(); |
| Rectangle clientArea = getClientArea(); |
| |
| if (index >= getTopIndex()) { |
| sourceY += (index-getTopIndex()) * itemHeight; |
| } |
| scroll( |
| 0, sourceY + itemHeight, // destination x, y |
| 0, sourceY, // source x, y |
| clientArea.width, clientArea.height, true); |
| } |
| /** |
| * Scroll the items below the item at position 'index' up |
| * so that they cover the removed item. |
| * @param index - index of the removed item |
| */ |
| void scrollVerticalRemovedItem(int index) { |
| int itemHeight = getItemHeight(); |
| int headerHeight = getHeaderHeight(); |
| int destY; |
| Rectangle clientArea = getClientArea(); |
| |
| destY = Math.max(headerHeight, headerHeight + (index - getTopIndex()) * itemHeight); |
| scroll( |
| 0, destY, // destination x, y |
| 0, destY + itemHeight, // source x, y |
| clientArea.width, clientArea.height, true); |
| } |
| /** |
| * Selects the items at the given zero-relative indices in the receiver. |
| * If the item at the given zero-relative index in the receiver |
| * is not selected, it is selected. If the item at the index |
| * was selected, it remains selected. Indices that are out |
| * of range and duplicate indices are ignored. |
| * |
| * @param indices the array of indices for the items to select |
| * |
| * @exception IllegalArgumentException <ul> |
| * <li>ERROR_NULL_ARGUMENT - if the array of indices 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 select(int indices[]) { |
| checkWidget (); |
| if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); |
| int length = indices.length; |
| if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) return; |
| if ((style & SWT.SINGLE) != 0) { |
| deselectAllExcept(getVisibleItem(indices[0])); |
| } |
| SelectableItem item = null; |
| for (int i = length - 1; i >= 0; --i) { |
| item = getVisibleItem(indices[i]); |
| if (item != null) { |
| select(item); |
| } |
| } |
| if (item != null) { |
| setLastSelection(item, false); |
| } |
| } |
| /** |
| * 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. |
| * |
| * @param index the index of the item to select |
| * |
| * @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 select(int index) { |
| checkWidget(); |
| SelectableItem item = getVisibleItem(index); |
| |
| if (isMultiSelect() == false) { |
| deselectAllExcept(getVisibleItem(index)); |
| } |
| if (item != null) { |
| select(item); |
| setLastSelection(item, false); |
| } |
| } |
| /** |
| * Selects the items at the given zero-relative indices in the receiver. |
| * If the item at the index was already selected, it remains |
| * selected. The range of the indices is inclusive. Indices that are |
| * out of range are ignored and no items will be selected if start is |
| * greater than end. |
| * |
| * @param start the start of the range |
| * @param end the end of the range |
| * |
| * @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 select(int start, int end) { |
| checkWidget (); |
| if (end < 0 || start > end || ((style & SWT.SINGLE) != 0 && start != end)) return; |
| int count = getItemVector().size(); |
| if (count == 0 || start >= count) return; |
| start = Math.max (0, start); |
| end = Math.min (end, count - 1); |
| if ((style & SWT.SINGLE) != 0) { |
| deselectAllExcept(getVisibleItem(start)); |
| } |
| // select in the same order as all the other selection and deslection methods. |
| // Otherwise setLastSelection repeatedly changes the lastSelectedItem for repeated |
| // selections of the items, causing flash. |
| SelectableItem item = null; |
| for (int i = end; i >= start; i--) { |
| item = getVisibleItem(i); |
| if (item != null) { |
| select(item); |
| } |
| } |
| if (item != null) { |
| setLastSelection(item, false); |
| } |
| } |
| /** |
| * Selects all the items in the receiver. |
| * |
| * @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 selectAll() { |
| checkWidget(); |
| Enumeration items = getItemVector().elements(); |
| TableItem item = null; |
| |
| if (isMultiSelect() == false) { |
| return; |
| } |
| while (items.hasMoreElements() == true) { |
| item = (TableItem) items.nextElement(); |
| select(item); |
| } |
| if (item != null) { |
| setLastSelection(item, false); |
| } |
| } |
| /** |
| * Set the y position of 'column'. |
| * @param column - the TableColumn that should be set to |
| * a new y position. |
| */ |
| void setColumnPosition(TableColumn column) { |
| Rectangle bounds = column.getBounds(); |
| |
| bounds.y = getHeaderHeight() - getTopIndex() * getItemHeight(); |
| column.setBounds(bounds); |
| } |
| /** |
| * Change the cursor of the receiver. |
| * @param isColumnResizeCursor - indicates whether the column |
| * resize cursor or the regular cursor should be set. |
| */ |
| void setColumnResizeCursor(boolean isColumnResizeCursor) { |
| if (isColumnResizeCursor != this.isColumnResizeCursor) { |
| this.isColumnResizeCursor = isColumnResizeCursor; |
| if (isColumnResizeCursor == true) { |
| setCursor(getColumnResizeCursor()); |
| } |
| else { |
| setCursor(null); |
| } |
| } |
| } |
| /** |
| * Set the current position of the resized column to 'xPosition'. |
| * @param xPosition - the current position of the resized column |
| */ |
| void setColumnResizeX(int xPosition) { |
| columnResizeX = xPosition; |
| } |
| /** |
| * Set the width of the receiver's contents to 'newWidth'. |
| * Content width is used to calculate the horizontal scrollbar. |
| */ |
| void setContentWidth(int newWidth) { |
| TableColumn fillColumn = getFillColumn(); |
| Rectangle fillColumnBounds; |
| int widthDiff = newWidth - getContentWidth(); |
| |
| super.setContentWidth(newWidth); |
| if (fillColumn != null) { |
| fillColumnBounds = fillColumn.getBounds(); |
| fillColumnBounds.x += widthDiff; |
| fillColumnBounds.width = Math.max(0, getClientArea().width - newWidth); |
| fillColumn.setBounds(fillColumnBounds); |
| } |
| } |
| /** |
| * Set the width of the first column to fit 'item' if it is longer than |
| * the current column width. |
| * Do nothing if the user has already set a width. |
| */ |
| void setFirstColumnWidth(TableItem item) { |
| int newWidth; |
| TableColumn column; |
| |
| if (internalGetColumnCount() > 0) { |
| column = internalGetColumn(TableColumn.FIRST); |
| if (column.isDefaultWidth() == true) { |
| newWidth = Math.max(column.getWidth(), item.getPreferredWidth(TableColumn.FIRST)); |
| column.setWidth(newWidth); |
| column.setDefaultWidth(true); // reset to true so that we know when the user has set |
| // the width instead of us setting a default width. |
| } |
| } |
| } |
| public void setFont(Font font) { |
| checkWidget(); |
| int itemCount = getItemCount(); |
| |
| if (font == null || font.equals(getFont()) == true) { |
| return; |
| } |
| setRedraw(false); // disable redraw because itemChanged() triggers undesired redraw |
| resetItemData(); |
| super.setFont(font); |
| |
| GC gc = new GC(this); |
| Point extent = gc.stringExtent("String"); |
| fontHeight = extent.y; |
| gc.dispose(); |
| |
| for (int i = 0; i < itemCount; i++) { |
| itemChanged(getItem(i), 0, getClientArea().width); |
| } |
| setRedraw(true); // re-enable redraw |
| getHeader().setFont(font); |
| } |
| /** |
| * Marks the receiver's header as visible if the argument is <code>true</code>, |
| * and marks it invisible otherwise. |
| * <p> |
| * If one of the receiver's ancestors is not visible or some |
| * other condition makes the receiver not visible, marking |
| * it visible may not actually cause it to be displayed. |
| * </p> |
| * |
| * @param visible the new visibility state |
| * |
| * @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 setHeaderVisible(boolean headerVisible) { |
| checkWidget(); |
| if (headerVisible != getHeaderVisible()) { |
| getHeader().setLocation(0, 0); |
| getHeader().setVisible(headerVisible); |
| // Windows resets scrolling so do we |
| setTopIndex(0, true); |
| moveColumnsVertical(); |
| resizeVerticalScrollbar(); |
| redraw(); |
| } |
| } |
| public void setItemCount (int count) { |
| checkWidget (); |
| count = Math.max (0, count); |
| int itemCount = getItemCount (); |
| if (count == itemCount) return; |
| setRedraw (false); |
| remove (count, itemCount - 1); |
| for (int i = itemCount; i<count; i++) { |
| new TableItem (this, SWT.NONE); |
| } |
| setRedraw (true); |
| } |
| /** |
| * Set the vector that stores the items of the receiver |
| * to 'newVector'. |
| * @param newVector - Vector to use for storing the items of |
| * the receiver. |
| */ |
| void setItemVector(Vector newVector) { |
| items = newVector; |
| } |
| /** |
| * Marks the receiver's lines as visible if the argument is <code>true</code>, |
| * and marks it invisible otherwise. |
| * <p> |
| * If one of the receiver's ancestors is not visible or some |
| * other condition makes the receiver not visible, marking |
| * it visible may not actually cause it to be displayed. |
| * </p> |
| * |
| * @param visible the new visibility state |
| * |
| * @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 setLinesVisible(boolean drawGridLines) { |
| checkWidget(); |
| if (this.drawGridLines != drawGridLines) { |
| this.drawGridLines = drawGridLines; |
| redraw(); |
| } |
| } |
| public void setRedraw(boolean redraw) { |
| checkWidget(); |
| super.setRedraw(redraw); |
| getHeader().setRedraw(redraw); |
| } |
| /** |
| * Set the column that is being resized to 'column'. |
| * @param column - the TableColumn that is being resized. |
| * A null value indicates that no column resize operation is |
| * in progress. |
| */ |
| void setResizeColumn(TableColumn column) { |
| resizeColumn = column; |
| } |
| /** |
| * Selects the items at the given zero-relative indices in the receiver. |
| * The current selected is first cleared, then the new items are selected. |
| * |
| * @param indices the indices of the items to select |
| * |
| * @exception IllegalArgumentException <ul> |
| * <li>ERROR_NULL_ARGUMENT - if the array of indices 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> |
| * |
| * @see Table#deselectAll() |
| * @see Table#select(int[]) |
| */ |
| public void setSelection(int [] indices) { |
| checkWidget (); |
| if (indices == null) error (SWT.ERROR_NULL_ARGUMENT); |
| int length = indices.length; |
| if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) { |
| deselectAll (); |
| return; |
| } |
| if ((style & SWT.MULTI) != 0) { |
| Vector keepSelected = new Vector(length); |
| for (int i = 0; i < length; i++) { |
| SelectableItem item = getVisibleItem(indices[i]); |
| if (item != null) { |
| keepSelected.addElement(item); |
| } |
| } |
| deselectAllExcept(keepSelected); |
| } |
| select(indices); |
| showSelection (); |
| } |
| /** |
| * Sets the receiver's selection to be the given array of items. |
| * The current selected is first cleared, then the new items are |
| * selected. |
| * |
| * @param items the array of items |
| * |
| * @exception IllegalArgumentException <ul> |
| * <li>ERROR_NULL_ARGUMENT - if the array of items is null</li> |
| * <li>ERROR_INVALID_ARGUMENT - if one of 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> |
| * |
| * @see Table#deselectAll() |
| * @see Table#select(int) |
| */ |
| public void setSelection(TableItem items[]) { |
| checkWidget (); |
| if (items == null) error (SWT.ERROR_NULL_ARGUMENT); |
| int length = items.length; |
| if (length == 0 || ((style & SWT.SINGLE) != 0 && length > 1)) { |
| deselectAll (); |
| return; |
| } |
| setSelectableSelection(items); |
| } |
| /** |
| * Selects the item at the given zero-relative index in the receiver. |
| * The current selected is first cleared, then the new item is selected. |
| * |
| * @param index the index of the item to select |
| * |
| * @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> |
| * |
| * @see Table#deselectAll() |
| * @see Table#select(int) |
| */ |
| public void setSelection(int index) { |
| checkWidget(); |
| deselectAllExcept(getVisibleItem(index)); |
| select(index); |
| showSelection (); |
| } |
| /** |
| * Selects the items at the given zero-relative indices in the receiver. |
| * The current selection is first cleared, then 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. |
| * |
| * @param start the start index of the items to select |
| * @param end the end index of the items to select |
| * |
| * @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> |
| * |
| * @see Table#deselectAll() |
| * @see Table#select(int,int) |
| */ |
| public void setSelection(int start, int end) { |
| checkWidget (); |
| if (end < 0 || start > end || ((style & SWT.SINGLE) != 0 && start != end)) { |
| deselectAll (); |
| return; |
| } |
| int count = getItemVector().size(); |
| if (count == 0 || start >= count) { |
| deselectAll (); |
| return; |
| } |
| start = Math.max (0, start); |
| end = Math.min (end, count - 1); |
| if ((style & SWT.MULTI) != 0) { |
| Vector keepSelected = new Vector(); |
| for (int i = start; i <= end; i++) { |
| SelectableItem item = getVisibleItem(i); |
| if (item != null) { |
| keepSelected.addElement(item); |
| } |
| } |
| deselectAllExcept(keepSelected); |
| } |
| select(start, end); |
| showSelection (); |
| } |
| /** |
| * 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 |
| * |
| * @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 setTopIndex(int index) { |
| checkWidget(); |
| int itemCount = getItemCount(); |
| int itemCountWhole = getItemCountWhole(); |
| if (index < 0 || itemCount == 0) return; |
| if (index >= itemCount) index = itemCount - 1; |
| if (itemCount > itemCountWhole) { |
| if (index + itemCountWhole <= itemCount) { |
| setTopIndex(index, true); |
| } else if (index > itemCount - itemCountWhole) { |
| setTopIndex(itemCount - itemCountWhole, true); |
| } else { |
| showSelectableItem(index); |
| } |
| } |
| } |
| /** |
| * Set the index of the first visible item in the receiver's client |
| * area to 'index'. |
| * @param index - 0-based index of the first visible item in the |
| * receiver's client area. |
| * @param adjustScrollbar - true=set the position of the vertical |
| * scroll bar to the new top index. |
| * false=don't adjust the vertical scroll bar |
| */ |
| void setTopIndexNoScroll(int index, boolean adjustScrollbar) { |
| super.setTopIndexNoScroll(index, adjustScrollbar); |
| moveColumnsVertical(); |
| } |
| |
| /** |
| * 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 |
| * |
| * @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> |
| * |
| * @since 3.0 |
| */ |
| public void showColumn (TableColumn column) { |
| checkWidget (); |
| if (column == null) error (SWT.ERROR_NULL_ARGUMENT); |
| if (column.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); |
| if (column.getParent() != this) return; |
| if (columns == null || columns.size() <= 1) return; |
| } |
| |
| /** |
| * Shows the item. If the item is already showing in the receiver, |
| * this method simply returns. Otherwise, the items are scrolled until |
| * the item is visible. |
| * |
| * @param item the item to be shown |
| * |
| * @exception IllegalArgumentException <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> |
| * |
| * @see Table#showSelection() |
| */ |
| public void showItem(TableItem item) { |
| checkWidget(); |
| if (item == null) error (SWT.ERROR_NULL_ARGUMENT); |
| if (item.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); |
| showSelectableItem(item); |
| } |
| /** |
| * 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. |
| * |
| * @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> |
| * |
| * @see Table#showItem(TableItem) |
| */ |
| public void showSelection() { |
| checkWidget(); |
| super.showSelection(); |
| } |
| void sort (int [] items) { |
| /* Shell Sort from K&R, pg 108 */ |
| int length = items.length; |
| for (int gap=length/2; gap>0; gap/=2) { |
| for (int i=gap; i<length; i++) { |
| for (int j=i-gap; j>=0; j-=gap) { |
| if (items [j] <= items [j + gap]) { |
| int swap = items [j]; |
| items [j] = items [j + gap]; |
| items [j + gap] = swap; |
| } |
| } |
| } |
| } |
| } |
| /** |
| * Start a column resize operation. |
| * @param event - the mouse event that occured over the header |
| * widget |
| */ |
| void startColumnResize(Event event) { |
| Vector columns = internalGetColumnVector(); |
| TableColumn hitColumn = getColumnAtX(event.x); |
| Rectangle hitColumnBounds; |
| int hitIndex = hitColumn.getIndex(); |
| |
| if (hitColumn == getFillColumn()) { // clicked on the fill column? |
| hitColumn = (TableColumn) columns.lastElement(); // resize the last real column |
| } |
| else |
| if ((event.x - hitColumn.getBounds().x <= COLUMN_RESIZE_OFFSET) && // check if left side of a column was clicked |
| (hitIndex > 0)) { |
| hitColumn = (TableColumn) columns.elementAt(hitIndex - 1); // resize the preceding column |
| } |
| hitColumnBounds = hitColumn.getBounds(); |
| setColumnResizeX(hitColumnBounds.x + hitColumnBounds.width); |
| setResizeColumn(hitColumn); |
| } |
| /** |
| * Return 'text' after it has been checked to be no longer than 'maxWidth' |
| * when drawn on 'gc'. |
| * If it is too long it will be truncated up to the last character. |
| * @param text - the String that should be checked for length |
| * @param maxWidth - maximum width of 'text' |
| * @param gc - GC to use for String measurement |
| */ |
| String trimItemText(String text, int maxWidth, GC gc) { |
| int textWidth; |
| int dotsWidth; |
| |
| if (text != null && text.length() > 1) { |
| textWidth = gc.stringExtent(text).x; |
| if (textWidth > maxWidth) { |
| dotsWidth = gc.stringExtent(Table.DOT_STRING).x; |
| while (textWidth + dotsWidth > maxWidth && text.length() > 1) { |
| text = text.substring(0, text.length() - 1); // chop off one character at the end |
| textWidth = gc.stringExtent(text).x; |
| } |
| text = text.concat(Table.DOT_STRING); |
| } |
| } |
| return text; |
| } |
| |
| } |