1 /*******************************************************************************
2 * Copyright (c) 2000, 2017 IBM Corporation and others.
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
12 * IBM Corporation - initial API and implementation
13 *******************************************************************************/
14 package org.eclipse.swt.widgets;
17 import org.eclipse.swt.*;
18 import org.eclipse.swt.events.*;
19 import org.eclipse.swt.graphics.*;
20 import org.eclipse.swt.internal.*;
21 import org.eclipse.swt.internal.win32.*;
24 * Instances of this class represent a column in a table widget.
26 * <dt><b>Styles:</b></dt>
27 * <dd>LEFT, RIGHT, CENTER</dd>
28 * <dt><b>Events:</b></dt>
29 * <dd> Move, Resize, Selection</dd>
32 * Note: Only one of the styles LEFT, RIGHT and CENTER may be specified.
34 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
37 * @see <a href="http://www.eclipse.org/swt/snippets/#table">Table, TableItem, TableColumn snippets</a>
38 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
39 * @noextend This class is not intended to be subclassed by clients.
41 public class TableColumn extends Item {
43 boolean resizable, moveable;
48 * Constructs a new instance of this class given its parent
49 * (which must be a <code>Table</code>) and a style value
50 * describing its behavior and appearance. The item is added
51 * to the end of the items maintained by its parent.
53 * The style value is either one of the style constants defined in
54 * class <code>SWT</code> which is applicable to instances of this
55 * class, or must be built by <em>bitwise OR</em>'ing together
56 * (that is, using the <code>int</code> "|" operator) two or more
57 * of those <code>SWT</code> style constants. The class description
58 * lists the style constants that are applicable to the class.
59 * Style bits are also inherited from superclasses.
62 * @param parent a composite control which will be the parent of the new instance (cannot be null)
63 * @param style the style of control to construct
65 * @exception IllegalArgumentException <ul>
66 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
68 * @exception SWTException <ul>
69 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
70 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
76 * @see Widget#checkSubclass
77 * @see Widget#getStyle
79 public TableColumn (Table parent, int style) {
80 super (parent, checkStyle (style));
83 parent.createItem (this, parent.getColumnCount ());
87 * Constructs a new instance of this class given its parent
88 * (which must be a <code>Table</code>), a style value
89 * describing its behavior and appearance, and the index
90 * at which to place it in the items maintained by its parent.
92 * The style value is either one of the style constants defined in
93 * class <code>SWT</code> which is applicable to instances of this
94 * class, or must be built by <em>bitwise OR</em>'ing together
95 * (that is, using the <code>int</code> "|" operator) two or more
96 * of those <code>SWT</code> style constants. The class description
97 * lists the style constants that are applicable to the class.
98 * Style bits are also inherited from superclasses.
101 * Note that due to a restriction on some platforms, the first column
102 * is always left aligned.
104 * @param parent a composite control which will be the parent of the new instance (cannot be null)
105 * @param style the style of control to construct
106 * @param index the zero-relative index to store the receiver in its parent
108 * @exception IllegalArgumentException <ul>
109 * <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
110 * <li>ERROR_INVALID_RANGE - if the index is not between 0 and the number of elements in the parent (inclusive)</li>
112 * @exception SWTException <ul>
113 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
114 * <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
120 * @see Widget#checkSubclass
121 * @see Widget#getStyle
123 public TableColumn (Table parent, int style, int index) {
124 super (parent, checkStyle (style));
126 this.parent = parent;
127 parent.createItem (this, index);
131 * Adds the listener to the collection of listeners who will
132 * be notified when the control is moved or resized, by sending
133 * it one of the messages defined in the <code>ControlListener</code>
136 * @param listener the listener which should be notified
138 * @exception IllegalArgumentException <ul>
139 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
141 * @exception SWTException <ul>
142 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
143 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
146 * @see ControlListener
147 * @see #removeControlListener
149 public void addControlListener(ControlListener listener) {
151 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
152 TypedListener typedListener = new TypedListener (listener);
153 addListener (SWT.Resize,typedListener);
154 addListener (SWT.Move,typedListener);
158 * Adds the listener to the collection of listeners who will
159 * be notified when the control is selected by the user, by sending
160 * it one of the messages defined in the <code>SelectionListener</code>
163 * <code>widgetSelected</code> is called when the column header is selected.
164 * <code>widgetDefaultSelected</code> is not called.
167 * @param listener the listener which should be notified when the control is selected by the user
169 * @exception IllegalArgumentException <ul>
170 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
172 * @exception SWTException <ul>
173 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
174 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
177 * @see SelectionListener
178 * @see #removeSelectionListener
179 * @see SelectionEvent
181 public void addSelectionListener (SelectionListener listener) {
183 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
184 TypedListener typedListener = new TypedListener (listener);
185 addListener (SWT.Selection,typedListener);
186 addListener (SWT.DefaultSelection,typedListener);
189 static int checkStyle (int style) {
190 return checkBits (style, SWT.LEFT, SWT.CENTER, SWT.RIGHT, 0, 0, 0);
194 protected void checkSubclass () {
195 if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
199 void destroyWidget () {
200 parent.destroyItem (this);
205 * Returns a value which describes the position of the
206 * text or image in the receiver. The value will be one of
207 * <code>LEFT</code>, <code>RIGHT</code> or <code>CENTER</code>.
209 * @return the alignment
211 * @exception SWTException <ul>
212 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
213 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
216 public int getAlignment () {
218 if ((style & SWT.LEFT) != 0) return SWT.LEFT;
219 if ((style & SWT.CENTER) != 0) return SWT.CENTER;
220 if ((style & SWT.RIGHT) != 0) return SWT.RIGHT;
225 String getNameText () {
230 * Returns the receiver's parent, which must be a <code>Table</code>.
232 * @return the receiver's parent
234 * @exception SWTException <ul>
235 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
236 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
239 public Table getParent () {
245 * Gets the moveable attribute. A column that is
246 * not moveable cannot be reordered by the user
247 * by dragging the header but may be reordered
250 * @return the moveable attribute
252 * @exception SWTException <ul>
253 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
254 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
257 * @see Table#getColumnOrder()
258 * @see Table#setColumnOrder(int[])
259 * @see TableColumn#setMoveable(boolean)
264 public boolean getMoveable () {
270 * Gets the resizable attribute. A column that is
271 * not resizable cannot be dragged by the user but
272 * may be resized by the programmer.
274 * @return the resizable attribute
276 * @exception SWTException <ul>
277 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
278 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
281 public boolean getResizable () {
287 * Returns the receiver's tool tip text, or null if it has
290 * @return the receiver's tool tip text
292 * @exception SWTException <ul>
293 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
294 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
299 public String getToolTipText () {
305 * Gets the width of the receiver.
309 * @exception SWTException <ul>
310 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
311 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
314 public int getWidth () {
316 return DPIUtil.autoScaleDown(getWidthInPixels());
319 int getWidthInPixels () {
320 int index = parent.indexOf (this);
321 if (index == -1) return 0;
322 long hwnd = parent.handle;
323 return (int)OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
327 * Causes the receiver to be resized to its preferred size.
328 * For a composite, this involves computing the preferred size
329 * from its layout, if there is one.
331 * @exception SWTException <ul>
332 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
333 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
337 public void pack () {
339 int index = parent.indexOf (this);
340 if (index == -1) return;
341 long hwnd = parent.handle;
342 int oldWidth = (int)OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
343 TCHAR buffer = new TCHAR (parent.getCodePage (), text, true);
344 int headerWidth = (int)OS.SendMessage (hwnd, OS.LVM_GETSTRINGWIDTH, 0, buffer) + Table.HEADER_MARGIN;
345 if (OS.IsAppThemed ()) headerWidth += Table.HEADER_EXTRA;
346 boolean hasHeaderImage = false;
347 if (image != null || parent.sortColumn == this) {
348 hasHeaderImage = true;
349 if (parent.sortColumn == this && parent.sortDirection != SWT.NONE) {
350 headerWidth += Table.SORT_WIDTH;
351 } else if (image != null) {
352 Rectangle bounds = image.getBoundsInPixels ();
353 headerWidth += bounds.width;
355 long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
356 int margin = (int)OS.SendMessage (hwndHeader, OS.HDM_GETBITMAPMARGIN, 0, 0);
357 headerWidth += margin * 4;
359 parent.ignoreColumnResize = true;
361 if (parent.hooks (SWT.MeasureItem)) {
362 RECT headerRect = new RECT ();
363 long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
364 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect);
365 OS.MapWindowPoints (hwndHeader, hwnd, headerRect, 2);
366 long hDC = OS.GetDC (hwnd);
367 long oldFont = 0, newFont = OS.SendMessage (hwnd, OS.WM_GETFONT, 0, 0);
368 if (newFont != 0) oldFont = OS.SelectObject (hDC, newFont);
369 int count = (int)OS.SendMessage (hwnd, OS.LVM_GETITEMCOUNT, 0, 0);
370 for (int i=0; i<count; i++) {
371 TableItem item = parent._getItem (i, false);
373 long hFont = item.fontHandle (index);
374 if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
375 Event event = parent.sendMeasureItemEvent (item, i, index, hDC);
376 if (hFont != -1) hFont = OS.SelectObject (hDC, hFont);
377 if (isDisposed () || parent.isDisposed ()) break;
378 Rectangle bounds = event.getBoundsInPixels();
379 columnWidth = Math.max (columnWidth, bounds.x + bounds.width - headerRect.left);
382 if (newFont != 0) OS.SelectObject (hDC, oldFont);
383 OS.ReleaseDC (hwnd, hDC);
384 OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, columnWidth);
386 OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, OS.LVSCW_AUTOSIZE);
387 columnWidth = (int)OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
390 * Bug in Windows. When LVM_SETCOLUMNWIDTH is used with LVSCW_AUTOSIZE
391 * where each item has I_IMAGECALLBACK but there are no images in the
392 * table, the size computed by LVM_SETCOLUMNWIDTH is too small for the
393 * first column, causing long items to be clipped with '...'. The fix
394 * is to increase the column width by a small amount.
396 if (parent.imageList == null) columnWidth += 2;
398 * Bug in Windows. When LVM_SETCOLUMNWIDTH is used with LVSCW_AUTOSIZE
399 * for a table with a state image list, the column is width does not
400 * include space for the state icon. The fix is to increase the column
401 * width by the width of the image list.
403 if ((parent.style & SWT.CHECK) != 0) {
404 long hStateList = OS.SendMessage (hwnd, OS.LVM_GETIMAGELIST, OS.LVSIL_STATE, 0);
405 if (hStateList != 0) {
406 int [] cx = new int [1], cy = new int [1];
407 OS.ImageList_GetIconSize (hStateList, cx, cy);
408 columnWidth += cx [0];
413 if (headerWidth > columnWidth) {
414 if (!hasHeaderImage) {
416 * Feature in Windows. When LVSCW_AUTOSIZE_USEHEADER is used
417 * with LVM_SETCOLUMNWIDTH to resize the last column, the last
418 * column is expanded to fill the client area. The fix is to
419 * resize the table to be small, set the column width and then
420 * restore the table to its original size.
423 boolean fixWidth = index == parent.getColumnCount () - 1;
426 OS.GetWindowRect (hwnd, rect);
427 OS.UpdateWindow (hwnd);
428 int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOREDRAW | OS.SWP_NOZORDER;
429 OS.SetWindowPos (hwnd, 0, 0, 0, 0, rect.bottom - rect.top, flags);
431 OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, OS.LVSCW_AUTOSIZE_USEHEADER);
433 int flags = OS.SWP_NOACTIVATE | OS.SWP_NOMOVE | OS.SWP_NOZORDER;
434 OS.SetWindowPos (hwnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, flags);
437 OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, headerWidth);
441 OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, columnWidth);
444 parent.ignoreColumnResize = false;
445 int newWidth = (int)OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0);
446 if (oldWidth != newWidth) {
447 updateToolTip (index);
448 sendEvent (SWT.Resize);
449 if (isDisposed ()) return;
450 boolean moved = false;
451 int [] order = parent.getColumnOrder ();
452 TableColumn [] columns = parent.getColumns ();
453 for (int i=0; i<order.length; i++) {
454 TableColumn column = columns [order [i]];
455 if (moved && !column.isDisposed ()) {
456 column.updateToolTip (order [i]);
457 column.sendEvent (SWT.Move);
459 if (column == this) moved = true;
465 void releaseHandle () {
466 super.releaseHandle ();
471 void releaseParent () {
472 super.releaseParent ();
473 if (parent.sortColumn == this) {
474 parent.sortColumn = null;
479 * Removes the listener from the collection of listeners who will
480 * be notified when the control is moved or resized.
482 * @param listener the listener which should no longer be notified
484 * @exception IllegalArgumentException <ul>
485 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
487 * @exception SWTException <ul>
488 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
489 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
492 * @see ControlListener
493 * @see #addControlListener
495 public void removeControlListener (ControlListener listener) {
497 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
498 if (eventTable == null) return;
499 eventTable.unhook (SWT.Move, listener);
500 eventTable.unhook (SWT.Resize, listener);
504 * Removes the listener from the collection of listeners who will
505 * be notified when the control is selected by the user.
507 * @param listener the listener which should no longer be notified
509 * @exception IllegalArgumentException <ul>
510 * <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
512 * @exception SWTException <ul>
513 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
514 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
517 * @see SelectionListener
518 * @see #addSelectionListener
520 public void removeSelectionListener(SelectionListener listener) {
522 if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
523 if (eventTable == null) return;
524 eventTable.unhook (SWT.Selection, listener);
525 eventTable.unhook (SWT.DefaultSelection,listener);
529 * Controls how text and images will be displayed in the receiver.
530 * The argument should be one of <code>LEFT</code>, <code>RIGHT</code>
531 * or <code>CENTER</code>.
533 * Note that due to a restriction on some platforms, the first column
534 * is always left aligned.
536 * @param alignment the new alignment
538 * @exception SWTException <ul>
539 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
540 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
543 public void setAlignment (int alignment) {
545 if ((alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER)) == 0) return;
546 int index = parent.indexOf (this);
547 if (index == -1 || index == 0) return;
548 style &= ~(SWT.LEFT | SWT.RIGHT | SWT.CENTER);
549 style |= alignment & (SWT.LEFT | SWT.RIGHT | SWT.CENTER);
550 long hwnd = parent.handle;
551 LVCOLUMN lvColumn = new LVCOLUMN ();
552 lvColumn.mask = OS.LVCF_FMT;
553 OS.SendMessage (hwnd, OS.LVM_GETCOLUMN, index, lvColumn);
554 lvColumn.fmt &= ~OS.LVCFMT_JUSTIFYMASK;
556 if ((style & SWT.LEFT) == SWT.LEFT) fmt = OS.LVCFMT_LEFT;
557 if ((style & SWT.CENTER) == SWT.CENTER) fmt = OS.LVCFMT_CENTER;
558 if ((style & SWT.RIGHT) == SWT.RIGHT) fmt = OS.LVCFMT_RIGHT;
560 OS.SendMessage (hwnd, OS.LVM_SETCOLUMN, index, lvColumn);
562 * Bug in Windows. When LVM_SETCOLUMN is used to change
563 * the alignment of a column, the column is not redrawn
564 * to show the new alignment. The fix is to compute the
565 * visible rectangle for the column and redraw it.
568 parent.forceResize ();
569 RECT rect = new RECT (), headerRect = new RECT ();
570 OS.GetClientRect (hwnd, rect);
571 long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
572 OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect);
573 OS.MapWindowPoints (hwndHeader, hwnd, headerRect, 2);
574 rect.left = headerRect.left;
575 rect.right = headerRect.right;
576 OS.InvalidateRect (hwnd, rect, true);
581 public void setImage (Image image) {
583 if (image != null && image.isDisposed ()) {
584 error (SWT.ERROR_INVALID_ARGUMENT);
586 super.setImage (image);
587 if (parent.sortColumn != this || parent.sortDirection != SWT.NONE) {
588 setImage (image, false, false);
592 void setImage (Image image, boolean sort, boolean right) {
593 int index = parent.indexOf (this);
594 if (index == -1) return;
595 long hwnd = parent.handle;
596 LVCOLUMN lvColumn = new LVCOLUMN ();
597 lvColumn.mask = OS.LVCF_FMT | OS.LVCF_IMAGE;
598 OS.SendMessage (hwnd, OS.LVM_GETCOLUMN, index, lvColumn);
600 lvColumn.fmt |= OS.LVCFMT_IMAGE;
601 lvColumn.iImage = parent.imageIndexHeader (image);
602 if (right) lvColumn.fmt |= OS.LVCFMT_BITMAP_ON_RIGHT;
604 lvColumn.mask &= ~OS.LVCF_IMAGE;
605 lvColumn.fmt &= ~(OS.LVCFMT_IMAGE | OS.LVCFMT_BITMAP_ON_RIGHT);
607 OS.SendMessage (hwnd, OS.LVM_SETCOLUMN, index, lvColumn);
611 * Sets the moveable attribute. A column that is
612 * moveable can be reordered by the user by dragging
613 * the header. A column that is not moveable cannot be
614 * dragged by the user but may be reordered
617 * @param moveable the moveable attribute
619 * @exception SWTException <ul>
620 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
621 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
624 * @see Table#setColumnOrder(int[])
625 * @see Table#getColumnOrder()
626 * @see TableColumn#getMoveable()
631 public void setMoveable (boolean moveable) {
633 this.moveable = moveable;
634 parent.updateMoveable ();
638 * Sets the resizable attribute. A column that is
639 * resizable can be resized by the user dragging the
640 * edge of the header. A column that is not resizable
641 * cannot be dragged by the user but may be resized
644 * @param resizable the resize attribute
646 * @exception SWTException <ul>
647 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
648 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
651 public void setResizable (boolean resizable) {
653 this.resizable = resizable;
656 void setSortDirection (int direction) {
657 int index = parent.indexOf (this);
658 if (index == -1) return;
659 long hwnd = parent.handle;
660 long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
661 HDITEM hdItem = new HDITEM ();
662 hdItem.mask = OS.HDI_FORMAT | OS.HDI_IMAGE;
663 OS.SendMessage (hwndHeader, OS.HDM_GETITEM, index, hdItem);
666 hdItem.fmt &= ~(OS.HDF_IMAGE | OS.HDF_SORTDOWN);
667 hdItem.fmt |= OS.HDF_SORTUP;
668 if (image == null) hdItem.mask &= ~OS.HDI_IMAGE;
671 hdItem.fmt &= ~(OS.HDF_IMAGE | OS.HDF_SORTUP);
672 hdItem.fmt |= OS.HDF_SORTDOWN;
673 if (image == null) hdItem.mask &= ~OS.HDI_IMAGE;
676 hdItem.fmt &= ~(OS.HDF_SORTUP | OS.HDF_SORTDOWN);
678 hdItem.fmt |= OS.HDF_IMAGE;
679 hdItem.iImage = parent.imageIndexHeader (image);
681 hdItem.fmt &= ~OS.HDF_IMAGE;
682 hdItem.mask &= ~OS.HDI_IMAGE;
686 OS.SendMessage (hwndHeader, OS.HDM_SETITEM, index, hdItem);
688 * Bug in Windows. When LVM_SETSELECTEDCOLUMN is used to
689 * specify a selected column, Windows does not redraw either
690 * the new or the previous selected column. The fix is to
691 * force a redraw of both.
693 * Feature in Windows. When LVM_SETBKCOLOR is used with
694 * CLR_NONE and LVM_SETSELECTEDCOLUMN is used to select
695 * a column, Windows fills the column with the selection
696 * color, drawing on top of the background image and any
697 * other custom drawing. The fix is to avoid setting the
700 parent.forceResize ();
701 RECT rect = new RECT ();
702 OS.GetClientRect (hwnd, rect);
703 if ((int)OS.SendMessage (hwnd, OS.LVM_GETBKCOLOR, 0, 0) != OS.CLR_NONE) {
704 int oldColumn = (int)OS.SendMessage (hwnd, OS.LVM_GETSELECTEDCOLUMN, 0, 0);
705 int newColumn = direction == SWT.NONE ? -1 : index;
706 OS.SendMessage (hwnd, OS.LVM_SETSELECTEDCOLUMN, newColumn, 0);
707 RECT headerRect = new RECT ();
708 if (oldColumn != -1) {
709 if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, oldColumn, headerRect) != 0) {
710 OS.MapWindowPoints (hwndHeader, hwnd, headerRect, 2);
711 rect.left = headerRect.left;
712 rect.right = headerRect.right;
713 OS.InvalidateRect (hwnd, rect, true);
717 RECT headerRect = new RECT ();
718 if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, headerRect) != 0) {
719 OS.MapWindowPoints (hwndHeader, hwnd, headerRect, 2);
720 rect.left = headerRect.left;
721 rect.right = headerRect.right;
722 OS.InvalidateRect (hwnd, rect, true);
727 public void setText (String string) {
729 if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
730 if (string.equals (text)) return;
731 int index = parent.indexOf (this);
732 if (index == -1) return;
733 super.setText (string);
736 * Bug in Windows. For some reason, when the title
737 * of a column is changed after the column has been
738 * created, the alignment must also be reset or the
739 * text does not draw. The fix is to query and then
742 long hwnd = parent.handle;
743 LVCOLUMN lvColumn = new LVCOLUMN ();
744 lvColumn.mask = OS.LVCF_FMT;
745 OS.SendMessage (hwnd, OS.LVM_GETCOLUMN, index, lvColumn);
748 * Bug in Windows. When a column header contains a
749 * mnemonic character, Windows does not measure the
750 * text properly. This causes '...' to always appear
751 * at the end of the text. The fix is to remove
752 * mnemonic characters.
754 long hHeap = OS.GetProcessHeap ();
755 char [] buffer = fixMnemonic (string);
756 int byteCount = buffer.length * TCHAR.sizeof;
757 long pszText = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, byteCount);
758 OS.MoveMemory (pszText, buffer, byteCount);
759 lvColumn.mask |= OS.LVCF_TEXT;
760 lvColumn.pszText = pszText;
761 long result = OS.SendMessage (hwnd, OS.LVM_SETCOLUMN, index, lvColumn);
762 if (pszText != 0) OS.HeapFree (hHeap, 0, pszText);
763 if (result == 0) error (SWT.ERROR_CANNOT_SET_TEXT);
767 * Sets the receiver's tool tip text to the argument, which
768 * may be null indicating that the default tool tip for the
769 * control will be shown. For a control that has a default
770 * tool tip, such as the Tree control on Windows, setting
771 * the tool tip text to an empty string replaces the default,
772 * causing no tool tip text to be shown.
774 * The mnemonic indicator (character '&') is not displayed in a tool tip.
775 * To display a single '&' in the tool tip, the character '&' can be
776 * escaped by doubling it in the string.
779 * NOTE: This operation is a hint and behavior is platform specific, on Windows
780 * for CJK-style mnemonics of the form " (&C)" at the end of the tooltip text
781 * are not shown in tooltip.
784 * @param string the new tool tip text (or null)
786 * @exception SWTException <ul>
787 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
788 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
793 public void setToolTipText (String string) {
795 toolTipText = string;
796 long hwndHeaderToolTip = parent.headerToolTipHandle;
797 if (hwndHeaderToolTip == 0) {
798 parent.createHeaderToolTips ();
799 parent.updateHeaderToolTips ();
804 * Sets the width of the receiver.
806 * @param width the new width
808 * @exception SWTException <ul>
809 * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
810 * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
813 public void setWidth (int width) {
815 setWidthInPixels(DPIUtil.autoScaleUp(width));
818 void setWidthInPixels (int width) {
819 if (width < 0) return;
820 int index = parent.indexOf (this);
821 if (index == -1) return;
822 long hwnd = parent.handle;
823 if (width != (int)OS.SendMessage (hwnd, OS.LVM_GETCOLUMNWIDTH, index, 0)) {
824 OS.SendMessage (hwnd, OS.LVM_SETCOLUMNWIDTH, index, width);
828 void updateToolTip (int index) {
829 long hwndHeaderToolTip = parent.headerToolTipHandle;
830 if (hwndHeaderToolTip != 0) {
831 long hwnd = parent.handle;
832 long hwndHeader = OS.SendMessage (hwnd, OS.LVM_GETHEADER, 0, 0);
833 RECT rect = new RECT ();
834 if (OS.SendMessage (hwndHeader, OS.HDM_GETITEMRECT, index, rect) != 0) {
835 TOOLINFO lpti = new TOOLINFO ();
836 lpti.cbSize = TOOLINFO.sizeof;
837 lpti.hwnd = hwndHeader;
839 lpti.left = rect.left;
841 lpti.right = rect.right;
842 lpti.bottom = rect.bottom;
843 OS.SendMessage (hwndHeaderToolTip, OS.TTM_NEWTOOLRECT, 0, lpti);