Package org.sf.feeling.swt.win32.extension.widgets

Source Code of org.sf.feeling.swt.win32.extension.widgets.CToolBar

/*******************************************************************************
* Copyright (c) 2007 cnfree.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*  cnfree  - initial API and implementation
*******************************************************************************/
package org.sf.feeling.swt.win32.extension.widgets;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.ShellListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.graphics.Pattern;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Region;
import org.eclipse.swt.internal.Callback;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.sf.feeling.swt.win32.extension.Win32;
import org.sf.feeling.swt.win32.extension.graphics.GraphicsUtil;
import org.sf.feeling.swt.win32.extension.widgets.theme.GeneralThemeRender;
import org.sf.feeling.swt.win32.extension.widgets.theme.GlossyThemeRender;
import org.sf.feeling.swt.win32.extension.widgets.theme.OfficeThemeRender;
import org.sf.feeling.swt.win32.extension.widgets.theme.ThemeRender;
import org.sf.feeling.swt.win32.extension.widgets.theme.VS2005ThemeRender;
import org.sf.feeling.swt.win32.internal.extension.Extension;
import org.sf.feeling.swt.win32.internal.extension.graphics.GCExtension;

/**
* Style: SWT.MULITI, SWT.NONE, LARGE_ICON or SMALL_ICON
*
* @author <a href="mailto:cnfree2000@hotmail.com">cnfree</a>
*
*/
public class CToolBar implements MenuHolder, Bar
{

  private static final int KEY_LEFT = 16777219;

  private static final int KEY_RIGHT = 16777220;

  private static final int KEY_DOWN = 16777218;

  private static final int KEY_UP = 16777217;

  private static final int SUBMENUWIDTH = 11;

  private static final int CHEVRON_LENGTH = 12;

  private static final int HORIZON_GAP = 4;

  private static final int HORIZON_MARGIN = 2, VERTICAL_MARGIN = 1;

  private static final int SEPARATOR_WIDTH = 4;

  private static final int SHADOW_GAP = 4;

  private static final int VERTICAL_GAP = 3;

  private CToolItem chevronStartItem;

  private List drawCommands = new ArrayList();

  private boolean drawUpwards;

  private GridLayout layout;

  private CLabel toolbar;

  private MenuControl popupMenu;

  private boolean selected = false;

  private int style = SWT.NONE;

  private ThemeRender theme;

  private int trackItemIndex = -1;

  private final static int IMAGE_MIN_WIDTH = 16;

  private final static int IMAGE_MIN_HEIGHT = 16;

  private int imageWidth = IMAGE_MIN_WIDTH;

  private int imageHeight = IMAGE_MIN_HEIGHT;

  public final static int LARGE_ICON = 1 << 13;

  public final static int SMALL_ICON = 1 << 14;

  private static final int DRAW_FLAGS = SWT.DRAW_TAB | SWT.DRAW_TRANSPARENT
      | SWT.DRAW_DELIMITER;

  public CToolBar(Composite parent, int style)
  {
    this(parent, style, new VS2005ThemeRender());
  }

  private boolean menuTracked;

  public CToolBar(Composite parent, int style, ThemeRender theme)
  {
    toolbar = new CLabel(parent, SWT.NONE)
    {
      public Point computeSize(int wHint, int hHint, boolean changed)
      {
        if (this.isVisible())
        {
          Rectangle rect = recalculate();
          return new Point(rect.width, rect.height);
        }
        else
          return super.computeSize(wHint, hHint, changed);
      }
    };
    this.style = style;
    layout = new GridLayout();
    layout.marginWidth = layout.marginHeight = 0;
    layout.horizontalSpacing = 0;
    setTheme(theme);
    toolbar.setLayout(layout);
    toolbar.addPaintListener(new PaintListener()
    {

      public void paintControl(PaintEvent e)
      {
        onPaint(e);
      }

    });

    toolbar.addDisposeListener(new DisposeListener()
    {

      public void widgetDisposed(DisposeEvent e)
      {
        hideMenu();
      }

    });

    final ShellListener shellListener = new ShellListener()
    {
      public void shellClosed(ShellEvent e)
      {
        hideMenu();
      }

      public void shellDeactivated(ShellEvent e)
      {
        hideMenu();
      }

      public void shellIconified(ShellEvent e)
      {
        hideMenu();
      }

      public void shellActivated(ShellEvent e)
      {
        hideMenu();
      }

      public void shellDeiconified(ShellEvent e)
      {
        hideMenu();
      }
    };
    toolbar.getShell().addShellListener(shellListener);

    final Listener mouseDownListener = new Listener()
    {

      public void handleEvent(Event e)
      {
        if (getShell() == null || getShell().isDisposed())
        {
          Display.getDefault().removeFilter(SWT.MouseDown, this);
          return;
        }
        if (e.widget == null || e.widget.isDisposed()
            || checkMouseDownEvent(((Control) e.widget).toDisplay(e.x, e.y)))
        {
          hideMenu();
        }
      }
    };

    Display.getDefault().addFilter(SWT.MouseDown, mouseDownListener);

    final Listener keyDownListener = new Listener()
    {

      public void handleEvent(Event e)
      {
        if (toolbar == null || toolbar.isDisposed())
        {
          Display.getDefault().removeFilter(SWT.KeyDown, this);
          e.doit = false;
          return;
        }
        KeyEvent ke = new KeyEvent(e);
        if ((ke.keyCode == SWT.ALT) || ke.keyCode == SWT.F10)
        {
          hideMenu();
          return;
        }
        if (getCurrentMenu() == null)
        {
          return;
        }

        getCurrentMenu().dealAltKeyEvent(ke);

        if (ke.keyCode == KEY_RIGHT && trackItemIndex > -1)
        {
          getCurrentMenu().subMenuSelected();
        }
        if (ke.keyCode == KEY_LEFT && trackItemIndex > -1)
        {
          getCurrentMenu().parentMenuSelected();
        }
        if (ke.keyCode == KEY_DOWN || ke.keyCode == KEY_UP)
        {
          if (ke.keyCode == KEY_DOWN) getCurrentMenu().downSelected();
          else
            getCurrentMenu().upSelected();
        }
        if (ke.keyCode == SWT.ESC)
        {
          if (getCurrentMenu().parentMenu == null)
          {
            hideMenu();
            trackItemIndex = -1;
            selected = false;
            refresh();
          }
          else
          {
            getCurrentMenu().parentMenuSelected();
          }
        }
        if (ke.keyCode == SWT.CR)
        {
          getCurrentMenu().handleSelectedEvent();
        }
      }
    };
    Display.getDefault().addFilter(SWT.KeyDown, keyDownListener);

    toolbar.addDisposeListener(new DisposeListener()
    {

      public void widgetDisposed(DisposeEvent e)
      {
        Display.getDefault().removeFilter(SWT.MouseDown, mouseDownListener);
        Display.getDefault().removeFilter(SWT.KeyDown, keyDownListener);

      }

    });

    toolbar.addMouseMoveListener(new MouseMoveListener()
    {
      public void mouseMove(MouseEvent e)
      {
        handleMouseMoveEvent(new Point(e.x, e.y));
      }
    });

    toolbar.addMouseTrackListener(new MouseTrackAdapter()
    {

      public void mouseExit(MouseEvent e)
      {
        handleMouseMoveEvent(new Point(e.x, e.y));
      }
    });

    toolbar.addMouseListener(new MouseAdapter()
    {
      private boolean hideMenuCommand = false;

      public void mouseDown(MouseEvent e)
      {
        if (e.button != 1) return;
        for (int i = 0; i < drawCommands.size(); i++)
        {
          ToolDrawCommand command = ((ToolDrawCommand) drawCommands.get(i));
          if (command.getDrawRect().contains(e.x, e.y)
              && (command.getToolItem() == null || command.getToolItem()
                  .isEnabled()))
          {
            if (!selected && !isShowMenu())
            {
              selected = true;
              refresh();
              trackItemIndex = i;
              refresh();

              CToolItem item = command.getToolItem();
              if (item != null && item.getMenu() != null
                  && getMenuRect(command).contains(e.x, e.y))
              {
                menuTracked = true;
                drawCommand(trackItemIndex, true);
                showMenu(command);
              }
              else
              {
                menuTracked = false;
                drawCommand(trackItemIndex, true);
                if (item == null || !item.canSelected()) showMenu(command);
              }
            }
            else
            {
              hideMenuCommand = true;
            }
            return;
          }
        }
        selected = false;
        return;
      }

      public void mouseUp(MouseEvent e)
      {
        if (isShowMenu())
        {
          if (hideMenuCommand)
          {
            hideMenuCommand = false;
            popupMenu.hideMenu();
            popupMenu = null;
            selected = false;
            refresh();
          }
        }
        else
        {
          selected = false;
          if (trackItemIndex >= 0 && e.button == 1)
          {
            drawCommand(trackItemIndex, true);
            CToolItem item = ((ToolDrawCommand) drawCommands.get(trackItemIndex))
                .getToolItem();
            if (item != null && item.isEnabled())
            {
              Event event = new Event();
              event.widget = toolbar;
              event.data = item;
              event.type = SWT.SELECTED;
              getItem(trackItemIndex).fireSelectionEvent(
                  new SelectionEvent(event));
              fireSelectionEvent(event);
              Display.getDefault().asyncExec(new Runnable()
              {
                public void run()
                {
                  refresh();
                }
              });
            }
          }
          refresh();
        }
      }
    });
    MenuHolderManager.registerHolder(this);
  }

