| package org.eclipse.swt.widgets;
|
|
|
| /*
|
| * Copyright (c) 2000, 2002 IBM Corp. All rights reserved. |
| * This file is 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
|
| */
|
|
|
| import org.eclipse.swt.*;
|
| import org.eclipse.swt.events.*;
|
| import org.eclipse.swt.graphics.*;
|
|
|
| /**
|
| * Instances of this class represent a column in a table widget.
|
| * <dl>
|
| * <dt><b>Styles:</b></dt>
|
| * <dd>LEFT, RIGHT, CENTER</dd>
|
| * <dt><b>Events:</b></dt>
|
| * <dd> Move, Resize, Selection</dd>
|
| * </dl>
|
| * <p>
|
| * Note: Only one of the styles LEFT, RIGHT and CENTER may be specified.
|
| * </p><p>
|
| * IMPORTANT: This class is <em>not</em> intended to be subclassed.
|
| * </p>
|
| */ |
| public class TableColumn extends Item {
|
| static final int FIRST = 0; // index of the first column
|
| static final int FILL = -1; // index that identifies the column used to
|
| // fill space not used by other columns.
|
| private static final int DEFAULT_WIDTH = 10;
|
|
|
| private Table parent;
|
| private int index; // 0-based column index
|
| private Rectangle bounds = new Rectangle(0, 0, 0, 0);
|
| private boolean isDefaultWidth = true;
|
| private boolean resize = true;
|
|
|
| /**
|
| * Create a new TableColumn without adding it to the parent.
|
| * Currently used to create fill columns and default columns.
|
| * @see createFillColumn
|
| * @see createDefaultColumn
|
| * @param parent - Table widget the new instance will be a child of.
|
| */ |
| TableColumn(Table parent) {
|
| super(parent, SWT.NULL);
|
| this.parent = parent;
|
| }
|
|
|
| /**
|
| * Constructs a new instance of this class given its parent
|
| * (which must be a <code>Table</code>) and a style value
|
| * describing its behavior and appearance. The item is added
|
| * to the end of the items maintained by its parent.
|
| * <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#LEFT
|
| * @see SWT#RIGHT
|
| * @see SWT#CENTER
|
| * @see Widget#checkSubclass
|
| * @see Widget#getStyle
|
| */ |
| public TableColumn(Table parent, int style) {
|
| this(parent, style, checkNull(parent).getColumnCount());
|
| }
|
|
|
| /**
|
| * Constructs a new instance of this class given its parent
|
| * (which must be a <code>Table</code>), a style value
|
| * describing its behavior and appearance, and the index
|
| * at which to place it in the items maintained by its parent.
|
| * <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
|
| * @param index the index to store the receiver in its parent
|
| *
|
| * @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#LEFT
|
| * @see SWT#RIGHT
|
| * @see SWT#CENTER
|
| * @see Widget#checkSubclass
|
| * @see Widget#getStyle
|
| */ |
| public TableColumn(Table parent, int style, int index) {
|
| super(parent, checkStyle (style), index);
|
|
|
| this.parent = parent;
|
| if (index < 0 || index > parent.getColumnCount()) {
|
| error(SWT.ERROR_INVALID_RANGE);
|
| }
|
| setIndex(index);
|
| parent.addColumn(this);
|
| setWidth(DEFAULT_WIDTH);
|
| setDefaultWidth(true);
|
| addListener(SWT.Dispose, new Listener() {
|
| public void handleEvent(Event event) {disposeColumn();}
|
| });
|
| }
|
| /**
|
| * Adds the listener to the collection of listeners who will
|
| * be notified when the control is moved or resized, by sending
|
| * it one of the messages defined in the <code>ControlListener</code>
|
| * interface.
|
| *
|
| * @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 ControlListener
|
| * @see #removeControlListener
|
| */ |
| public void addControlListener(ControlListener listener) {
|
| checkWidget();
|
| if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
|
| TypedListener typedListener = new TypedListener (listener);
|
| addListener (SWT.Resize,typedListener);
|
| addListener (SWT.Move,typedListener);
|
| }
|
| /**
|
| * Adds the listener to the collection of listeners who will
|
| * be notified when the control is selected, by sending
|
| * it one of the messages defined in the <code>SelectionListener</code>
|
| * interface.
|
| * <p>
|
| * <code>widgetSelected</code> is called when the column header is selected.
|
| * <code>widgetDefaultSelected</code> is not called.
|
| * </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);
|
| }
|
| /**
|
| * Throw an SWT.ERROR_NULL_ARGUMENT exception if 'table' is null.
|
| * Otherwise return 'table'
|
| */ |
| static Table checkNull(Table table) {
|
| if (table == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
|
| return table;
|
| }
|
| static int checkStyle (int style) {
|
| return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
|
| }
|
| protected void checkSubclass () {
|
| if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
|
| }
|
| /**
|
| * Create a new instance of TableColumn that acts as a default column
|
| * if the user does not create a TableColumn.
|
| * @param parent - Table widget the new instance will be a child of.
|
| */ |
| static TableColumn createDefaultColumn(Table parent) {
|
| TableColumn defaultColumn = new TableColumn(parent);
|
|
|
| defaultColumn.setIndex(FIRST);
|
| defaultColumn.setWidth(DEFAULT_WIDTH);
|
| defaultColumn.setDefaultWidth(true);
|
| return defaultColumn;
|
| }
|
| /**
|
| * Create a new instance of TableColumn that acts as the rightmost
|
| * fill column in a Table. The new object is not added to the parent
|
| * like a regular column is.
|
| * @param parent - Table widget the new instance will be a child of.
|
| */ |
| static TableColumn createFillColumn(Table parent) {
|
| TableColumn fillColumn = new TableColumn(parent);
|
|
|
| fillColumn.setIndex(FILL);
|
| return fillColumn;
|
| }
|
| /**
|
| * Remove the receiver from its parent
|
| */ |
| void disposeColumn() {
|
| getParent().removeColumn(this);
|
| }
|
| /**
|
| * Returns a value which describes the position of the
|
| * text or image in the receiver. The value will be one of
|
| * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>.
|
| *
|
| * @return the alignment
|
| *
|
| * @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 getAlignment () {
|
| checkWidget();
|
| if ((style & SWT.LEFT) != 0) return SWT.LEFT;
|
| if ((style & SWT.CENTER) != 0) return SWT.CENTER;
|
| if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
|
| return SWT.LEFT;
|
| }
|
|
|
| /**
|
| * Answer the bounding rectangle of the receiver.
|
| */ |
| Rectangle getBounds() {
|
| return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height); // copy the object to prevent changes
|
| }
|
| public Display getDisplay() {
|
| if (parent == null) { // access parent field directly to prevent endless recursion
|
| error(SWT.ERROR_WIDGET_DISPOSED);
|
| }
|
| return parent.getDisplay();
|
| }
|
| /**
|
| * Answer the index of the receiver. Specifies the position of the
|
| * receiver relative to other columns in the parent.
|
| */ |
| int getIndex() {
|
| return index;
|
| }
|
| /**
|
| * Returns the receiver's parent, which must be a <code>Table</code>.
|
| *
|
| * @return the receiver's parent
|
| *
|
| * @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 Table getParent() {
|
| checkWidget();
|
| return parent;
|
| }
|
| /**
|
| * Gets the resizable attribute. A column that is
|
| * not resizable cannot be dragged by the user but
|
| * may be resized by the programmer.
|
| *
|
| * @return the resizable attribute
|
| *
|
| * @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 getResizable() {
|
| checkWidget();
|
| return resize;
|
| }
|
| /**
|
| * Gets the width of the receiver.
|
| *
|
| * @return the width
|
| *
|
| * @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 getWidth () {
|
| checkWidget();
|
| return getBounds().width;
|
| }
|
| /**
|
| * Set the colun bounds.
|
| */ |
| void internalSetBounds(Rectangle newBounds) {
|
| bounds = newBounds;
|
| }
|
| /**
|
| * Answer whether the column has a default width or if a width has been
|
| * set by the user.
|
| * @return
|
| * true=column width is a default width set internally
|
| * false=column width has been set by the user.
|
| */ |
| boolean isDefaultWidth() {
|
| return isDefaultWidth;
|
| }
|
| /**
|
| * Causes the receiver to be resized to its preferred size.
|
| * For a composite, this involves computing the preferred size
|
| * from its layout, if there is one.
|
| *
|
| * @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 pack() {
|
| checkWidget();
|
| Table parent = getParent();
|
| int index = parent.indexOf(this);
|
|
|
| if (getIndex() != TableColumn.FILL && index != -1) {
|
| setWidth(parent.getPreferredColumnWidth(index));
|
| }
|
| }
|
|
|
| /**
|
| * Removes the listener from the collection of listeners who will
|
| * be notified when the control is moved or resized.
|
| *
|
| * @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 ControlListener
|
| * @see #addControlListener
|
| */ |
| public void removeControlListener (ControlListener listener) {
|
| checkWidget();
|
| if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
|
| if (eventTable == null) return;
|
| eventTable.unhook (SWT.Move, listener);
|
| eventTable.unhook (SWT.Resize, listener);
|
| }
|
| /**
|
| * Removes the listener from the collection of listeners who will
|
| * be notified when the control is selected.
|
| *
|
| * @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 #addSelectionListener
|
| */ |
| public void removeSelectionListener(SelectionListener listener) {
|
| checkWidget();
|
| if (listener == null) {
|
| error(SWT.ERROR_NULL_ARGUMENT);
|
| }
|
| removeListener(SWT.Selection, listener);
|
| removeListener(SWT.DefaultSelection, listener);
|
| }
|
| /**
|
| * Controls how text and images will be displayed in the receiver.
|
| * The argument should be one of <code>LEFT</code>, <code>RIGHT</code>
|
| * or <code>CENTER</code>.
|
| *
|
| * @param alignment the new alignment
|
| *
|
| * @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 setAlignment(int alignment) {
|
| checkWidget();
|
| int index = getIndex();
|
|
|
| if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) != 0 && index != 0) { // ignore calls for the first column to match Windows behavior
|
| style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
|
| style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
|
| getParent().getHeader().redraw(index);
|
| }
|
| }
|
| /**
|
| * Set the bounding rectangle of the receiver to 'newBounds'.
|
| * Notify the table widget if the column width changes.
|
| * @param newBounds - the new bounding rectangle of the receiver,
|
| * consisting of x, y, width, height
|
| */ |
| void setBounds(Rectangle newBounds) {
|
| if (newBounds.width != bounds.width) {
|
| if (isDefaultWidth() == true) {
|
| setDefaultWidth(false);
|
| }
|
| getParent().columnChange(this, newBounds);
|
| }
|
| else {
|
| // columnChange causes update (via scroll) which may flush redraw
|
| // based on old bounds. Setting bounds after notifying table fixes 1GABZR5
|
| // Table sets column bounds at appropriate time when called above with
|
| // width change. Only set bounds when table was not called. Fixes 1GCGDPB
|
| bounds = newBounds;
|
| }
|
| }
|
| /**
|
| * Set whether the column has a default width or if a width has been
|
| * set by the user.
|
| * @param isDefaultWidth
|
| * true=column width is a default width set internally
|
| * false=column width has been set by the user
|
| */ |
| void setDefaultWidth(boolean isDefaultWidth) {
|
| this.isDefaultWidth = isDefaultWidth;
|
| }
|
| public void setImage(Image image) {
|
| super.setImage(image);
|
| Header header = parent.getHeader();
|
| header.setHeaderHeight();
|
| header.redraw();
|
| parent.redraw();
|
| }
|
| /**
|
| * Set the index of the receiver to 'newIndex'. The index specifies the
|
| * position of the receiver relative to other columns in the parent.
|
| */ |
| void setIndex(int newIndex) {
|
| this.index = newIndex;
|
| }
|
| /**
|
| * Sets the resizable attribute. A column that is
|
| * not resizable cannot be dragged by the user but
|
| * may be resized by the programmer.
|
| *
|
| * @param resizable the resize attribute
|
| *
|
| * @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 setResizable(boolean resize) {
|
| checkWidget();
|
| this.resize = resize;
|
| }
|
| public void setText(String newText) {
|
| checkWidget();
|
| int index = getIndex();
|
|
|
| if (newText == null) {
|
| error(SWT.ERROR_NULL_ARGUMENT);
|
| }
|
| if (index != FILL && (text == null || text.equals(newText) == false)) {
|
| super.setText(newText);
|
| getParent().getHeader().redraw(index);
|
| }
|
| }
|
| /**
|
| * Sets the width of the receiver.
|
| *
|
| * @param width the new width
|
| *
|
| * @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 setWidth(int width) {
|
| checkWidget();
|
| Rectangle bounds = getBounds();
|
| int oldWidth = bounds.width;
|
| int redrawX;
|
|
|
| if (width != oldWidth) {
|
| redrawX = bounds.x;
|
| bounds.width = width;
|
| setBounds(bounds);
|
| // redraw at old column position if column was resized wider.
|
| // fixes focus rectangle.
|
| redrawX += Math.min(width, oldWidth);
|
| parent.redraw(
|
| redrawX - 2, 0,
|
| 2, parent.getClientArea().height, false); // redraw 2 pixels wide to redraw item focus rectangle and grid line
|
| }
|
| }
|
| }
|