void releaseImages() { TBBUTTONINFO info = new TBBUTTONINFO(); info.cbSize = TBBUTTONINFO.sizeof; info.dwMask = OS.TBIF_IMAGE | OS.TBIF_STYLE; long /*int*/ hwnd = parent.handle; OS.SendMessage(hwnd, OS.TB_GETBUTTONINFO, id, info); /* * Feature in Windows. For some reason, a tool item that has * the style BTNS_SEP does not return I_IMAGENONE when queried * for an image index, despite the fact that no attempt has been * made to assign an image to the item. As a result, operations * on an image list that use the wrong index cause random results. * The fix is to ensure that the tool item is not a separator * before using the image index. Since separators cannot have * an image and one is never assigned, this is not a problem. */ if ((info.fsStyle & OS.BTNS_SEP) == 0 && info.iImage != OS.I_IMAGENONE) { ImageList imageList = parent.getImageList(); ImageList hotImageList = parent.getHotImageList(); ImageList disabledImageList = parent.getDisabledImageList(); if (imageList != null) imageList.put(info.iImage, null); if (hotImageList != null) hotImageList.put(info.iImage, null); if (disabledImageList != null) disabledImageList.put(info.iImage, null); } }
/** * Sets the image the receiver will display to the argument. * * <p>Note: This operation is a hint and is not supported on platforms that do not have this * concept (for example, Windows NT). Furthermore, some platforms (such as GTK), cannot display * both a check box and an image at the same time. Instead, they hide the image and display the * check box. * * @param image the image to display * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * </ul> */ public void setImage(Image image) { checkWidget(); if ((style & SWT.SEPARATOR) != 0) return; super.setImage(image); if (OS.IsWinCE) { if ((OS.IsPPC || OS.IsSP) && parent.hwndCB != 0) { long /*int*/ hwndCB = parent.hwndCB; TBBUTTONINFO info = new TBBUTTONINFO(); info.cbSize = TBBUTTONINFO.sizeof; info.dwMask = OS.TBIF_IMAGE; info.iImage = parent.imageIndex(image); OS.SendMessage(hwndCB, OS.TB_SETBUTTONINFO, id, info); } return; } if (OS.WIN32_VERSION < OS.VERSION(4, 10)) return; MENUITEMINFO info = new MENUITEMINFO(); info.cbSize = MENUITEMINFO.sizeof; info.fMask = OS.MIIM_BITMAP; if (parent.foreground != -1) { info.hbmpItem = OS.HBMMENU_CALLBACK; } else { if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(6, 0) && OS.IsAppThemed()) { if (hBitmap != 0) OS.DeleteObject(hBitmap); info.hbmpItem = hBitmap = image != null ? Display.create32bitDIB(image) : 0; } else { info.hbmpItem = image != null ? OS.HBMMENU_CALLBACK : 0; } } long /*int*/ hMenu = parent.handle; OS.SetMenuItemInfo(hMenu, id, false, info); parent.redraw(); }
/** * Returns <code>true</code> if the receiver is enabled, and <code>false</code> otherwise. A * disabled menu item is typically not selectable from the user interface and draws with an * inactive or "grayed" look. * * @return the receiver's enabled state * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * </ul> * * @see #isEnabled */ public boolean getEnabled() { checkWidget(); if ((OS.IsPPC || OS.IsSP) && parent.hwndCB != 0) { long /*int*/ hwndCB = parent.hwndCB; TBBUTTONINFO info = new TBBUTTONINFO(); info.cbSize = TBBUTTONINFO.sizeof; info.dwMask = OS.TBIF_STATE; OS.SendMessage(hwndCB, OS.TB_GETBUTTONINFO, id, info); return (info.fsState & OS.TBSTATE_ENABLED) != 0; } /* * Feature in Windows. For some reason, when the menu item * is a separator, GetMenuItemInfo() always indicates that * the item is not enabled. The fix is to track the enabled * state for separators. */ if ((style & SWT.SEPARATOR) != 0) { return (state & DISABLED) == 0; } long /*int*/ hMenu = parent.handle; MENUITEMINFO info = new MENUITEMINFO(); info.cbSize = MENUITEMINFO.sizeof; info.fMask = OS.MIIM_STATE; boolean success; if (OS.IsWinCE) { int index = parent.indexOf(this); if (index == -1) error(SWT.ERROR_CANNOT_GET_ENABLED); success = OS.GetMenuItemInfo(hMenu, index, true, info); } else { success = OS.GetMenuItemInfo(hMenu, id, false, info); } if (!success) error(SWT.ERROR_CANNOT_GET_ENABLED); return (info.fState & (OS.MFS_DISABLED | OS.MFS_GRAYED)) == 0; }
/** * Sets the width of the receiver, for <code>SEPARATOR</code> ToolItems. * * @param width the new width. If the new value is <code>SWT.DEFAULT</code>, the width is a * fixed-width area whose amount is determined by the platform. If the new value is 0 a * vertical or horizontal line will be drawn, depending on the setting of the corresponding * style bit (<code>SWT.VERTICAL</code> or <code>SWT.HORIZONTAL</code>). If the new value is * <code>SWT.SEPARATOR_FILL</code> a variable-width space is inserted that acts as a spring * between the two adjoining items which will push them out to the extent of the containing * ToolBar. * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * </ul> */ public void setWidth(int width) { checkWidget(); if ((style & SWT.SEPARATOR) == 0) return; if (width < 0) return; long /*int*/ hwnd = parent.handle; TBBUTTONINFO info = new TBBUTTONINFO(); info.cbSize = TBBUTTONINFO.sizeof; info.dwMask = OS.TBIF_SIZE; info.cx = cx = (short) width; OS.SendMessage(hwnd, OS.TB_SETBUTTONINFO, id, info); parent.layoutItems(); }
/** * Sets the receiver's text. The string may include the mnemonic character. * * <p>Mnemonics are indicated by an '&' that causes the next character to be the mnemonic. * When the user presses a key sequence that matches the mnemonic, a selection event occurs. On * most platforms, the mnemonic appears underlined but may be emphasised in a platform specific * manner. The mnemonic indicator character '&' can be escaped by doubling it in the string, * causing a single '&' to be displayed. * * @param string the new text * @exception IllegalArgumentException * <ul> * <li>ERROR_NULL_ARGUMENT - if the text is null * </ul> * * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * </ul> */ public void setText(String string) { checkWidget(); if (string == null) error(SWT.ERROR_NULL_ARGUMENT); if ((style & SWT.SEPARATOR) != 0) return; if (string.equals(text)) return; super.setText(string); long /*int*/ hwnd = parent.handle; TBBUTTONINFO info = new TBBUTTONINFO(); info.cbSize = TBBUTTONINFO.sizeof; info.dwMask = OS.TBIF_TEXT | OS.TBIF_STYLE; info.fsStyle = (byte) (widgetStyle() | OS.BTNS_AUTOSIZE); long /*int*/ hHeap = OS.GetProcessHeap(), pszText = 0; if (string.length() != 0) { info.fsStyle |= OS.BTNS_SHOWTEXT; TCHAR buffer = new TCHAR(parent.getCodePage(), string, true); int byteCount = buffer.length() * TCHAR.sizeof; pszText = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount); OS.MoveMemory(pszText, buffer, byteCount); info.pszText = pszText; } OS.SendMessage(hwnd, OS.TB_SETBUTTONINFO, id, info); if (pszText != 0) OS.HeapFree(hHeap, 0, pszText); /* * Bug in Windows. For some reason, when the font is set * before any tool item has text, the tool items resize to * a very small size. Also, a tool item will only show text * when text has already been set on one item and then a new * item is created. The fix is to use WM_SETFONT to force * the tool bar to redraw and layout. */ parent.setDropDownItems(false); long /*int*/ hFont = OS.SendMessage(hwnd, OS.WM_GETFONT, 0, 0); OS.SendMessage(hwnd, OS.WM_SETFONT, hFont, 0); parent.setDropDownItems(true); parent.layoutItems(); }
void updateImages(boolean enabled) { if ((style & SWT.SEPARATOR) != 0) return; long /*int*/ hwnd = parent.handle; TBBUTTONINFO info = new TBBUTTONINFO(); info.cbSize = TBBUTTONINFO.sizeof; info.dwMask = OS.TBIF_IMAGE; OS.SendMessage(hwnd, OS.TB_GETBUTTONINFO, id, info); if (info.iImage == OS.I_IMAGENONE && image == null) return; ImageList imageList = parent.getImageList(); ImageList hotImageList = parent.getHotImageList(); ImageList disabledImageList = parent.getDisabledImageList(); if (info.iImage == OS.I_IMAGENONE) { Rectangle bounds = image.getBounds(); int listStyle = parent.style & SWT.RIGHT_TO_LEFT; if (imageList == null) { imageList = display.getImageListToolBar(listStyle, bounds.width, bounds.height); } if (disabledImageList == null) { disabledImageList = display.getImageListToolBarDisabled(listStyle, bounds.width, bounds.height); } if (hotImageList == null) { hotImageList = display.getImageListToolBarHot(listStyle, bounds.width, bounds.height); } Image disabled = disabledImage; if (disabledImage == null) { if (disabledImage2 != null) disabledImage2.dispose(); disabledImage2 = null; disabled = image; if (!enabled) { disabled = disabledImage2 = new Image(display, image, SWT.IMAGE_DISABLE); } } /* * Bug in Windows. When a tool item with the style * BTNS_CHECK or BTNS_CHECKGROUP is selected and then * disabled, the item does not draw using the disabled * image. The fix is to assign the disabled image in * all image lists. */ Image image2 = image, hot = hotImage; if ((style & (SWT.CHECK | SWT.RADIO)) != 0) { if (!enabled) image2 = hot = disabled; } info.iImage = imageList.add(image2); disabledImageList.add(disabled); hotImageList.add(hot != null ? hot : image2); parent.setImageList(imageList); parent.setDisabledImageList(disabledImageList); parent.setHotImageList(hotImageList); } else { Image disabled = null; if (disabledImageList != null) { if (image != null) { if (disabledImage2 != null) disabledImage2.dispose(); disabledImage2 = null; disabled = disabledImage; if (disabledImage == null) { disabled = image; if (!enabled) { disabled = disabledImage2 = new Image(display, image, SWT.IMAGE_DISABLE); } } } disabledImageList.put(info.iImage, disabled); } /* * Bug in Windows. When a tool item with the style * BTNS_CHECK or BTNS_CHECKGROUP is selected and then * disabled, the item does not draw using the disabled * image. The fix is to use the disabled image in all * image lists. */ Image image2 = image, hot = hotImage; if ((style & (SWT.CHECK | SWT.RADIO)) != 0) { if (!enabled) image2 = hot = disabled; } if (imageList != null) imageList.put(info.iImage, image2); if (hotImageList != null) { hotImageList.put(info.iImage, hot != null ? hot : image2); } if (image == null) info.iImage = OS.I_IMAGENONE; } /* * Bug in Windows. If the width of an item has already been * calculated, the tool bar control will not recalculate it to * include the space for the image. The fix is to set the width * to zero, forcing the control recalculate the width for the item. */ info.dwMask |= OS.TBIF_SIZE; info.cx = 0; OS.SendMessage(hwnd, OS.TB_SETBUTTONINFO, id, info); long /*int*/ hFont = OS.SendMessage(hwnd, OS.WM_GETFONT, 0, 0); OS.SendMessage(hwnd, OS.WM_SETFONT, hFont, 0); parent.layoutItems(); }
/** * Sets the control that is used to fill the bounds of the item when the item is a <code>SEPARATOR * </code>. * * @param control the new control * @exception IllegalArgumentException * <ul> * <li>ERROR_INVALID_ARGUMENT - if the control has been disposed * <li>ERROR_INVALID_PARENT - if the control is not in the same widget tree * </ul> * * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * </ul> */ public void setControl(Control control) { checkWidget(); if (control != null) { if (control.isDisposed()) error(SWT.ERROR_INVALID_ARGUMENT); if (control.parent != parent) error(SWT.ERROR_INVALID_PARENT); } if ((style & SWT.SEPARATOR) == 0) return; this.control = control; /* * Feature in Windows. When a tool bar wraps, tool items * with the style BTNS_SEP are used as wrap points. This * means that controls that are placed on top of separator * items are not positioned properly. Also, vertical tool * bars are implemented using TB_SETROWS to set the number * of rows. When a control is placed on top of a separator, * the height of the separator does not grow. The fix in * both cases is to change the tool item style from BTNS_SEP * to BTNS_BUTTON, causing the item to wrap like a tool item * button. The new tool item button is disabled to avoid key * traversal and the image is set to I_IMAGENONE to avoid * getting the first image from the image list. */ if ((parent.style & (SWT.WRAP | SWT.VERTICAL)) != 0) { boolean changed = false; long /*int*/ hwnd = parent.handle; TBBUTTONINFO info = new TBBUTTONINFO(); info.cbSize = TBBUTTONINFO.sizeof; info.dwMask = OS.TBIF_STYLE | OS.TBIF_STATE; OS.SendMessage(hwnd, OS.TB_GETBUTTONINFO, id, info); if (control == null) { if ((info.fsStyle & OS.BTNS_SEP) == 0) { changed = true; info.fsStyle &= ~(OS.BTNS_BUTTON | OS.BTNS_SHOWTEXT); info.fsStyle |= OS.BTNS_SEP; if ((state & DISABLED) != 0) { info.fsState &= ~OS.TBSTATE_ENABLED; } else { info.fsState |= OS.TBSTATE_ENABLED; } } } else { if ((info.fsStyle & OS.BTNS_SEP) != 0) { changed = true; info.fsStyle &= ~OS.BTNS_SEP; info.fsStyle |= OS.BTNS_BUTTON | OS.BTNS_SHOWTEXT; info.fsState &= ~OS.TBSTATE_ENABLED; info.dwMask |= OS.TBIF_IMAGE; info.iImage = OS.I_IMAGENONE; } } if (changed) { OS.SendMessage(hwnd, OS.TB_SETBUTTONINFO, id, info); /* * Bug in Windows. When TB_SETBUTTONINFO changes the * style of a tool item from BTNS_SEP to BTNS_BUTTON * and the tool bar is wrapped, the tool bar does not * redraw properly. Windows uses separator items as * wrap points and sometimes draws etching above or * below and entire row. The fix is to redraw the * tool bar. */ if (OS.SendMessage(hwnd, OS.TB_GETROWS, 0, 0) > 1) { OS.InvalidateRect(hwnd, null, true); } } } resizeControl(); }
/** * Enables the receiver if the argument is <code>true</code>, and disables it otherwise. A * disabled menu item is typically not selectable from the user interface and draws with an * inactive or "grayed" look. * * @param enabled the new enabled state * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * </ul> */ public void setEnabled(boolean enabled) { checkWidget(); if ((OS.IsPPC || OS.IsSP) && parent.hwndCB != 0) { long /*int*/ hwndCB = parent.hwndCB; TBBUTTONINFO info = new TBBUTTONINFO(); info.cbSize = TBBUTTONINFO.sizeof; info.dwMask = OS.TBIF_STATE; OS.SendMessage(hwndCB, OS.TB_GETBUTTONINFO, id, info); info.fsState &= ~OS.TBSTATE_ENABLED; if (enabled) info.fsState |= OS.TBSTATE_ENABLED; OS.SendMessage(hwndCB, OS.TB_SETBUTTONINFO, id, info); } else { /* * Feature in Windows. For some reason, when the menu item * is a separator, GetMenuItemInfo() always indicates that * the item is not enabled. The fix is to track the enabled * state for separators. */ if ((style & SWT.SEPARATOR) != 0) { if (enabled) { state &= ~DISABLED; } else { state |= DISABLED; } } long /*int*/ hMenu = parent.handle; if (OS.IsWinCE) { int index = parent.indexOf(this); if (index == -1) return; int uEnable = OS.MF_BYPOSITION | (enabled ? OS.MF_ENABLED : OS.MF_GRAYED); OS.EnableMenuItem(hMenu, index, uEnable); } else { MENUITEMINFO info = new MENUITEMINFO(); info.cbSize = MENUITEMINFO.sizeof; info.fMask = OS.MIIM_STATE; boolean success = OS.GetMenuItemInfo(hMenu, id, false, info); if (!success) { int error = OS.GetLastError(); SWT.error( SWT.ERROR_CANNOT_SET_ENABLED, null, " [GetLastError=0x" + Integer.toHexString(error) + "]"); // $NON-NLS-1$ $NON-NLS-2$ } int bits = OS.MFS_DISABLED | OS.MFS_GRAYED; if (enabled) { if ((info.fState & bits) == 0) return; info.fState &= ~bits; } else { if ((info.fState & bits) == bits) return; info.fState |= bits; } success = OS.SetMenuItemInfo(hMenu, id, false, info); if (!success) { /* * Bug in Windows. For some reason SetMenuItemInfo(), * returns a fail code when setting the enabled or * selected state of a default item, but sets the * state anyway. The fix is to ignore the error. * * NOTE: This only happens on Vista. */ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(6, 0)) { success = id == OS.GetMenuDefaultItem(hMenu, OS.MF_BYCOMMAND, OS.GMDI_USEDISABLED); } if (!success) { int error = OS.GetLastError(); SWT.error( SWT.ERROR_CANNOT_SET_ENABLED, null, " [GetLastError=0x" + Integer.toHexString(error) + "]"); // $NON-NLS-1$ $NON-NLS-2$ } } } } parent.destroyAccelerators(); parent.redraw(); }
/** * Sets the receiver's text. The string may include the mnemonic character and accelerator text. * * <p>Mnemonics are indicated by an '&' that causes the next character to be the mnemonic. * When the user presses a key sequence that matches the mnemonic, a selection event occurs. On * most platforms, the mnemonic appears underlined but may be emphasised in a platform specific * manner. The mnemonic indicator character '&' can be escaped by doubling it in the string, * causing a single '&' to be displayed. * * <p>Accelerator text is indicated by the '\t' character. On platforms that support accelerator * text, the text that follows the '\t' character is displayed to the user, typically indicating * the key stroke that will cause the item to become selected. On most platforms, the accelerator * text appears right aligned in the menu. Setting the accelerator text does not install the * accelerator key sequence. The accelerator key sequence is installed using #setAccelerator. * * @param string the new text * @exception IllegalArgumentException * <ul> * <li>ERROR_NULL_ARGUMENT - if the text is null * </ul> * * @exception SWTException * <ul> * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * </ul> * * @see #setAccelerator */ public void setText(String string) { checkWidget(); if (string == null) error(SWT.ERROR_NULL_ARGUMENT); if ((style & SWT.SEPARATOR) != 0) return; if (text.equals(string)) return; super.setText(string); long /*int*/ hHeap = OS.GetProcessHeap(); long /*int*/ pszText = 0; boolean success = false; if ((OS.IsPPC || OS.IsSP) && parent.hwndCB != 0) { /* * Bug in WinCE PPC. Tool items on the menubar don't resize * correctly when the character '&' is used (even when it * is a sequence '&&'). The fix is to remove all '&' from * the string. */ if (string.indexOf('&') != -1) { int length = string.length(); char[] text = new char[length]; string.getChars(0, length, text, 0); int i = 0, j = 0; for (i = 0; i < length; i++) { if (text[i] != '&') text[j++] = text[i]; } if (j < i) string = new String(text, 0, j); } /* Use the character encoding for the default locale */ TCHAR buffer = new TCHAR(0, string, true); int byteCount = buffer.length() * TCHAR.sizeof; pszText = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount); OS.MoveMemory(pszText, buffer, byteCount); long /*int*/ hwndCB = parent.hwndCB; TBBUTTONINFO info2 = new TBBUTTONINFO(); info2.cbSize = TBBUTTONINFO.sizeof; info2.dwMask = OS.TBIF_TEXT; info2.pszText = pszText; success = OS.SendMessage(hwndCB, OS.TB_SETBUTTONINFO, id, info2) != 0; } else { MENUITEMINFO info = new MENUITEMINFO(); info.cbSize = MENUITEMINFO.sizeof; long /*int*/ hMenu = parent.handle; /* Use the character encoding for the default locale */ TCHAR buffer = new TCHAR(0, string, true); int byteCount = buffer.length() * TCHAR.sizeof; pszText = OS.HeapAlloc(hHeap, OS.HEAP_ZERO_MEMORY, byteCount); OS.MoveMemory(pszText, buffer, byteCount); /* * Bug in Windows 2000. For some reason, when MIIM_TYPE is set * on a menu item that also has MIIM_BITMAP, the MIIM_TYPE clears * the MIIM_BITMAP style. The fix is to use MIIM_STRING. */ if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) { info.fMask = OS.MIIM_STRING; } else { info.fMask = OS.MIIM_TYPE; info.fType = widgetStyle(); } info.dwTypeData = pszText; success = OS.SetMenuItemInfo(hMenu, id, false, info); } if (pszText != 0) OS.HeapFree(hHeap, 0, pszText); if (!success) { int error = OS.GetLastError(); SWT.error( SWT.ERROR_CANNOT_SET_TEXT, null, " [GetLastError=0x" + Integer.toHexString(error) + "]"); // $NON-NLS-1$ $NON-NLS-2$ } parent.redraw(); }