  private List listeners;

  public void addSelectionListener(SelectionListener listener)
  {
    if (toolbar.isDisposed()) return;
    if (listener == null) return;
    if (listeners == null) listeners = new ArrayList();
    if (!listeners.contains(listener)) listeners.add(listener);
  }

  public void removeSelectionListener(SelectionListener listener)
  {
    if (toolbar.isDisposed()) return;
    if (listener == null) return;
    listeners.remove(listener);
    if (listeners != null && listeners.size() == 0) listeners = null;
  }

  void fireSelectionEvent(final Event event)
  {
    if (toolbar.isDisposed()) return;
    if (listeners != null)
    {
      final SelectionEvent selectEvent = new SelectionEvent(event);
      for (int i = 0; i < listeners.size(); i++)
      {
        final SelectionListener listener = (SelectionListener) listeners.get(i);
        Display.getDefault().asyncExec(new Runnable()
        {
          public void run()
          {
            listener.widgetSelected(selectEvent);
          }
        });
      }
    }
  }

  public boolean checkMouseDownEvent(Point location)
  {
    if (toolbar.isDisposed()) return true;
    if (new Rectangle(0, 0, toolbar.getSize().x, toolbar.getSize().y).contains(toolbar
        .toControl(location)))
    {
      for (int i = 0; i < drawCommands.size(); i++)
      {
        ToolDrawCommand command = ((ToolDrawCommand) drawCommands.get(i));
        if (command.getDrawRect().contains(toolbar.toControl(location)))
        {
          return false;
        }
      }
      return true;
    }
    if (popupMenu != null) return popupMenu.checkMouseDownEvent(location);
    return true;
  }

  private void drawAllCommands(GC gc)
  {
    for (int i = 0; i < drawCommands.size(); i++)
    {
      ToolDrawCommand dc = (ToolDrawCommand) drawCommands.get(i);
      drawSingleCommand(gc, dc, (i == trackItemIndex));
    }
  }

  private void drawCommand(int drawItem, boolean tracked)
  {
    if (drawItem < 0 || drawItem >= drawCommands.size()) return;
    GC gc = new GC(toolbar);
    drawSingleCommand(gc, (ToolDrawCommand) drawCommands.get(drawItem), tracked);
    gc.dispose();
  }

  public void drawSelectionUpwards()
  {
    // Double check the state is correct for this method to be called
    if ((trackItemIndex != -1) && (selected))
    {
      // This flag is tested in the DrawCommand method
      drawUpwards = true;

      // Force immediate redraw of the item
      drawCommand(trackItemIndex, true);
    }
  }

