void relayout() {
   ToolItem[] items = getItems();
   boolean hasText = false, hasImage = false;
   for (int i = 0; i < items.length; i++) {
     ToolItem item = items[i];
     if (item != null) {
       item.resizeControl();
       hasText |= item.text != null && item.text.length() > 0;
       hasImage |= item.image != null;
     }
   }
   int type = OS.GTK_TOOLBAR_ICONS;
   if (hasText && hasImage) {
     if ((style & SWT.RIGHT) != 0) {
       type = OS.GTK_TOOLBAR_BOTH_HORIZ;
     } else {
       type = OS.GTK_TOOLBAR_BOTH;
     }
   } else if (hasText) {
     type = OS.GTK_TOOLBAR_TEXT;
   } else if (hasImage) {
     type = OS.GTK_TOOLBAR_ICONS;
   }
   OS.gtk_toolbar_set_style(handle, type);
 }
 /**
  * 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();
 }