/**
   * Sets the receiver's text. The string may include the mnemonic character.
   *
   * <p>Mnemonics are indicated by an '&amp;' 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 '&amp;' can be escaped by doubling it in the string,
   * causing a single '&amp;' 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();
  }
 /**
  * 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();
 }