  private void drawSingleCommand(GC gc, ToolDrawCommand dc, boolean tracked)
  {
    Rectangle drawRect = dc.getDrawRect();
    CToolItem mc = dc.getToolItem();
    if (!dc.isSeparator())
    {
      if (dc.isEnabled())
      {
        if (tracked)
        {
          if (theme instanceof GeneralThemeRender)
          {
            GeneralThemeRender themeRender = (GeneralThemeRender) theme;
            if (selected)
            {
              if (mc == null)
              {
                gc.setForeground(themeRender.getTool_item_bg_selected1());
                gc.setBackground(themeRender.getTool_item_bg_selected2());
                gc.fillGradientRectangle(drawRect.x, drawRect.y,
                    drawRect.width, drawRect.height, true);
                gc.setForeground(themeRender.getTool_item_fg_selected());
                gc.drawRectangle(drawRect);
              }
              else
              {
                if (menuTracked || (mc.getMenu() != null && !mc.canSelected()))
                {
                  gc.setForeground(themeRender.getTool_item_showmenu_bg1());
                  gc.setBackground(themeRender.getTool_item_showmenu_bg2());
                  gc.fillGradientRectangle(drawRect.x, drawRect.y,
                      drawRect.width, drawRect.height, true);
                  gc.setForeground(themeRender.getTool_item_showmenu_fg());
                  gc.drawRectangle(drawRect);
                }
                else
                {
                  gc.setForeground(themeRender.getTool_item_bg_selected1());
                  gc.setBackground(themeRender.getTool_item_bg_selected2());
                  if (mc.getMenu() != null)
                  {
                    Rectangle noneMenuRect = getNonMenuRect(dc);
                    gc.fillGradientRectangle(noneMenuRect.x,
                        noneMenuRect.y, noneMenuRect.width,
                        noneMenuRect.height, true);
                    gc.setForeground(themeRender.getTool_item_bg_track1());
                    gc.setBackground(themeRender.getTool_item_bg_track2());
                    Rectangle menuRect = getMenuRect(dc);
                    gc.fillGradientRectangle(menuRect.x, menuRect.y,
                        menuRect.width, menuRect.height, true);
                  }
                  else
                  {
                    gc.fillGradientRectangle(drawRect.x, drawRect.y,
                        drawRect.width, drawRect.height, true);
                  }
                  gc.setForeground(themeRender.getTool_item_fg_selected());
                  gc.drawRectangle(drawRect);
                }
              }
            }
            else if (mc != null && (mc.getStyle() & SWT.CHECK) != 0
                && mc.getSelection())
            {
              gc.setForeground(themeRender
                  .getTool_item_check_selection_bg_track1());
              gc.setBackground(themeRender
                  .getTool_item_check_selection_bg_track2());
              gc.fillGradientRectangle(drawRect.x, drawRect.y, drawRect.width,
                  drawRect.height, true);
              gc.setForeground(themeRender
                  .getTool_item_check_selection_fg_track());
              gc.drawRectangle(drawRect);
            }
            else
            {
              gc.setForeground(themeRender.getTool_item_bg_track1());
              gc.setBackground(themeRender.getTool_item_bg_track2());
              gc.fillGradientRectangle(drawRect.x, drawRect.y, drawRect.width,
                  drawRect.height, true);
              gc.setForeground(themeRender.getTool_item_fg_track());
              gc.drawRectangle(drawRect);
            }
          }
          else if (theme instanceof OfficeThemeRender)
          {
            OfficeThemeRender themeRender = (OfficeThemeRender) theme;
            Color[] colors = null;
            if (selected)
            {
              if (mc == null)
              {
                colors = new Color[] {
                    themeRender.getTool_item_outer_top_selected1(),
                    themeRender.getTool_item_outer_top_selected2(),
                    themeRender.getTool_item_outer_bottom_selected1(),
                    themeRender.getTool_item_outer_bottom_selected2(),
                    themeRender.getTool_item_inner_top_selected1(),
                    themeRender.getTool_item_inner_top_selected2(),
                    themeRender.getTool_item_inner_bottom_selected1(),
                    themeRender.getTool_item_inner_bottom_selected2(),
                    themeRender.getTool_item_border_selected(), };
                drawGradientBack(gc, drawRect, colors);
                drawGradientBorder(gc, drawRect, colors);
              }
              else
              {
                if (menuTracked || (mc.getMenu() != null && !mc.canSelected()))
                {
                  colors = new Color[] {
                      themeRender
                          .getTool_item_outer_top_showmenu_color1(),
                      themeRender
                          .getTool_item_outer_top_showmenu_color2(),
                      themeRender
                          .getTool_item_outer_bottom_showmenu_color1(),
                      themeRender
                          .getTool_item_outer_bottom_showmenu_color2(),
                      themeRender
                          .getTool_item_inner_top_showmenu_color1(),
                      themeRender
                          .getTool_item_inner_top_showmenu_color2(),
                      themeRender
                          .getTool_item_inner_bottom_showmenu_color1(),
                      themeRender
                          .getTool_item_inner_bottom_showmenu_color2(),
                      themeRender.getTool_item_border_showmenu_color(), };
                  drawGradientBack(gc, drawRect, colors);
                  drawGradientBorder(gc, drawRect, colors);
                }
                else
                {
                  colors = new Color[] {
                      themeRender.getTool_item_outer_top_selected1(),
                      themeRender.getTool_item_outer_top_selected2(),
                      themeRender.getTool_item_outer_bottom_selected1(),
                      themeRender.getTool_item_outer_bottom_selected2(),
                      themeRender.getTool_item_inner_top_selected1(),
                      themeRender.getTool_item_inner_top_selected2(),
                      themeRender.getTool_item_inner_bottom_selected1(),
                      themeRender.getTool_item_inner_bottom_selected2(),
                      themeRender.getTool_item_border_selected(), };
                  if (mc.getMenu() != null)
                  {
                    drawGradientBack(gc, getNonMenuRect(dc), colors);
                    colors = new Color[] {
                        themeRender.getTool_item_outer_top_track1(),
                        themeRender.getTool_item_outer_top_track2(),
                        themeRender.getTool_item_outer_bottom_track1(),
                        themeRender.getTool_item_outer_bottom_track2(),
                        themeRender.getTool_item_inner_top_track1(),
                        themeRender.getTool_item_inner_top_track2(),
                        themeRender.getTool_item_inner_bottom_track1(),
                        themeRender.getTool_item_inner_bottom_track2(),
                        themeRender.getTool_item_border_track(), };
                    drawGradientBack(gc, getMenuRect(dc), colors);
                  }
                  else
                    drawGradientBack(gc, drawRect, colors);
                  drawGradientBorder(gc, drawRect, colors);
                }
              }
            }
            else if (mc != null && (mc.getStyle() & SWT.CHECK) != 0
                && mc.getSelection())
            {
              colors = new Color[] {
                  themeRender.getTool_item_outer_top_checked_track1(),
                  themeRender.getTool_item_outer_top_checked_track2(),
                  themeRender.getTool_item_outer_bottom_checked_track1(),
                  themeRender.getTool_item_outer_bottom_checked_track2(),
                  themeRender.getTool_item_inner_top_checked_track1(),
                  themeRender.getTool_item_inner_top_checked_track2(),
                  themeRender.getTool_item_inner_bottom_checked_track1(),
                  themeRender.getTool_item_inner_bottom_checked_track2(),
                  themeRender.getTool_item_border_checked_track(), };
              drawGradientBack(gc, drawRect, colors);
              drawGradientBorder(gc, drawRect, colors);
            }
            else
            {
              colors = new Color[] {
                  themeRender.getTool_item_outer_top_track1(),
                  themeRender.getTool_item_outer_top_track2(),
                  themeRender.getTool_item_outer_bottom_track1(),
                  themeRender.getTool_item_outer_bottom_track2(),
                  themeRender.getTool_item_inner_top_track1(),
                  themeRender.getTool_item_inner_top_track2(),
                  themeRender.getTool_item_inner_bottom_track1(),
                  themeRender.getTool_item_inner_bottom_track2(),
                  themeRender.getTool_item_border_track(), };
              drawGradientBack(gc, drawRect, colors);
              drawGradientBorder(gc, drawRect, colors);
            }
          }
          else if (theme instanceof GlossyThemeRender)
          {
            drawGlossyItem(gc, drawRect, dc, tracked);
          }
          if (selected) showMenuShadow(gc, dc.getDrawRect(), dc.getToolItem());
        }
        else if (mc != null && (mc.getStyle() & SWT.CHECK) != 0 && mc.getSelection())
        {
          if (theme instanceof GeneralThemeRender)
          {
            GeneralThemeRender themeRender = (GeneralThemeRender) theme;
            gc
                .setForeground(themeRender
                    .getTool_item_check_selection_bg_normal1());
            gc
                .setBackground(themeRender
                    .getTool_item_check_selection_bg_normal2());
            gc.fillGradientRectangle(drawRect.x, drawRect.y, drawRect.width,
                drawRect.height, true);
            gc.setForeground(themeRender.getTool_item_check_selection_fg_normal());
            gc.drawRectangle(drawRect);
          }
          else if (theme instanceof OfficeThemeRender)
          {
            OfficeThemeRender themeRender = (OfficeThemeRender) theme;
            Color[] colors = new Color[] {
                themeRender.getTool_item_outer_top_checked1(),
                themeRender.getTool_item_outer_top_checked2(),
                themeRender.getTool_item_outer_bottom_checked1(),
                themeRender.getTool_item_outer_bottom_checked2(),
                themeRender.getTool_item_inner_top_checked1(),
                themeRender.getTool_item_inner_top_checked2(),
                themeRender.getTool_item_inner_bottom_checked1(),
                themeRender.getTool_item_inner_bottom_checked2(),
                themeRender.getTool_item_border_checked(), };
            drawGradientBack(gc, drawRect, colors);
            drawGradientBorder(gc, drawRect, colors);
          }
          else if (theme instanceof GlossyThemeRender)
          {
            drawGlossyItem(gc, drawRect, dc, tracked);
          }
        }
      }
      if (dc.isChevron)
      {
        Image image = theme.getTool_chevronImage();
        int yPos = drawRect.y + VERTICAL_GAP;
        int xPos = drawRect.x + ((drawRect.width - image.getImageData().width) / 2)
            + 1;
        if (selected && tracked)
        {
          xPos += 1;
          yPos += 1;
        }
        gc.drawImage(image, xPos, yPos);
      }
      else
      {
        if (dc.isEnabled() && toolbar.isEnabled())
        {
          gc.setForeground(theme.getTool_item_fg());
        }
        else
          gc.setForeground(theme.getTool_item_fg_disabled());
        drawImageAndText(gc, dc, selected, tracked);
      }

    }
    else
    {
      Color darkColor = theme.getTool_item_separater_darkcolor();
      Color lightColor = theme.getTool_item_separater_lightcolor();
      drawSeparator(gc, dc.getDrawRect(), lightColor, darkColor);
    }

  }

