package org.eclipse.swt.widgets; | |
/* | |
* (c) Copyright IBM Corp. 2000, 2001. | |
* All Rights Reserved | |
*/ | |
import org.eclipse.swt.internal.*; | |
import org.eclipse.swt.internal.win32.*; | |
import org.eclipse.swt.*; | |
import org.eclipse.swt.graphics.*; | |
import org.eclipse.swt.events.*; | |
/** | |
* 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> | |
* IMPORTANT: This class is <em>not</em> intended to be subclassed. | |
* </p> | |
*/ | |
public class TableColumn extends Item { | |
Table parent; | |
boolean resizable; | |
/** | |
* 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 | |
* for all SWT widget classes should include a comment which | |
* describes the style constants which are applicable to the class. | |
* </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 | |
* @see Widget#checkSubclass | |
* @see Widget#getStyle | |
*/ | |
public TableColumn (Table parent, int style) { | |
super (parent, checkStyle (style)); | |
resizable = true; | |
this.parent = parent; | |
parent.createItem (this, 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 | |
* for all SWT widget classes should include a comment which | |
* describes the style constants which are applicable to the class. | |
* </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 | |
* @see Widget#checkSubclass | |
* @see Widget#getStyle | |
*/ | |
public TableColumn (Table parent, int style, int index) { | |
super (parent, checkStyle (style)); | |
resizable = true; | |
this.parent = parent; | |
parent.createItem (this, index); | |
} | |
/** | |
* 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); | |
} | |
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); | |
} | |
/** | |
* 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; | |
} | |
public Display getDisplay () { | |
Table parent = this.parent; | |
if (parent == null) error (SWT.ERROR_WIDGET_DISPOSED); | |
return parent.getDisplay (); | |
} | |
String getNameText () { | |
return getText (); | |
} | |
/** | |
* 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 resizable; | |
} | |
/** | |
* 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 (); | |
int index = parent.indexOf (this); | |
if (index == -1) return 0; | |
int hwnd = parent.handle; | |
return OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0); | |
} | |
/** | |
* 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 (); | |
int index = parent.indexOf (this); | |
if (index == -1) return; | |
int hwnd = parent.handle; | |
TCHAR buffer = new TCHAR (parent.getCodePage (), text, true); | |
int headerWidth = OS.SendMessage (hwnd, OS.LVM_GETSTRINGWIDTH, 0, buffer) + 10; | |
if (image != null) { | |
int margin = 0; | |
if ((COMCTL32_MAJOR << 16 | COMCTL32_MINOR) >= (5 << 16 | 80)) { | |
int hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0); | |
margin = OS.SendMessage (hwndHeader, OS.HDM_GETBITMAPMARGIN, 0, 0); | |
} else { | |
margin = OS.GetSystemMetrics (OS.SM_CXEDGE) * 3; | |
} | |
Rectangle rect = image.getBounds (); | |
headerWidth += rect.width + margin * 2; | |
} | |
OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, OS.LVSCW_AUTOSIZE); | |
int columnWidth = OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0); | |
if (headerWidth > columnWidth) { | |
if (image == null) { | |
OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, OS.LVSCW_AUTOSIZE_USEHEADER); | |
} else { | |
OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, headerWidth); | |
} | |
} | |
} | |
void releaseChild () { | |
super.releaseChild (); | |
parent.destroyItem (this); | |
} | |
void releaseWidget () { | |
super.releaseWidget (); | |
parent = null; | |
} | |
/** | |
* 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); | |
if (eventTable == null) return; | |
eventTable.unhook (SWT.Selection, listener); | |
eventTable.unhook (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 (); | |
if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return; | |
int index = parent.indexOf (this); | |
if (index == -1 || index == 0) return; | |
style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER); | |
style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER); | |
int fmt = 0; | |
if ((style & SWT.LEFT) == SWT.LEFT) fmt = OS.LVCFMT_LEFT; | |
if ((style & SWT.CENTER) == SWT.CENTER) fmt = OS.LVCFMT_CENTER; | |
if ((style & SWT.RIGHT) == SWT.RIGHT) fmt = OS.LVCFMT_RIGHT; | |
int hwnd = parent.handle; | |
LVCOLUMN lvColumn = new LVCOLUMN (); | |
lvColumn.mask = OS.LVCF_FMT; | |
lvColumn.fmt = fmt; | |
OS.SendMessage (hwnd, OS.LVM_SETCOLUMN, index, lvColumn); | |
} | |
public void setImage (Image image) { | |
checkWidget(); | |
if (image != null && image.isDisposed ()) { | |
error (SWT.ERROR_INVALID_ARGUMENT); | |
} | |
int index = parent.indexOf (this); | |
if (index == -1) return; | |
super.setImage (image); | |
int hwnd = parent.handle; | |
LVCOLUMN lvColumn = new LVCOLUMN (); | |
lvColumn.mask = OS.LVCF_FMT | OS.LVCF_IMAGE; | |
lvColumn.fmt = OS.LVCFMT_IMAGE; | |
lvColumn.iImage = parent.imageIndex (image); | |
OS.SendMessage (hwnd, OS.LVM_SETCOLUMN, index, lvColumn); | |
if (image == null) { | |
lvColumn.mask = OS.LVCF_FMT; | |
if ((style & SWT.LEFT) == SWT.LEFT) lvColumn.fmt = OS.LVCFMT_LEFT; | |
if ((style & SWT.CENTER) == SWT.CENTER) lvColumn.fmt = OS.LVCFMT_CENTER; | |
if ((style & SWT.RIGHT) == SWT.RIGHT) lvColumn.fmt = OS.LVCFMT_RIGHT; | |
OS.SendMessage (hwnd, OS.LVM_SETCOLUMN, index, lvColumn); | |
} | |
} | |
/** | |
* 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 resizable) { | |
checkWidget (); | |
this.resizable = resizable; | |
} | |
public void setText (String string) { | |
checkWidget (); | |
if (string == null) error (SWT.ERROR_NULL_ARGUMENT); | |
int index = parent.indexOf (this); | |
if (index == -1) return; | |
super.setText (string); | |
/* | |
* Bug in Windows. For some reason, when the title | |
* of a column is changed after the column has been | |
* created, the alignment must also be reset or the | |
* text does not draw. The fix is to query and then | |
* set the alignment. | |
*/ | |
int hwnd = parent.handle; | |
LVCOLUMN lvColumn = new LVCOLUMN (); | |
lvColumn.mask = OS.LVCF_FMT; | |
OS.SendMessage (hwnd, OS.LVM_GETCOLUMN, index, lvColumn); | |
/* Set the column title */ | |
int hHeap = OS.GetProcessHeap (); | |
TCHAR buffer = new TCHAR (parent.getCodePage (), string, true); | |
int byteCount = buffer.length () * TCHAR.sizeof; | |
int pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount); | |
OS.MoveMemory (pszText, buffer, byteCount); | |
lvColumn.mask |= OS.LVCF_TEXT; | |
lvColumn.pszText = pszText; | |
int result = OS.SendMessage (hwnd, OS.LVM_SETCOLUMN, index, lvColumn); | |
if (pszText != 0) OS.HeapFree (hHeap, 0, pszText); | |
if (result == 0) error (SWT.ERROR_CANNOT_SET_TEXT); | |
} | |
/** | |
* 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 (); | |
int index = parent.indexOf (this); | |
if (index == -1) return; | |
int hwnd = parent.handle; | |
OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, width); | |
} | |
} |