/******************************************************************************* * Copyright (c) 2012, 2015 EclipseSource and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * EclipseSource - initial API and implementation ******************************************************************************/ package org.eclipse.nebula.widgets.grid; import static org.eclipse.swt.internal.widgets.MarkupUtil.isToolTipMarkupEnabledFor; import static org.eclipse.swt.internal.widgets.MarkupValidator.isValidationDisabledFor; import org.eclipse.nebula.widgets.grid.internal.gridcolumnkit.GridColumnLCA; import org.eclipse.rap.rwt.RWT; import org.eclipse.rap.rwt.internal.lifecycle.WidgetLCA; import org.eclipse.rap.rwt.internal.textsize.TextSizeUtil; import org.eclipse.rap.rwt.theme.BoxDimensions; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.internal.widgets.MarkupValidator; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Item; import org.eclipse.swt.widgets.TypedListener; /** * <p> * NOTE: THIS WIDGET AND ITS API ARE STILL UNDER DEVELOPMENT. THIS IS A * PRE-RELEASE ALPHA VERSION. USERS SHOULD EXPECT API CHANGES IN FUTURE * VERSIONS. * </p> * Instances of this class represent a column in a grid widget. * <p> * <dl> * <dt><b>Styles:</b></dt> * <dd>SWT.LEFT, SWT.RIGHT, SWT.CENTER<!--, SWT.CHECK--></dd> * <dt><b>Events:</b></dt> * <dd>Move, Resize, Selection, Show, Hide</dd> * </dl> */ @SuppressWarnings( "restriction" ) public class GridColumn extends Item { static final String FOOTER_SPAN = "footerSpan"; private static final int SORT_INDICATOR_WIDTH = 10; private static final int MARGIN_IMAGE = 3; private static final int DEFAULT_WIDTH = 10; private int width = DEFAULT_WIDTH; private int minimumWidth; private Grid parent; private GridColumnGroup group; private int sortStyle = SWT.NONE; private boolean check; private boolean tableCheck; private boolean moveable; private boolean resizeable = true; private boolean checkable = true; private boolean detail = true; private boolean summary = true; private boolean visible = true; private int alignment = SWT.LEFT; private Font headerFont; private String headerTooltip; private String footerText = ""; private Image footerImage; private Font footerFont; private int footerSpan = 1; private boolean packed; private boolean wordWrap; private boolean headerWordWrap; int imageCount; int textCount; /** * Constructs a new instance of this class given its parent (which must be a * <code>Grid</code>) and a style value describing its behavior and * appearance. The item is added to the end of the items maintained by its * parent. * * @param parent * an Grid control which will be the parent of the new instance * (cannot be null) * @param style * the style of control to construct * @throws IllegalArgumentException * <ul> * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> * </ul> * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the parent</li> * <li> * ERROR_INVALID_SUBCLASS - if this class is not an allowed * subclass</li> * </ul> */ public GridColumn( Grid parent, int style ) { this( parent, style, -1 ); } /** * Constructs a new instance of this class given its parent (which must be a * <code>Grid</code>), a style value describing its behavior and appearance, * and the index at which to place it in the items maintained by its parent. * * @param parent * an Grid 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 * @throws IllegalArgumentException * <ul> * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> * </ul> * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the parent</li> * <li> * ERROR_INVALID_SUBCLASS - if this class is not an allowed * subclass</li> * </ul> */ public GridColumn( Grid parent, int style, int index ) { super( parent, style, index ); init( parent, style, index ); } /** * Constructs a new instance of this class given its parent column group * (which must be a <code>GridColumnGroup</code>), a style value describing * its behavior and appearance, and the index at which to place it in the * items maintained by its parent. * * @param parent * an Grid control which will be the parent of the new instance * (cannot be null) * @param style * the style of control to construct * @throws IllegalArgumentException * <ul> * <li>ERROR_NULL_ARGUMENT - if the parent is null</li> * </ul> * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the parent</li> * <li> * ERROR_INVALID_SUBCLASS - if this class is not an allowed * subclass</li> * </ul> */ public GridColumn( GridColumnGroup parent, int style ) { super( parent.getParent(), style, parent.getNewColumnIndex() ); init( parent.getParent(), style, parent.getNewColumnIndex() ); group = parent; group.newColumn( this ); } /** * {@inheritDoc} */ @Override public void dispose() { if( !parent.isDisposing() && !isDisposed() ) { parent.removeColumn( this ); if( group != null ) { group.removeColumn( this ); } } super.dispose(); } /** * Returns the parent grid. * * @return the parent grid. * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public Grid getParent() { checkWidget(); return parent; } /** * Returns the column group if this column was created inside a group, or * {@code null} otherwise. * * @return the column group. * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public GridColumnGroup getColumnGroup() { checkWidget(); return group; } /** * Adds the listener to the collection of listeners who will be notified * when the receiver's is pushed, by sending it one of the messages defined * in the <code>SelectionListener</code> interface. * * @param listener * the listener which should be notified * @throws IllegalArgumentException * <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void addSelectionListener( SelectionListener listener ) { checkWidget(); if( listener == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } TypedListener typedListener = new TypedListener( listener ); addListener( SWT.Selection, typedListener ); addListener( SWT.DefaultSelection, typedListener ); } /** * Removes the listener from the collection of listeners who will be * notified when the receiver's selection changes. * * @param listener * the listener which should no longer be notified * @see SelectionListener * @see #addSelectionListener(SelectionListener) * @throws org.eclipse.swt.SWTException * <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 removeSelectionListener( SelectionListener listener ) { checkWidget(); if( listener == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } removeListener( SWT.Selection, listener ); removeListener( SWT.DefaultSelection, listener ); } /** * Adds a listener to the list of listeners notified when the column is * moved or resized. * * @param listener * listener * @throws IllegalArgumentException * <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void addControlListener( ControlListener listener ) { checkWidget(); if( listener == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } TypedListener typedListener = new TypedListener( listener ); addListener( SWT.Move, typedListener ); addListener( SWT.Resize, typedListener ); } /** * Removes the given control listener. * * @param listener * listener. * @throws IllegalArgumentException * <ul> * <li>ERROR_NULL_ARGUMENT - if the listener is null</li> * </ul> * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void removeControlListener( ControlListener listener ) { checkWidget(); if( listener == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } removeListener( SWT.Move, listener ); removeListener( SWT.Resize, listener ); } /** * Sets the width of the column. * * @param width * new width * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setWidth( int width ) { checkWidget(); internalSetWidth( width ); } /** * Returns the width of the column. * * @return width of column * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public int getWidth() { checkWidget(); return width; } /** * Set the minimum width of the column * * @param minimumWidth * the minimum width */ public void setMinimumWidth( int minimumWidth ) { checkWidget(); this.minimumWidth = Math.max( 0, minimumWidth ); if( minimumWidth > width ) { internalSetWidth( minimumWidth ); } } /** * @return the minimum width */ public int getMinimumWidth() { checkWidget(); return minimumWidth; } @Override public void setText( String text ) { super.setText( text ); parent.layoutCache.invalidateHeaderHeight(); parent.scheduleRedraw(); } @Override public void setImage( Image image ) { super.setImage( image ); parent.layoutCache.invalidateHeaderHeight(); parent.scheduleRedraw(); } /** * Sets the sort indicator style for the column. This method does not actual * sort the data in the table. Valid values include: SWT.UP, SWT.DOWN, * SWT.NONE. * * @param style * SWT.UP, SWT.DOWN, SWT.NONE * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setSort( int style ) { checkWidget(); if( style == SWT.UP || style == SWT.DOWN || style == SWT.NONE ) { // TODO: [if] Currently, client implementation supports only one sort column if( style != SWT.NONE ) { for( int i = 0; i < parent.getColumnCount(); i++ ) { GridColumn column = parent.getColumn( i ); if( column != this ) { column.setSort( SWT.NONE ); } } } sortStyle = style; parent.redraw(); } } /** * Returns the sort indicator value. * * @return SWT.UP, SWT.DOWN, SWT.NONE * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public int getSort() { checkWidget(); return sortStyle; } /** * Sets the column moveable or fixed. * * @param moveable * true to enable column moving * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setMoveable( boolean moveable ) { checkWidget(); this.moveable = moveable; parent.redraw(); } /** * Returns true if this column is moveable. * * @return true if moveable. * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public boolean getMoveable() { checkWidget(); return moveable; } /** * Sets the column resizeable. * * @param resizeable * true to make the column resizeable * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setResizeable( boolean resizeable ) { checkWidget(); this.resizeable = resizeable; } /** * Returns true if the column is resizeable. * * @return true if the column is resizeable. * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public boolean getResizeable() { checkWidget(); return resizeable; } /** * Sets the checkable state. If false the checkboxes in the column cannot be * checked. * * @param checkable * the new checkable state. * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setCheckable(boolean checkable) { checkWidget(); this.checkable = checkable; } /** * Returns the checkable state. If false the checkboxes in the column cannot * be checked. * * @return true if the column is checkable (only applicable when style is * SWT.CHECK). * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public boolean getCheckable() { checkWidget(); return checkable; } /** * Sets the column as a detail column in a column group. Detail columns are * shown when a column group is expanded. If this column was not created in * a column group, this method has no effect. * * @param detail * true to show this column when the group is expanded. * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setDetail( boolean detail ) { checkWidget(); this.detail = detail; } /** * Returns true if this column is set as a detail column in a column group. * Detail columns are shown when the group is expanded. * * @return true if the column is a detail column. * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public boolean isDetail() { checkWidget(); return detail; } /** * Sets the column as a summary column in a column group. Summary columns * are shown when a column group is collapsed. If this column was not * created in a column group, this method has no effect. * * @param summary * true to show this column when the group is collapsed. * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setSummary( boolean summary ) { checkWidget(); this.summary = summary; } /** * Returns true if this column is set as a summary column in a column group. * Summary columns are shown when the group is collapsed. * * @return true if the column is a summary column. * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public boolean isSummary() { checkWidget(); return summary; } /** * Sets the column's visibility. * * @param visible * the visible to set * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setVisible( boolean visible ) { checkWidget(); boolean before = isVisible(); this.visible = visible; if( isVisible() != before ) { if( visible ) { notifyListeners( SWT.Show, new Event() ); } else { notifyListeners( SWT.Hide, new Event() ); } GridColumn[] orderedColumns = parent.getColumnsInOrder(); boolean fire = false; for( int i = 0; i < orderedColumns.length; i++ ) { GridColumn column = orderedColumns[ i ]; if( column == this ) { fire = true; } else if( fire && column.isVisible() ) { column.fireMoved(); } } parent.redraw(); } } /** * Returns the visibility state as set with {@code setVisible}. * * @return the visible * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public boolean getVisible() { checkWidget(); return visible; } /** * Returns true if the column is visible, false otherwise. If the column is * in a group and the group is not expanded and this is a detail column, * returns false (and vice versa). * * @return true if visible, false otherwise * * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public boolean isVisible() { checkWidget(); boolean result = visible; if( group != null && !group.isDisposed() ) { if( ( group.getExpanded() && !isDetail() ) || ( !group.getExpanded() && !isSummary() ) ) { result = false; } } return result; } /** * Returns true if the column includes a check box. * * @return true if the column includes a check box. * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public boolean isCheck() { checkWidget(); return check || tableCheck; } /** * Returns true if this column includes a tree toggle. * * @return true if the column includes the tree toggle. * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public boolean isTree() { checkWidget(); return parent.isTreeColumn( parent.indexOf( this ) ); } /** * Sets the column alignment. * * @param alignment * SWT.LEFT, SWT.RIGHT, SWT.CENTER * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setAlignment( int alignment ) { checkWidget(); if( alignment == SWT.LEFT || alignment == SWT.CENTER || alignment == SWT.RIGHT ) { this.alignment = alignment; } } /** * Returns the column alignment. * * @return SWT.LEFT, SWT.RIGHT, SWT.CENTER * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public int getAlignment() { checkWidget(); return alignment; } /** * Returns the true if the cells in receiver wrap their text. * * @return true if the cells wrap their text. * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public boolean getWordWrap() { checkWidget(); return wordWrap; } /** * If the argument is true, wraps the text in the receiver's cells. This * feature will not cause the row height to expand to accommodate the * wrapped text. Please use <code>Grid#setItemHeight</code> to change the * height of each row. * * @param wordWrap * true to make cells wrap their text. * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setWordWrap( boolean wordWrap ) { checkWidget(); if( this.wordWrap != wordWrap ) { this.wordWrap = wordWrap; parent.scheduleRedraw(); } } /** * Sets the Font to be used when displaying the Header text. * * @param font * the new header font (or null) * @throws IllegalArgumentException * <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been * disposed</li> * </ul> * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setHeaderFont( Font font ) { checkWidget(); if( font != null && font.isDisposed() ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } headerFont = font; parent.layoutCache.invalidateHeaderHeight(); parent.scheduleRedraw(); } /** * Returns the font that the receiver will use to paint textual information * for the header. * * @return the receiver's font * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public Font getHeaderFont() { checkWidget(); return headerFont == null ? parent.getFont() : headerFont; } /** * Sets the tooltip text of the column header. * * @param toolTipText the tooltip text * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setHeaderTooltip( String toolTipText ) { checkWidget(); if( toolTipText != null && isToolTipMarkupEnabledFor( this ) && !isValidationDisabledFor( this ) ) { MarkupValidator.getInstance().validate( toolTipText ); } headerTooltip = toolTipText; } /** * Returns the tooltip of the column header. * * @return the tooltip text (or null) * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public String getHeaderTooltip() { checkWidget(); return headerTooltip; } /** * Sets whether or not text is word-wrapped in the header for this column. * If Grid.setAutoHeight(true) is set, the row height is adjusted to * accommodate word-wrapped text. * * @param wordWrap * Set to true to wrap the text, false otherwise * @see #getHeaderWordWrap() */ public void setHeaderWordWrap( boolean wordWrap ) { checkWidget(); if( headerWordWrap != wordWrap ) { headerWordWrap = wordWrap; parent.layoutCache.invalidateHeaderHeight(); parent.layoutCache.invalidateFooterHeight(); parent.scheduleRedraw(); } } /** * Returns whether or not text is word-wrapped in the header for this * column. * * @return true if the header wraps its text. * @see GridColumn#setHeaderWordWrap(boolean) */ public boolean getHeaderWordWrap() { checkWidget(); return headerWordWrap; } /** * Sets the receiver's footer text. * * @param text * the new text * * @exception IllegalArgumentException * <ul> * <li>ERROR_NULL_ARGUMENT - if the text is null</li> * </ul> * @exception org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been * disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setFooterText( String text ) { checkWidget(); if( text == null ) { SWT.error( SWT.ERROR_NULL_ARGUMENT ); } footerText = text; parent.layoutCache.invalidateFooterHeight(); } /** * Returns the receiver's footer text, which will be an empty string if it * has never been set. * * @return the receiver's text * * @exception org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been * disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public String getFooterText() { checkWidget(); return footerText; } /** * Sets the receiver's footer image to the argument, which may be null * indicating that no image should be displayed. * * @param image * the image to display on the receiver (may be null) * * @exception IllegalArgumentException * <ul> * <li>ERROR_INVALID_ARGUMENT - if the image has been * disposed</li> * </ul> * @exception org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been * disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setFooterImage( Image image ) { checkWidget(); if( image != null && image.isDisposed() ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } footerImage = image; parent.layoutCache.invalidateFooterHeight(); } /** * Returns the receiver's footer image if it has one, or null if it does * not. * * @return the receiver's image * * @exception org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been * disposed</li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public Image getFooterImage() { checkWidget(); return footerImage; } /** * Sets the Font to be used when displaying the Footer text. * * @param font * the new footer font (or null) * @throws IllegalArgumentException * <ul> * <li>ERROR_INVALID_ARGUMENT - if the argument has been * disposed</li> * </ul> * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void setFooterFont( Font font ) { checkWidget(); if( font != null && font.isDisposed() ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } footerFont = font; parent.layoutCache.invalidateFooterHeight(); parent.scheduleRedraw(); } /** * Returns the font that the receiver will use to paint textual information * for the footer. * * @return the receiver's font * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public Font getFooterFont() { checkWidget(); return footerFont == null ? parent.getFont() : footerFont; } /** * Causes the receiver to be resized to its preferred size. * * @throws org.eclipse.swt.SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * </li> * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the * thread that created the receiver</li> * </ul> */ public void pack() { checkWidget(); int newWidth = Math.max( getPreferredWidth(), parent.getMaxContentWidth( this ) ); setWidth( newWidth ); packed = true; parent.redraw(); } @Override public void setData( String key, Object value ) { handleFooterSpan( key, value ); if( !RWT.TOOLTIP_MARKUP_ENABLED.equals( key ) || !isToolTipMarkupEnabledFor( this ) ) { super.setData( key, value ); } } @Override @SuppressWarnings( "unchecked" ) public <T> T getAdapter( Class<T> adapter ) { if( adapter == WidgetLCA.class ) { return ( T )GridColumnLCA.INSTANCE; } return super.getAdapter( adapter ); } private void handleFooterSpan( String key, Object value ) { if( FOOTER_SPAN.equals( key ) ) { if( !( value instanceof Integer ) || ( ( Integer )value ).intValue() < 1 ) { SWT.error( SWT.ERROR_INVALID_ARGUMENT ); } footerSpan = ( ( Integer )value ).intValue(); if( getHeaderWordWrap() ) { parent.layoutCache.invalidateFooterHeight(); parent.scheduleRedraw(); } } } void repack() { if( packed ) { pack(); } } int getLeft() { int result = 0; boolean found = false; int[] columnOrder = parent.getColumnOrder(); for( int i = 0; i < columnOrder.length && !found; i++ ) { GridColumn currentColumn = parent.getColumn( columnOrder[ i ] ); if( currentColumn == this ) { found = true; } else if( currentColumn.isVisible() ) { result += currentColumn.getWidth(); } } return result; } int getHeaderWrapWidth() { BoxDimensions headerPadding = parent.getHeaderPadding(); int result = width - headerPadding.left - headerPadding.right; Image headerImage = getImage(); if( headerImage != null ) { result -= headerImage.getBounds().width; result -= MARGIN_IMAGE; } if( sortStyle != SWT.NONE ) { result -= SORT_INDICATOR_WIDTH; result -= MARGIN_IMAGE; } return result; } int getFooterWrapWidth() { BoxDimensions headerPadding = parent.getHeaderPadding(); int result = getFooterWidth() - headerPadding.left - headerPadding.right; if( footerImage != null ) { result -= footerImage.getBounds().width; result -= MARGIN_IMAGE; } return result; } private int getFooterWidth() { int result = width; if( footerSpan != 1 ) { boolean found = false; int nextColumns = 0; int[] columnOrder = parent.getColumnOrder(); for( int i = 0; i < columnOrder.length; i++ ) { GridColumn currentColumn = parent.getColumn( columnOrder[ i ] ); if( currentColumn == this ) { found = true; } else if( found && currentColumn.isVisible() && footerSpan > ++nextColumns ) { result += currentColumn.getWidth(); } } } return result; } private int getPreferredWidth() { int headerWidth = 0; String headerText = getText(); Image headerImage = getImage(); headerWidth = getContentWidth( getHeaderFont(), headerText, headerImage ); if( sortStyle != SWT.NONE ) { headerWidth += SORT_INDICATOR_WIDTH; if( headerText.length() > 0 || headerImage != null ) { headerWidth += MARGIN_IMAGE; } } int footerWidth = 0; if( parent.getFooterVisible() ) { footerWidth = getContentWidth( getFooterFont(), footerText, footerImage ); } // Add 1px for the right column border return Math.max( headerWidth, footerWidth ) + 1; } private int getContentWidth( Font font, String text, Image image ) { int contentWidth = 0; if( text.length() > 0 ) { contentWidth += TextSizeUtil.textExtent( font, text, 0 ).x; } if( image != null ) { contentWidth += image.getBounds().width; if( text.length() > 0 ) { contentWidth += MARGIN_IMAGE; } } BoxDimensions headerPadding = parent.getHeaderPadding(); contentWidth += headerPadding.left + headerPadding.right; return contentWidth; } private void internalSetWidth( int width ) { int newWidth = Math.max( minimumWidth, width ); if( this.width != newWidth ) { this.width = newWidth; packed = false; processControlEvents(); if( parent.isAutoHeight() && getHeaderWordWrap() ) { parent.layoutCache.invalidateHeaderHeight(); parent.layoutCache.invalidateFooterHeight(); } parent.scheduleRedraw(); } } protected boolean isTableCheck() { return tableCheck; } protected void setTableCheck( boolean tableCheck ) { this.tableCheck = tableCheck; } private void init( Grid parent, int style, int index ) { this.parent = parent; if( ( style & SWT.RIGHT ) == SWT.RIGHT ) { alignment = SWT.RIGHT; } if( ( style & SWT.CENTER ) == SWT.CENTER ) { alignment = SWT.CENTER; } if( ( style & SWT.CHECK ) == SWT.CHECK ) { check = true; } parent.newColumn( this, index ); } private void processControlEvents() { int[] columnOrder = parent.getColumnOrder(); boolean found = false; for( int i = 0; i < columnOrder.length; i++ ) { GridColumn currentColumn = parent.getColumn( columnOrder[ i ] ); if( currentColumn == this ) { found = true; fireResized(); } else if( found ) { currentColumn.fireMoved(); } } } void fireResized() { Event event = new Event(); event.display = getDisplay(); event.item = this; event.widget = parent; notifyListeners( SWT.Resize, event ); } void fireMoved() { Event event = new Event(); event.display = getDisplay(); event.item = this; event.widget = parent; notifyListeners( SWT.Move, event ); } }