  private void drawGlossyItem(GC gc, Rectangle drawRect, ToolDrawCommand dc, boolean tracked)
  {
    GlossyThemeRender themeRender = (GlossyThemeRender) theme;
    gc.setAntialias(SWT.ON);
    Rectangle outerBorder = new Rectangle(drawRect.x, drawRect.y, drawRect.width + 1,
        drawRect.height + 1);
    Rectangle innerBorder = GraphicsUtil.inflate(outerBorder, -1, -1);
    Rectangle glossy = new Rectangle(innerBorder.x, innerBorder.y, innerBorder.width,
        innerBorder.height / 2);
    Rectangle glow = GraphicsUtil.createRectangleFromLTRB(outerBorder.x, outerBorder.y
        + Math.round(outerBorder.height * .5f), outerBorder.x + outerBorder.width,
        outerBorder.y + outerBorder.height);

    Pattern pattern = new Pattern(null, 0, glossy.y, 0, glossy.y + glossy.height,
        themeRender.getTool_item_bg_color1(), themeRender
            .getTool_item_bg_color1_alpha(), themeRender.getTool_item_bg_color2(),
        themeRender.getTool_item_bg_color2_alpha());
    Path path = new Path(null);
    path.addRectangle(glossy.x, glossy.y, glossy.width, glossy.height);
    gc.setBackgroundPattern(pattern);
    gc.fillPath(path);
    path.dispose();

    // draw border
    path = GraphicsUtil.createRoundRectangle(outerBorder, 2);
    gc.setForeground(themeRender.getTool_item_outer_border());
    gc.drawPath(path);
    path.dispose();

    if (tracked
        && dc.getToolItem() != null
        && selected
        && (menuTracked || (dc.getToolItem().getMenu() != null && !dc.getToolItem()
            .canSelected())))
    {
      path = GraphicsUtil.createTopRoundRectangle(innerBorder, 2);
      gc.setBackground(themeRender.getTool_item_bg_glossy_showMenu());
      gc.fillPath(path);
      path.dispose();

      path = GraphicsUtil.createTopRoundRectangle(innerBorder, 2);
      gc.setForeground(themeRender.getTool_item_bg_glossy_showMenu());
      gc.drawPath(path);
      path.dispose();
      gc.setAdvanced(false);
      return;
    }
    else if (tracked && dc.getToolItem() != null && selected
        && dc.getToolItem().getMenu() != null)
    {
      pattern = new Pattern(null, 0, glossy.y, 0, glossy.y + glossy.height, themeRender
          .getTool_item_bg_glossy_selected1(), themeRender
          .getTool_item_bg_glossy_selected1_alpha(), themeRender
          .getTool_item_bg_glossy_selected2(), themeRender
          .getTool_item_bg_glossy_selected2_alpha());
      Rectangle nonMenuRect = getNonMenuRect(dc);
      Rectangle nonMenuGlossy = new Rectangle(innerBorder.x, innerBorder.y,
          nonMenuRect.width - 1, innerBorder.height / 2);
      path = createTopLeftRoundRectangle(nonMenuGlossy, 2);
      gc.setBackgroundPattern(pattern);
      gc.fillPath(path);
      path.dispose();

      pattern = new Pattern(null, 0, glossy.y, 0, glossy.y + glossy.height, themeRender
          .getTool_item_bg_glossy_track1(), themeRender
          .getTool_item_bg_glossy_track1_alpha(), themeRender
          .getTool_item_bg_glossy_track2(), themeRender
          .getTool_item_bg_glossy_track2_alpha());

      Rectangle menuRect = getMenuRect(dc);
      Rectangle menuGlossy = new Rectangle(menuRect.x, innerBorder.y,
          menuRect.width - 1, innerBorder.height / 2);
      path = createTopRightRoundRectangle(menuGlossy, 2);
      gc.setBackgroundPattern(pattern);
      gc.fillPath(path);
      path.dispose();

      Color innerBorderColor = themeRender.getTool_item_inner_border_selected();

      path = createLeftRoundPath(new Rectangle(innerBorder.x, innerBorder.y,
          nonMenuRect.width - 1, innerBorder.height), 2);
      gc.setForeground(innerBorderColor);
      gc.drawPath(path);
      path.dispose();

      innerBorderColor = themeRender.getTool_item_inner_border_track();

      path = createRightRoundPath(new Rectangle(menuRect.x, innerBorder.y,
          menuRect.width, innerBorder.height), 2);
      gc.setForeground(innerBorderColor);
      gc.drawPath(path);
      path.dispose();

      path = GraphicsUtil.createRoundRectangle(glow, 2);
      gc.setClipping(path);
      path.dispose();

      Color glowColor = themeRender.getTool_item_bg_glow_track();
      path = createBottomRadialPath(glow);
      float[] point = new float[2];
      float[] bounds = new float[4];
      path.getBounds(bounds);
      point[0] = (bounds[0] + bounds[0] + bounds[2]) / 2f;
      point[1] = (bounds[1] + bounds[1] + bounds[3]) / 2f;
      GCExtension extension = new GCExtension(gc);
      extension.fillGradientPath(path, point, glowColor, 255, new Color[] { glowColor },
          new int[] { 0 });
      path.dispose();
      gc.setClipping((Region) null);

      gc.setAdvanced(false);
      return;
    }

    if (!(selected && tracked)) pattern = new Pattern(null, 0, glossy.y, 0, glossy.y
        + glossy.height, themeRender.getTool_item_bg_glossy_track1(), themeRender
        .getTool_item_bg_glossy_track1_alpha(), themeRender
        .getTool_item_bg_glossy_track2(), themeRender
        .getTool_item_bg_glossy_track2_alpha());
    else
      pattern = new Pattern(null, 0, glossy.y, 0, glossy.y + glossy.height, themeRender
          .getTool_item_bg_glossy_selected1(), themeRender
          .getTool_item_bg_glossy_selected1_alpha(), themeRender
          .getTool_item_bg_glossy_selected2(), themeRender
          .getTool_item_bg_glossy_selected2_alpha());
    path = GraphicsUtil.createTopRoundRectangle(glossy, 2);
    gc.setBackgroundPattern(pattern);
    gc.fillPath(path);
    path.dispose();

    Color innerBorderColor = (selected && tracked)
        || (dc.getToolItem() != null && (dc.getToolItem().getStyle() & SWT.CHECK) != 0 && dc
            .getToolItem().getSelection()) ? themeRender
        .getTool_item_inner_border_selected() : themeRender
        .getTool_item_inner_border_track();

    path = GraphicsUtil.createRoundRectangle(innerBorder, 2);
    gc.setForeground(innerBorderColor);
    gc.drawPath(path);
    path.dispose();

    if (!((menuTracked || (dc.getToolItem() != null && dc.getToolItem().getMenu() != null && !dc
        .getToolItem().canSelected()))
        && selected && tracked))
    {
      path = GraphicsUtil.createRoundRectangle(glow, 2);
      gc.setClipping(path);
      path.dispose();

      Color glowColor = themeRender.getTool_item_bg_glow_track();

      if (dc.getToolItem() != null && (dc.getToolItem().getStyle() & SWT.CHECK) != 0
          && dc.getToolItem().getSelection())
      {
        if (tracked)
        {
          glowColor = themeRender.getTool_item_bg_checked_glow_track();
        }
        else
        {
          glowColor = themeRender.getTool_item_bg_checked_glow();
        }
      }

      path = createBottomRadialPath(glow);
      float[] point = new float[2];
      float[] bounds = new float[4];
      path.getBounds(bounds);
      point[0] = (bounds[0] + bounds[0] + bounds[2]) / 2f;
      point[1] = (bounds[1] + bounds[1] + bounds[3]) / 2f;
      GCExtension extension = new GCExtension(gc);
      extension.fillGradientPath(path, point, glowColor, 255, new Color[] { glowColor },
          new int[] { 0 });
      path.dispose();
      gc.setClipping((Region) null);
    }
    gc.setAdvanced(false);
  }

  private Path createBottomRadialPath(Rectangle glow)
  {
    float[] bounds = new float[4];
    bounds[0] = glow.x;
    bounds[1] = glow.y;
    bounds[2] = glow.width;
    bounds[3] = glow.height;
    bounds[0] -= bounds[2] * .35f;
    bounds[1] -= bounds[3] * .15f;
    bounds[2] *= 1.7f;
    bounds[3] *= 2.3f;
    return GraphicsUtil.createEllipsePath(bounds);
  }

  /*
   * Three status: normal, hover(VS2003), disable.
   */
  private void drawImageAndText(GC gc, ToolDrawCommand mc, boolean selected, boolean tracked)
  {
    gc.setAdvanced(false);
    Rectangle drawRect = mc.getSelectRect();
    if (mc.getToolItem().getMenu() != null) drawRect = new Rectangle(drawRect.x,
        drawRect.y, drawRect.width - SUBMENUWIDTH, drawRect.height);
    int left = drawRect.x;
    int top = drawRect.y;
    int right = drawRect.width + left;
    int bottom = drawRect.height + top;
    int length = gc.textExtent(mc.getToolItem().getText(), DRAW_FLAGS).x;
    int height = gc.getFontMetrics().getHeight();
    String text = null;
    if (mc.getToolItem().getText().length() > 0) text = mc.getToolItem().getText();
    Image image = mc.getToolItem().getImage();

    if (text == null && hasText && ((style & SWT.TOP) != 0 || (style & SWT.BOTTOM) != 0)) text = "";

    if (text != null && image != null)
    {

      if ((style & SWT.TOP) != 0)
      {
        int x = left + Math.round((drawRect.width - image.getImageData().width) / 2f);
        int y = top + Math.round((imageHeight - image.getImageData().height) / 2f);
        drawImage(gc, mc, x, y, tracked);
        gc.drawText(text, left + Math.round((drawRect.width - length) / 2f), top
            + imageHeight + VERTICAL_MARGIN, DRAW_FLAGS);
      }
      else if ((style & SWT.BOTTOM) != 0)
      {
        int x = left + Math.round((drawRect.width - image.getImageData().width) / 2f);
        int y = bottom - imageHeight
            + Math.round((imageHeight - image.getImageData().height) / 2f);
        drawImage(gc, mc, x, y, tracked);
        gc
            .drawText(text, left + Math.round((drawRect.width - length) / 2f), top
                + drawRect.height - imageHeight - VERTICAL_MARGIN - height,
                DRAW_FLAGS);
      }
      else if ((style & SWT.RIGHT) != 0)
      {
        gc.drawText(text, right - imageWidth - HORIZON_MARGIN - length, top
            + Math.round((drawRect.height - height) / 2f), DRAW_FLAGS);
        int x = (right - imageWidth) + (imageWidth - image.getImageData().width) / 2;
        int y = top + Math.round((drawRect.height - image.getImageData().height) / 2f);
        drawImage(gc, mc, x, y, tracked);
      }
      else
      {
        int x = left + (imageWidth - image.getImageData().width) / 2;
        int y = top + Math.round((drawRect.height - image.getImageData().height) / 2f);
        drawImage(gc, mc, x, y, tracked);
        gc.drawText(text, left + HORIZON_MARGIN + imageWidth, top
            + Math.round((drawRect.height - height) / 2f), DRAW_FLAGS);
      }
    }
    else
    {
      if (text != null)
      {
        gc.drawText(text, left + Math.round((drawRect.width - length) / 2f), top
            + Math.round((drawRect.height - height) / 2f), DRAW_FLAGS);
      }
      else if (image != null)
      {
        int x = left + Math.round((drawRect.width - image.getImageData().width) / 2f);
        int y = top + Math.round((drawRect.height - image.getImageData().height) / 2f);
        drawImage(gc, mc, x, y, tracked);
      }
    }

    if (mc.getToolItem().getMenu() != null)
    {
      Rectangle menuRect = getMenuRect(mc);
      gc.setAdvanced(false);
      if (mc.isEnabled())
      {
        if (tracked) gc.setBackground(theme.getTool_item_arrow_bg_track());
        else
        {
          gc.setBackground(theme.getTool_item_arrow_bg());
        }
      }
      else
        gc.setBackground(theme.getTool_item_arrow_bg_disabled());
      GraphicsUtil.drawArrow(gc, menuRect, SWT.DOWN);

      if (tracked && !(menuTracked && selected) && mc.getToolItem().canSelected()
          && mc.getToolItem().isEnabled())
      {
        if (!(theme instanceof OfficeThemeRender))
        {
          if (theme instanceof GeneralThemeRender) gc
              .setForeground(((GeneralThemeRender) theme)
                  .getTool_item_check_separater_color());
          else if (theme instanceof GlossyThemeRender) gc
              .setForeground(((GlossyThemeRender) theme)
                  .getTool_item_check_separater_color());
          gc.drawLine(menuRect.x, menuRect.y + 1, menuRect.x, menuRect.y
              + menuRect.height - 1);
        }
        else
        {
          if (!selected)
          {
            gc.setForeground(((OfficeThemeRender) theme)
                .getTool_item_check_separater_drakcolor());
            gc.drawLine(menuRect.x, menuRect.y + 1, menuRect.x, menuRect.y
                + menuRect.height - 1);
            gc.setForeground(((OfficeThemeRender) theme)
                .getTool_item_check_separater_lightcolor());
            gc.drawLine(menuRect.x + 1, menuRect.y + 1, menuRect.x + 1, menuRect.y
                + menuRect.height - 1);
          }
        }
      }
    }
  }

  private Rectangle getMenuRect(ToolDrawCommand mc)
  {
    int menuLeft = mc.getSelectRect().x + mc.getSelectRect().width + 3 - SUBMENUWIDTH;
    int menuRight = mc.getDrawRect().x + mc.getDrawRect().width;
    Rectangle menuRect = new Rectangle(menuLeft, mc.getDrawRect().y, menuRight - menuLeft,
        mc.getDrawRect().height);
    return menuRect;
  }

  private Rectangle getNonMenuRect(ToolDrawCommand mc)
  {
    int left = mc.getDrawRect().x;
    int right = mc.getSelectRect().x + mc.getSelectRect().width + 3 - SUBMENUWIDTH;
    Rectangle menuRect = new Rectangle(left, mc.getDrawRect().y, right - left, mc
        .getDrawRect().height);
    return menuRect;
  }

  private void drawImage(GC gc, ToolDrawCommand mc, int x, int y, boolean tracked)
  {
    Image image = mc.getToolItem().getImage();
    Image disableImage = mc.getToolItem().getDisableImage();
    if (image != null)
    {
      if (mc.isEnabled())
      {
        if (tracked && !selected
            && (theme.isShowToolImageShadow() && GraphicsUtil.checkGdip()))
        {
          ImageData shadowImage = image.getImageData();
          PaletteData palette = new PaletteData(new RGB[] { new RGB(0, 0, 0),
              new RGB(154, 156, 146) });
          ImageData data = new ImageData(shadowImage.width, shadowImage.height, 1,
              palette);
          data.transparentPixel = shadowImage.transparentPixel;
          if (shadowImage.getTransparencyType() == SWT.TRANSPARENCY_PIXEL)
          {
            for (int pixelX = 0; pixelX < shadowImage.width; pixelX++)
            {
              for (int pixelY = 0; pixelY < shadowImage.width; pixelY++)
              {
                int dstPixel = shadowImage.getPixel(pixelX, pixelY);
                if (dstPixel != shadowImage.transparentPixel)
                {
                  data.setPixel(pixelX, pixelY, 1);
                }
                else
                  data.setPixel(pixelX, pixelY, 0);

              }
            }

            gc.setAdvanced(true);

            Image tempImage = new Image(gc.getDevice(), data);
            gc.drawImage(tempImage, x + 1, y + 1);
            tempImage.dispose();
            gc.setAdvanced(false);
            gc.drawImage(image, x - 1, y - 1);
          }
          else
          {
            gc.drawImage(image, x, y);
          }
        }
        else
        {
          if (GraphicsUtil.checkGdip() && theme.isShowToolImageShadow())
          {
            RGB[] rgbs = image.getImageData().palette.getRGBs();
            if (rgbs != null)
            {
              for (int i = 0; i < rgbs.length; i++)
              {
                RGB rgb = rgbs[i];
                rgb.red = (rgb.red + 76) - (((rgb.red + 32) / 64) * 19);
                rgb.green = (rgb.green + 76) - (((rgb.green + 32) / 64) * 19);
                rgb.blue = (rgb.blue + 76) - (((rgb.blue + 32) / 64) * 19);
              }
              ImageData shadowImage = image.getImageData();
              ImageData data = new ImageData(shadowImage.width,
                  shadowImage.height, shadowImage.depth, new PaletteData(
                      rgbs));
              data.transparentPixel = shadowImage.transparentPixel;
              for (int pixelX = 0; pixelX < shadowImage.width; pixelX++)
              {
                for (int pixelY = 0; pixelY < shadowImage.width; pixelY++)
                {
                  int dstPixel = shadowImage.getPixel(pixelX, pixelY);
                  if (dstPixel != shadowImage.transparentPixel)
                  {
                    data.setPixel(pixelX, pixelY, dstPixel);
                  }
                  else
                    data.setPixel(pixelX, pixelY,
                        shadowImage.transparentPixel);
                }
              }
              Image fadedImage = new Image(null, data);
              gc.drawImage(fadedImage, x, y);
              fadedImage.dispose();
            }
          }
          else
            gc.drawImage(image, x, y);
        }
      }
      else
      {
        // Draw a image disabled
        if (disableImage == null)
        {
          disableImage = new Image(null, image, SWT.IMAGE_DISABLE);
          gc.drawImage(disableImage, x, y);
          disableImage.dispose();
        }
        else
        {
          gc.drawImage(disableImage, x, y);
        }

      }
    }

  }

  private void drawGradientBack(GC g, Rectangle rect, Color[] colors)
  {
    g.setAdvanced(true);
    Rectangle backRect = new Rectangle(rect.x, rect.y, rect.width + 1, rect.height + 1);
    Rectangle backRect1 = GraphicsUtil.inflate(backRect, -1, -1);
    int height = backRect1.height / 2;
    Rectangle rect1 = new Rectangle(backRect1.x, backRect1.y, backRect1.width, height);
    Rectangle rect2 = new Rectangle(backRect1.x, backRect1.y + height, backRect1.width,
        backRect1.height - height);

    g.setForeground(colors[0]);
    g.setBackground(colors[1]);
    g.fillGradientRectangle(rect1.x, rect1.y, rect1.width, rect1.height, true);

    g.setForeground(colors[2]);
    g.setBackground(colors[3]);
    g.fillGradientRectangle(rect2.x, rect2.y, rect2.width, rect2.height, true);

    Rectangle backRect2 = GraphicsUtil.inflate(backRect1, -1, -1);
    height = backRect2.height / 2;
    rect1 = new Rectangle(backRect2.x, backRect2.y, backRect2.width, height);
    rect2 = new Rectangle(backRect2.x, backRect2.y + height, backRect2.width,
        backRect2.height - height);

    g.setForeground(colors[4]);
    g.setBackground(colors[5]);
    g.fillGradientRectangle(rect1.x, rect1.y, rect1.width, rect1.height, true);

    g.setForeground(colors[6]);
    g.setBackground(colors[7]);
    g.fillGradientRectangle(rect2.x, rect2.y, rect2.width, rect2.height, true);

    g.setAdvanced(false);
  }

  private void drawGradientBorder(GC g, Rectangle rect, Color[] colors)
  {
    if (GraphicsUtil.checkGdip())
    {
      g.setAdvanced(true);
      Rectangle backRect = new Rectangle(rect.x, rect.y, rect.width, rect.height);
      Path path = GraphicsUtil.createRoundPath(backRect, 1.2f);
      g.setForeground(colors[8]);
      g.drawPath(path);
      path.dispose();
      g.setAdvanced(false);
    }
    else
    {
      g.setForeground(colors[8]);
      g.drawRectangle(rect);
    }
  }

  public Control getControl()
  {
    return toolbar;
  }

  protected ToolDrawCommand getCurrentCommand()
  {
    if (toolbar.isDisposed()) return null;
    if (trackItemIndex < 0 || trackItemIndex >= drawCommands.size()) return null;
    return (ToolDrawCommand) drawCommands.get(trackItemIndex);
  }

  public CToolItem getSelection()
  {
    if (trackItemIndex == -1) return null;
    else
    {
      ToolDrawCommand dc = (ToolDrawCommand) drawCommands.get(trackItemIndex);
      if (dc == null) return null;
      else
        return dc.getToolItem();
    }
  }

  public int getSelectionIndex()
  {
    return trackItemIndex;
  }

  public Shell getShell()
  {
    if (toolbar.isDisposed()) return null;
    return toolbar.getShell();
  }

  public ThemeRender getTheme()
  {
    return theme;
  }

  private void handleMouseMoveEvent(Point screenPos)
  {
    if (!checkEnableHandleEvent()) return;
    for (int i = 0; i < drawCommands.size(); i++)
    {
      final ToolDrawCommand command = ((ToolDrawCommand) drawCommands.get(i));
      if (command.getDrawRect().contains(screenPos.x, screenPos.y))
      {
        if (trackItemIndex != i)
        {
          selected = false;
          toolbar.setToolTipText(null);
          if (popupMenu != null)
          {
            popupMenu.hideMenu();
            popupMenu = null;
          }
          refresh();
          trackItemIndex = i;
          if (command.getToolItem() != null
              && command.getToolItem().getToolTip() != null)
          {
            toolbar.setToolTipText(command.getToolItem().getToolTip());
          }
          refresh();
          if (!isShowMenu() && command.getToolItem() != null
              && command.getToolItem().getMenu() != null)
          {
            if (getMenuRect(command).contains(screenPos))
            {
              menuTracked = true;
            }
            else
              menuTracked = false;
          }
          else
          {
            menuTracked = false;
          }
          drawCommand(trackItemIndex, true);
          return;
        }
        return;
      }
    }
    toolbar.setToolTipText(null);
    if (trackItemIndex >= 0)
    {
      if (!selected)
      {
        refresh();
        drawCommand(trackItemIndex, false);
        trackItemIndex = -1;
      }
      else
      {
        if (!isShowMenu())
        {
          selected = false;
          refresh();
          drawCommand(trackItemIndex, false);
          trackItemIndex = -1;
        }
      }
    }
  }

  protected boolean checkEnableHandleEvent()
  {
    MenuHolder holder = MenuHolderManager.getActiveHolder();
    if (holder != null && holder != CToolBar.this) return false;
    return true;
  }

  public void hideMenu()
  {
    if (popupMenu != null)
    {
      popupMenu.hideMenu();
      popupMenu = null;
    }
    if (toolbar.isDisposed()) return;
    selected = false;
    refresh();
    drawCommand(trackItemIndex, false);
    trackItemIndex = -1;
  }

  public boolean isMultiLine()
  {
    return (style & SWT.MULTI) != 0;
  }

  private boolean isShowMenu()
  {
    return popupMenu != null && !popupMenu.getShell().isDisposed();
  }

  private void onPaint(PaintEvent e)
  {
    if (theme instanceof GlossyThemeRender)
    {
      drawGlossyThemeBackGround(e.gc);
    }
    recalculate();
    toolbar.getParent().layout();
    drawAllCommands(e.gc);
  }

  private void drawGlossyThemeBackGround(GC gc)
  {
    GlossyThemeRender themeRender = (GlossyThemeRender) theme;
    Rectangle glossyRect = new Rectangle(0, 0, toolbar.getSize().x,
        toolbar.getSize().y / 2);
    Pattern pattern = new Pattern(null, 0, 0, 0, glossyRect.height, themeRender
        .getToolbar_bg_glossy_color1(), themeRender
        .getToolbar_bg_glossy_color1_alpha(), themeRender
        .getToolbar_bg_glossy_color2(), themeRender
        .getToolbar_bg_glossy_color2_alpha());
    gc.setBackgroundPattern(pattern);
    Path path = new Path(null);
    path.addRectangle(glossyRect.x, glossyRect.y, glossyRect.width, glossyRect.height);
    gc.fillPath(path);
    path.dispose();

    int glowSize = (int) (toolbar.getSize().y * 0.15);
    Rectangle glowRect = new Rectangle(0, toolbar.getSize().y - glowSize, toolbar
        .getSize().x, glowSize);
    pattern = new Pattern(null, 0, glowRect.y, 0, glowRect.y + glowRect.height,
        themeRender.getToolbar_bg_glow_color1(), themeRender
            .getToolbar_bg_glow_color1_alpha(), themeRender
            .getToolbar_bg_glow_color2(), themeRender
            .getToolbar_bg_glow_color2_alpha());
    gc.setBackgroundPattern(pattern);
    path = new Path(null);
    path.addRectangle(glowRect.x, glowRect.y, glowRect.width, glowRect.height);
    gc.fillPath(path);
    path.dispose();
  }

  private boolean hasText = false;

  protected Rectangle recalculate()
  {
    hasText = false;
    int length = toolbar.getSize().x;

    imageWidth = IMAGE_MIN_WIDTH;
    imageHeight = IMAGE_MIN_HEIGHT;
    for (int i = 0; i < getItemCount(); i++)
    {
      Image image = getItem(i).getImage();
      if (image != null && !image.isDisposed())
      {
        int width = image.getImageData().width;
        int height = image.getImageData().height;
        if (width > imageWidth) imageWidth = width;
        if (height > imageHeight) imageHeight = height;
      }
    }

    if (length > 0)
    {
      int rows = 0;
      int columns = 0;

      int cellMinLength = HORIZON_GAP * 2;
      int lengthStart = HORIZON_MARGIN;

      int verticalStart = 0;
      if ((style & SWT.MULTI) == 0) length -= (HORIZON_MARGIN + CHEVRON_LENGTH + 1);
      else
        length -= HORIZON_GAP;
      drawCommands.clear();
      chevronStartItem = null;
      GC gc = new GC(toolbar);
      int BREADTH_GAP = (gc.getFontMetrics().getHeight() / 3) + 1;
      int rowHeight = gc.getFontMetrics().getHeight() + BREADTH_GAP * 2 + 1;
      if ((style & SWT.TOP) != 0 || (style & SWT.BOTTOM) != 0)
      {
        rowHeight += imageHeight;
        rowHeight += VERTICAL_MARGIN;
      }
      else
      {
        int imageRowHeight = imageHeight + BREADTH_GAP * 2 + 1;
        rowHeight = (imageRowHeight > rowHeight ? imageRowHeight : rowHeight);
      }
      // rowHeight += (VERTICAL_GAP * 2 + 1);
      int index = 0;
      for (int i = 0; i < getItemCount(); i++)
      {
        CToolItem item = getItem(i);
        if (!item.isVisible()) continue;
        int cellLength = 0;
        if (item.getText().equals("-") || (item.getStyle() & SWT.SEPARATOR) != 0) cellLength = HORIZON_GAP
            + SEPARATOR_WIDTH;
        else
        {
          if (item.getText() == null)
          {
            cellLength = cellMinLength + imageWidth;
          }
          else if (item.getImage() == null)
          {
            cellLength = cellMinLength
                + gc.textExtent(item.getText(), DRAW_FLAGS).x;
          }
          else
          {
            if ((style & SWT.TOP) == 0 && (style & SWT.BOTTOM) == 0)
            {
              cellLength = cellMinLength
                  + gc.textExtent(item.getText(), DRAW_FLAGS).x
                  + HORIZON_MARGIN;
              cellLength += imageWidth;
            }
            else
            {
              cellLength = gc.textExtent(item.getText(), DRAW_FLAGS).x;
              cellLength = cellLength < imageWidth ? imageWidth : cellLength;
              cellLength += (cellMinLength);
            }
            hasText = true;
          }
          if (item.getMenu() != null) cellLength += SUBMENUWIDTH;
        }

        Rectangle cellRect = new Rectangle(lengthStart, rowHeight * rows + 2,
            cellLength, rowHeight - 1);
        lengthStart += cellLength;
        columns++;

        if ((lengthStart > length) && (columns > 1))
        {
          if ((style & SWT.MULTI) != 0)
          {
            rows++;
            columns = 1;
            lengthStart = cellLength;
            cellRect.x = HORIZON_MARGIN - 1;
            cellRect.y += rowHeight;

          }
          else
          {
            if (index <= trackItemIndex)
            {
              removeItemTracking();
            }
            chevronStartItem = item;
            cellRect.y = 1;
            cellRect.width = CHEVRON_LENGTH + HORIZON_MARGIN;
            cellRect.x = toolbar.getClientArea().width - cellRect.width - 1;
            cellRect.height = rowHeight + 1;

            Rectangle drawRect = new Rectangle(cellRect.x, cellRect.y,
                cellRect.width, cellRect.height);
            drawRect.height -= 2; // border=1, vertical space = 1;
            // 2border+vertical
            // drawRect.x += 1;// remove border
            // drawRect.width -= 2;

            drawCommands.add(new ToolDrawCommand(drawRect));
            break;
          }
        }
        Rectangle drawRect = new Rectangle(cellRect.x, cellRect.y, cellRect.width,
            cellRect.height);
        drawRect.height -= 2; // border=1, vertical space = 1;
        // 2border+vertical
        // drawRect.x += 1;// remove border
        // drawRect.width -= 2;

        Rectangle selectRect = new Rectangle(cellRect.x, cellRect.y, cellRect.width,
            cellRect.height);
        selectRect.height -= (2 * VERTICAL_GAP + 1);
        selectRect.width -= (2 * HORIZON_GAP + 1);
        selectRect.x += HORIZON_GAP;
        selectRect.y += VERTICAL_GAP;
        drawCommands.add(new ToolDrawCommand(item, drawRect, selectRect));
        index++;
      }
      gc.dispose();
      int controlHeight = (rows + 1) * rowHeight + 2 * verticalStart + 2;
      if (toolbar.getBounds().height != controlHeight)
      {
        Rectangle rect = new Rectangle(toolbar.getBounds().x, toolbar.getBounds().y,
            toolbar.getBounds().width, controlHeight);
        return rect;
      }
    }
    return toolbar.getBounds();
  }

  public void refresh()
  {
    if (toolbar != null && !toolbar.isDisposed()) toolbar.redraw();
  }

  private void removeItemTracking()
  {
    if (trackItemIndex != -1 && trackItemIndex < drawCommands.size())
    {
      ToolDrawCommand dc = (ToolDrawCommand) drawCommands.get(trackItemIndex);
      if (dc.getToolItem() != null)
      {
        Event event = new Event();
        event.data = dc.getToolItem();
        event.detail = SWT.Deactivate;
        toolbar.notifyListeners(SWT.Deactivate, event);
      }
      trackItemIndex = -1;
    }
  }

  public void setBackground(Color color)
  {
    if (toolbar != null && !toolbar.isDisposed()) toolbar.setBackground(color);
  }

  public void setBackground(Color[] colors, int[] percents, boolean vertical)
  {
    if (toolbar != null && !toolbar.isDisposed()) toolbar.setBackground(colors, percents,
        vertical);
  }

  public void setBackgroundImage(Image image)
  {
    if (toolbar != null && !toolbar.isDisposed()) toolbar.setBackgroundImage(image);
  }

  public void setMultiLine(boolean multi)
  {
    if (!multi) style = style & ~SWT.MULTI;
    else
      style |= SWT.MULTI;
  }

  public void setSelection(int index, boolean isSelected)
  {
    if (drawCommands.size() > 0)
    {
      // If no item is currently tracked then...
      if (index > -1 && index < drawCommands.size())
      {
        // ...start tracking the first valid command
        ToolDrawCommand dc = (ToolDrawCommand) drawCommands.get(index);
        if (!dc.isSeparator() && (dc.isChevron() || dc.isEnabled()))
        {
          refresh();
          trackItemIndex = index;
          selected = isSelected;
          refresh();
          drawCommand(trackItemIndex, true);
          if (selected)
          {
            showMenu(dc);
          }
        }
      }
      else
      {
        selected = false;
        refresh();
        drawCommand(trackItemIndex, false);
        trackItemIndex = -1;
        hideMenu();
      }
    }
  }

  public void setTheme(ThemeRender theme)
  {
    if (toolbar == null || toolbar.isDisposed()) return;
    if (!GraphicsUtil.checkGdip() && theme instanceof GlossyThemeRender) return;
    this.theme = theme;
    if (theme.getToolbar_bgColors_percents() == null)
    {
      toolbar.setBackground(theme.getToolbar_bgColors()[0]);
    }
    else
      toolbar.setBackground(theme.getToolbar_bgColors(), theme
          .getToolbar_bgColors_percents(), true);
  }

  private void showMenu(ToolDrawCommand command)
  {
    if (command == null || getCurrentCommand() == null) return;
    if (command.getToolItem() != getCurrentCommand().getToolItem()) return;
    if (command.isChevron())
    {
      List items = new ArrayList();
      int index = indexOf(chevronStartItem);
      if (index > 0)
      {
        for (int i = index; i < getItemCount(); i++)
        {
          if (!((getItem(i).getStyle() & SWT.SEPARATOR) != 0 || getItem(i).getText()
              .equals("-"))) items.add(getItem(i));
        }
        if (items.size() > 0)
        {
          drawUpwards = false;
          popupMenu = new ToolMenuControl(this, theme, this.style);
          ((ToolMenuControl) popupMenu).setToolItems((CToolItem[]) (items
              .toArray(new CToolItem[0])));
          ((ToolMenuControl) popupMenu).setTopRightLocation(toolbar.toDisplay(
              toolbar.getSize().x, toolbar.getSize().y));
          popupMenu.createAndShowWindow();
          installMouseHook();
        }
      }

    }
    else
    {
      drawUpwards = false;
      popupMenu = new MenuControl(this, theme);
      popupMenu.menu = command.getToolItem().getMenu();
      popupMenu.screenPos = toolbar.toDisplay(new Point(command.getDrawRect().x, command
          .getDrawRect().y
          + command.getDrawRect().height));
      popupMenu.bar = this;
      popupMenu.leftScreenPos = popupMenu.screenPos;
      popupMenu.aboveScreenPos = toolbar.toDisplay(new Point(command.getDrawRect().x,
          command.getDrawRect().y + 1));
      // popupMenu.menuBar = this;
      popupMenu.borderGap = command.getDrawRect().width;
      popupMenu.createAndShowWindow();
      installMouseHook();
    }
  }

  private Callback mouseCallback;

  private int newAddress;

  private int oldAddress;

  private void installMouseHook()
  {
    mouseCallback = new Callback(this, "MouseProc", 3);
    newAddress = mouseCallback.getAddress();
    if (newAddress == 0) SWT.error(SWT.ERROR_NO_MORE_CALLBACKS);
    int threadId = Extension.GetCurrentThreadId();
    oldAddress = Extension.SetWindowsHookEx(Win32.WH_MOUSE, newAddress, 0, threadId);
    popupMenu.getControl().addDisposeListener(new DisposeListener()
    {

      public void widgetDisposed(DisposeEvent e)
      {
        if (mouseCallback != null)
        {
          Extension.UnhookWindowsHookEx(oldAddress);
          mouseCallback.dispose();
          mouseCallback = null;
          newAddress = 0;
        }
      }

    });
  }

  int MouseProc(int /* long */code, int /* long */wParam, int /* long */lParam)
  {
    int result = Extension.CallNextHookEx(oldAddress, code, wParam, lParam);
    if (code < 0) return result;
    switch (wParam)
    {
    case Win32.WM_NCLBUTTONDOWN:
    case Win32.WM_NCRBUTTONDOWN:
      hideMenu();
      break;
    }
    return result;
  }

  private void showMenuShadow(GC gc, Rectangle drawRect, CToolItem mc)
  {
    if (!GraphicsUtil.checkGdip() || !theme.isShowToolItemShadow()) return;
    if (mc == null) return;
    gc.setAdvanced(true);
    if (mc.getMenu() != null && mc.getMenu().getItemCount() > 0 && mc.isEnabled()
        && (menuTracked || !mc.canSelected()))
    {
      if (drawUpwards)
      {
        int rightLeft = drawRect.x + drawRect.width + 1;
        int rightTop = drawRect.y + 1;
        int top = drawRect.y + drawRect.height + 1;
        int left = drawRect.x + SHADOW_GAP;
        int width = drawRect.width + 1;
        int height = SHADOW_GAP;

        Pattern pattern = new Pattern(gc.getDevice(), rightLeft, 9999, rightLeft
            + SHADOW_GAP, 9999, theme.getMenuShadowColor(), 48, theme
            .getMenuShadowColor(), 0);
        gc.setForegroundPattern(pattern);
        gc.setBackgroundPattern(pattern);
        gc.fillRectangle(new Rectangle(rightLeft, rightTop, SHADOW_GAP,
            drawRect.height));
        pattern.dispose();

        pattern = new Pattern(gc.getDevice(), left + SHADOW_GAP, top - SHADOW_GAP,
            left, top + height, theme.getMenuShadowColor(), 64, theme
                .getMenuShadowColor(), 0);
        gc.setForegroundPattern(pattern);
        gc.setBackgroundPattern(pattern);
        gc.fillRectangle(new Rectangle(left, top, SHADOW_GAP, height));
        pattern.dispose();

        pattern = new Pattern(gc.getDevice(), left + width - SHADOW_GAP - 2, top
            - SHADOW_GAP - 2, left + width, top + height, theme
            .getMenuShadowColor(), 64, theme.getMenuShadowColor(), 0);
        gc.setForegroundPattern(pattern);
        gc.setBackgroundPattern(pattern);
        gc.fillRectangle(new Rectangle(left + width - SHADOW_GAP, top, SHADOW_GAP - 1,
            height - 1));
        pattern.dispose();

        pattern = new Pattern(gc.getDevice(), 9999, top, 9999, top + height, theme
            .getMenuShadowColor(), 48, theme.getMenuShadowColor(), 0);
        gc.setForegroundPattern(pattern);
        gc.setBackgroundPattern(pattern);
        gc.fillRectangle(new Rectangle(left + SHADOW_GAP, top, width - SHADOW_GAP * 2,
            height));
        pattern.dispose();
      }
      else
      {
        int rightLeft = drawRect.x + drawRect.width + 1;
        int rightTop = drawRect.y + SHADOW_GAP;

        Pattern pattern = new Pattern(gc.getDevice(), rightLeft - SHADOW_GAP, rightTop
            + SHADOW_GAP, rightLeft + SHADOW_GAP, rightTop, theme
            .getMenuShadowColor(), 64, theme.getMenuShadowColor(), 0);
        gc.setForegroundPattern(pattern);
        gc.setBackgroundPattern(pattern);
        gc.fillRectangle(new Rectangle(rightLeft, drawRect.y + SHADOW_GAP,
            SHADOW_GAP - 2, 1));
        gc.fillRectangle(new Rectangle(rightLeft, drawRect.y + 1 + SHADOW_GAP,
            SHADOW_GAP - 1, 1));
        gc.fillRectangle(new Rectangle(rightLeft, drawRect.y + 2 + SHADOW_GAP,
            SHADOW_GAP, SHADOW_GAP - 2));
        pattern.dispose();

        rightTop += SHADOW_GAP;

        pattern = new Pattern(gc.getDevice(), rightLeft, 9999, rightLeft + SHADOW_GAP,
            9999, theme.getMenuShadowColor(), 48, theme.getMenuShadowColor(), 0);
        gc.setForegroundPattern(pattern);
        gc.setBackgroundPattern(pattern);
        gc.fillRectangle(new Rectangle(rightLeft, rightTop, SHADOW_GAP, drawRect.y
            + drawRect.height - rightTop + 1));
        pattern.dispose();
      }
    }
    gc.setAdvanced(false);
  }

  public boolean isAcitve()
  {
    return trackItemIndex > -1;
  }

  private List items = new ArrayList();

  public CToolItem addItem(CToolItem value)
  {
    items.add(value);
    return value;
  }

  public void addItems(CToolItem[] values)
  {
    for (int i = 0; i < values.length; i++)
    {
      addItem(values[i]);
    }
  }

  public void removeAll()
  {
    while (items.size() > 0)
      removeItem(getItem(0));
  }

  public void removeItem(CToolItem value)
  {
    value.disposed();
    items.remove(value);
  }

  public void addItem(int index, CToolItem value)
  {
    items.add(index, value);
  }

  public boolean contains(CToolItem value)
  {
    return items.contains(value);
  }

  public int getItemCount()
  {
    return items.size();
  }

  public CToolItem getItem(int index)
  {
    if (index < 0 || index >= items.size()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
    return (CToolItem) items.get(index);
  }

  public CToolItem getItem(String text)
  {
    for (int i = 0; i < items.size(); i++)
    {
      CToolItem item = getItem(i);
      if (item.getText().equals(text)) return item;
    }
    return null;
  }

  public boolean visibleItems()
  {
    for (int i = 0; i < items.size(); i++)
    {
      CToolItem item = getItem(i);
      if (item.isVisible())
      {
        if (!item.getText().equals("-"))
        {
          if (item.getMenu() != null && item.getMenu().getItemCount() > 0
              && !item.getMenu().visibleItems()) continue;
          return true;
        }
      }
    }

    return false;
  }

  public int indexOf(CToolItem value)
  {
    return items.indexOf(value);
  }

  private void drawSeparator(GC g, Rectangle rect, Color light, Color dark)
  {
    int x = rect.x + HORIZON_GAP;
    int y = rect.y;
    int bottom = y + rect.height;
    g.setForeground(dark);
    g.drawLine(x, y + VERTICAL_GAP + 1, x, bottom - VERTICAL_GAP + 1);
    g.setForeground(light);
    g.drawLine(x + 1, y + VERTICAL_GAP + 1, x + 1, bottom - VERTICAL_GAP + 1);
  }

  public CMenu getMenu()
  {
    return null;
  }

  public int getStyle()
  {
    return style;
  }

  public void setStyle(int style)
  {
    this.style = style;
    refresh();
  }

  MenuControl getCurrentMenu()
  {
    if (popupMenu != null && popupMenu instanceof ToolMenuControl) return null;
    if (popupMenu != null && popupMenu.trackItemIndex != -1) return popupMenu
        .getCurrentMenu();
    else if (popupMenu != null) return popupMenu;
    return null;
  }

  private Path createTopLeftRoundRectangle(Rectangle rectangle, int radius)
  {
    Path path = new Path(null);

    int l = rectangle.x;
    int t = rectangle.y;
    int w = rectangle.width;
    int h = rectangle.height;
    int d = radius << 1;

    path.addArc(l, t, d, d, -180, -90); // topleft
    path.lineTo(l + radius, t);
    path.lineTo(l + w, t);
    path.lineTo(l + w, t + h);
    path.lineTo(l, t + h);
    path.lineTo(l, t + radius);
    path.close();

    return path;
  }

  private Path createTopRightRoundRectangle(Rectangle rectangle, int radius)
  {
    Path path = new Path(null);

    int l = rectangle.x;
    int t = rectangle.y;
    int w = rectangle.width;
    int h = rectangle.height;
    int d = radius << 1;

    path.moveTo(l, t); // topleft
    path.lineTo(l + w - radius, t);
    path.addArc(l + w - d, t, d, d, -270, -90); // topright
    path.lineTo(l + w, t + radius);
    path.lineTo(l + w, t + h);
    path.lineTo(l, t + h);
    path.lineTo(l, t);
    path.close();

    return path;
  }

  public static Path createLeftRoundPath(Rectangle rectangle, int radius)
  {
    Path path = new Path(null);

    int l = rectangle.x;
    int t = rectangle.y;
    int w = rectangle.width;
    int h = rectangle.height;
    int d = radius << 1;

    path.moveTo(l + w, t);
    path.lineTo(l + radius, t);
    path.addArc(l, t, d, d, 90, 90);

    path.lineTo(l, t + radius);
    path.lineTo(l, t + h - radius);
    path.addArc(l, t + h - d, d, d, 180, 90);
    path.lineTo(l + radius, t + h);
    path.lineTo(l + w, t + h);

    return path;
  }

  public static Path createRightRoundPath(Rectangle rectangle, int radius)
  {
    Path path = new Path(null);

    int l = rectangle.x;
    int t = rectangle.y;
    int w = rectangle.width;
    int h = rectangle.height;
    int d = radius << 1;

    path.moveTo(l, t);
    path.lineTo(l + w - radius, t);
    path.addArc(l + w - d, t, d, d, -270, -90);
    path.lineTo(l + w, t + radius);
    path.lineTo(l + w, t + h - radius);
    path.addArc(l + w - d, t + h - d, d, d, 0, -90);
    path.lineTo(l + w - radius, t + h);
    path.lineTo(l, t + h); // top

    return path;
  }
}
TOP

Related Classes of org.sf.feeling.swt.win32.extension.widgets.CToolBar

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.