14b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye/*******************************************************************************
24b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye * Copyright (c) 2011 Google, Inc.
34b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye * All rights reserved. This program and the accompanying materials
44b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye * are made available under the terms of the Eclipse Public License v1.0
54b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye * which accompanies this distribution, and is available at
64b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye * http://www.eclipse.org/legal/epl-v10.html
74b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye *
84b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye * Contributors:
94b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye *    Google, Inc. - initial API and implementation
104b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye *******************************************************************************/
114b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyepackage org.eclipse.wb.core.controls.flyout;
124b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
134b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.jface.action.Action;
144b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.jface.action.IMenuListener;
154b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.jface.action.IMenuManager;
164b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.jface.action.MenuManager;
174b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.jface.resource.JFaceResources;
184b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.SWT;
194b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.events.DisposeEvent;
204b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.events.DisposeListener;
214b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.events.MouseAdapter;
224b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.events.MouseEvent;
234b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.events.MouseMoveListener;
244b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.events.MouseTrackAdapter;
254b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.graphics.Font;
264b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.graphics.GC;
274b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.graphics.Image;
284b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.graphics.Point;
294b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.graphics.Rectangle;
304b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.widgets.Composite;
314b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.widgets.Control;
324b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.widgets.Event;
334b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.widgets.Listener;
344b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.widgets.Sash;
354b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.swt.widgets.Tracker;
364b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.wb.core.controls.Messages;
374b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.wb.draw2d.IColorConstants;
384b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.wb.draw2d.ICursorConstants;
394b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport org.eclipse.wb.internal.core.utils.ui.DrawUtils;
404b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
414b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport java.util.ArrayList;
424b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyeimport java.util.List;
434b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
444b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye/**
454b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye * {@link FlyoutControlComposite} is container for two {@link Control}'s. One (client control) is
464b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye * used to fill client area. Second (flyout control) can be docked to any enabled position or
474b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye * temporary hidden.
484b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye *
494b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye * @author scheglov_ke
504b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye * @coverage core.control
514b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye */
524b1a9d7baa71df312585022c22e8025fafaba95aTor Norbyepublic final class FlyoutControlComposite extends Composite {
534b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private static final int RESIZE_WIDTH = 5;
544b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private static final int TITLE_LINES = 30;
554b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private static final int TITLE_MARGIN = 5;
564b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private static final Font TITLE_FONT = JFaceResources.getFontRegistry().getBold(
574b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      JFaceResources.DEFAULT_FONT);
584b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
594b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
604b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  // Images
614b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
624b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
634b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private static final Image PIN = loadImage("icons/pin.gif");
644b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private static final Image ARROW_LEFT = loadImage("icons/arrow_left.gif");
654b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private static final Image ARROW_RIGHT = loadImage("icons/arrow_right.gif");
664b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private static final Image ARROW_TOP = loadImage("icons/arrow_top.gif");
674b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private static final Image ARROW_BOTTOM = loadImage("icons/arrow_bottom.gif");
684b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
694b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private static Image loadImage(String path) {
704b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    return DrawUtils.loadImage(FlyoutControlComposite.class, path);
714b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
724b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
734b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
744b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
754b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  // Instance fields
764b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
774b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
784b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private final IFlyoutPreferences m_preferences;
794b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private final FlyoutContainer m_flyoutContainer;
804b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private int m_minWidth = 150;
814b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private int m_validDockLocations = -1;
824b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private final List<IFlyoutMenuContributor> m_menuContributors =
834b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      new ArrayList<IFlyoutMenuContributor>();
844b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
854b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
864b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
874b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  // Constructor
884b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
894b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
904b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  public FlyoutControlComposite(Composite parent, int style, IFlyoutPreferences preferences) {
914b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    super(parent, style);
924b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    m_preferences = preferences;
934b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // add listeners
944b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    addListener(SWT.Resize, new Listener() {
954b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      @Override
964b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    public void handleEvent(Event event) {
974b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (getShell().getMinimized()) {
984b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          return;
994b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
1004b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        layout();
1014b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
1024b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    });
1034b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // create container for flyout control
1044b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    m_flyoutContainer = new FlyoutContainer(this, SWT.NO_BACKGROUND);
1054b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
1064b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
1074b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
1084b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
1094b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  // Parents
1104b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
1114b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
1124b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  /**
1134b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   * @return the parent {@link Composite} for flyout {@link Control}.
1144b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   */
1154b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  public Composite getFlyoutParent() {
1164b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    return m_flyoutContainer;
1174b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
1184b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
1194b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  /**
1204b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   * @return the parent {@link Composite} for client {@link Control}.
1214b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   */
1224b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  public Composite getClientParent() {
1234b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    return this;
1244b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
1254b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
1264b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  /**
1274b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   * Sets the bit set with valid docking locations.
1284b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   */
1294b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  public void setValidDockLocations(int validDockLocations) {
1304b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    m_validDockLocations = validDockLocations;
1314b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
1324b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
1334b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
1344b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
1354b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  // Access
1364b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
1374b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
1384b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  /**
1394b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   * Sets the minimal width of flyout.
1404b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   */
1414b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  public void setMinWidth(int minWidth) {
1424b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    m_minWidth = minWidth;
1434b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
1444b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
1454b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  /**
1464b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   * Sets the text of title.
1474b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   */
1484b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  public void setTitleText(String text) {
1494b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    m_flyoutContainer.setTitleText(text);
1504b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
1514b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
1524b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  /**
1534b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   * Adds new {@link IFlyoutMenuContributor}.
1544b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   */
1554b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  public void addMenuContributor(IFlyoutMenuContributor contributor) {
1564b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    if (!m_menuContributors.contains(contributor)) {
1574b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      m_menuContributors.add(contributor);
1584b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
1594b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
1604b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
1614b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
1624b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
1634b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  // Layout
1644b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
1654b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
1664b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  @Override
1674b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  public void layout() {
1684b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    Rectangle clientArea = getClientArea();
1694b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    int state = m_preferences.getState();
1704b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    Control client = getChildren()[1];
1714b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // check, may be "clientArea" is empty, for example because CTabFolder page is not visible
1724b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    if (clientArea.width == 0 || clientArea.height == 0) {
1734b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      return;
1744b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
1754b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // check, maybe flyout has no Control, so "client" should fill client area
1764b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    if (m_flyoutContainer.getControl() == null
1774b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            // BEGIN ADT MODIFICATIONS
1784b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            || !m_flyoutContainer.getControl().getVisible()
1794b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            // END ADT MODIFICATIONS
1804b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            ) {
1814b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      m_flyoutContainer.setBounds(0, 0, 0, 0);
1824b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      client.setBounds(clientArea);
1834b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      return;
1844b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
1854b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // prepare width to display
1864b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    int width;
1874b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    int offset;
1884b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    if (state == IFlyoutPreferences.STATE_OPEN) {
1894b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      width = m_preferences.getWidth();
1904b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // limit maximum value
1914b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (isHorizontal()) {
1924b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        width = Math.min(clientArea.width / 2, width);
1934b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      } else {
1944b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        width = Math.min(clientArea.height / 2, width);
1954b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
1964b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // limit minimum value
1974b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      width = Math.max(width, m_minWidth);
1984b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      width = Math.max(width, 2 * m_flyoutContainer.m_titleHeight + m_flyoutContainer.m_titleWidth);
1994b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // remember actual width
2004b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      m_preferences.setWidth(width);
2014b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      //
2024b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      offset = width;
2034b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    } else if (state == IFlyoutPreferences.STATE_EXPANDED) {
2044b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      offset = m_flyoutContainer.m_titleHeight;
2054b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      width = m_preferences.getWidth();
2064b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    } else {
2074b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      width = m_flyoutContainer.m_titleHeight;
2084b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      offset = width;
2094b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
2104b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // change bounds for flyout container and client control
2114b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    {
2124b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (isWest()) {
2134b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_flyoutContainer.setBounds(0, 0, width, clientArea.height);
2144b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        client.setBounds(offset, 0, clientArea.width - offset, clientArea.height);
2154b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      } else if (isEast()) {
2164b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_flyoutContainer.setBounds(clientArea.width - width, 0, width, clientArea.height);
2174b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        client.setBounds(0, 0, clientArea.width - offset, clientArea.height);
2184b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      } else if (isNorth()) {
2194b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_flyoutContainer.setBounds(0, 0, clientArea.width, width);
2204b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        client.setBounds(0, offset, clientArea.width, clientArea.height - offset);
2214b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      } else if (isSouth()) {
2224b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_flyoutContainer.setBounds(0, clientArea.height - width, clientArea.width, width);
2234b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        client.setBounds(0, 0, clientArea.width, clientArea.height - offset);
2244b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
2254b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
2264b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
2274b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
2284b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
2294b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
2304b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  // Internal utils
2314b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
2324b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
2334b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private boolean isHorizontal() {
2344b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    return isWest() || isEast();
2354b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
2364b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
2374b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private boolean isWest() {
2384b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    return getDockLocation() == IFlyoutPreferences.DOCK_WEST;
2394b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
2404b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
2414b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private boolean isEast() {
2424b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    return getDockLocation() == IFlyoutPreferences.DOCK_EAST;
2434b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
2444b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
2454b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private boolean isNorth() {
2464b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    return getDockLocation() == IFlyoutPreferences.DOCK_NORTH;
2474b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
2484b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
2494b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private boolean isSouth() {
2504b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    return getDockLocation() == IFlyoutPreferences.DOCK_SOUTH;
2514b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
2524b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
2534b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  /**
2544b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   * @return <code>true</code> if given docking location is valid.
2554b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   */
2564b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private boolean isValidDockLocation(int location) {
2574b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    return (location & m_validDockLocations) == location;
2584b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
2594b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
2604b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  /**
2614b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   * @return current docking location.
2624b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   */
2634b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private int getDockLocation() {
2644b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    return m_preferences.getDockLocation();
2654b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
2664b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
2674b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  /**
2684b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   * Sets new docking location.
2694b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   */
2704b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private void setDockLocation(int dockLocation) {
2714b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    m_preferences.setDockLocation(dockLocation);
2724b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    layout();
2734b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
2744b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
2754b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  // BEGIN ADT MODIFICATIONS
2764b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  /** If the flyout hover is showing, dismiss it */
2774b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  public void dismissHover() {
2784b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (m_flyoutContainer != null) {
2794b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          m_flyoutContainer.dismissHover();
2804b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
2814b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
2824b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
2834b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  /** Sets a listener to be modified when windows are opened, collapsed and expanded */
2844b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  public void setListener(IFlyoutListener listener) {
2854b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      assert m_listener == null; // Only one listener supported
2864b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      m_listener = listener;
2874b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
2884b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private IFlyoutListener m_listener;
2894b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  // END ADT MODIFICATIONS
2904b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
2914b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
2924b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
2934b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  // FlyoutContainer
2944b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
2954b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
2964b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  /**
2974b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   * Container for flyout {@link Control}.
2984b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   *
2994b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   * @author scheglov_ke
3004b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye   */
3014b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private final class FlyoutContainer extends Composite {
3024b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
3034b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
3044b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // Container
3054b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
3064b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
3074b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    public FlyoutContainer(Composite parent, int style) {
3084b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      super(parent, style);
3094b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      configureMenu();
3104b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      updateTitleImage("Flyout");
3114b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // add listeners
3124b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      addListener(SWT.Dispose, new Listener() {
3134b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        @Override
3144b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        public void handleEvent(Event event) {
3154b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          if (m_titleImage != null) {
3164b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            m_titleImage.dispose();
3174b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            m_titleImageRotated.dispose();
3184b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            m_titleImage = null;
3194b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            m_titleImageRotated = null;
3204b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
3214b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          if (m_backImage != null) {
3224b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            m_backImage.dispose();
3234b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            m_backImage = null;
3244b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
3254b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
3264b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      });
3274b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      {
3284b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        Listener listener = new Listener() {
3294b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          @Override
3304b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        public void handleEvent(Event event) {
3314b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            layout();
3324b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
3334b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        };
3344b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        addListener(SWT.Move, listener);
3354b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        addListener(SWT.Resize, listener);
3364b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
3374b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      addListener(SWT.Paint, new Listener() {
3384b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        @Override
3394b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        public void handleEvent(Event event) {
3404b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          handlePaint(event.gc);
3414b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
3424b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      });
3434b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // mouse listeners
3444b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      addMouseListener(new MouseAdapter() {
3454b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        @Override
3464b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        public void mouseDown(MouseEvent event) {
3474b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          if (event.button == 1) {
3484b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            handle_mouseDown(event);
3494b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
3504b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
3514b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
3524b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        @Override
3534b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        public void mouseUp(MouseEvent event) {
3544b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          if (event.button == 1) {
3554b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            handle_mouseUp(event);
3564b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
3574b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
3584b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      });
3594b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      addMouseTrackListener(new MouseTrackAdapter() {
3604b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        @Override
3614b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        public void mouseExit(MouseEvent e) {
3624b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          m_stateHover = false;
3634b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          redraw();
3644b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          setCursor(null);
3654b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
3664b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
3674b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        @Override
3684b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        public void mouseHover(MouseEvent e) {
3694b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          handle_mouseHover();
3704b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
3714b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      });
3724b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      addMouseMoveListener(new MouseMoveListener() {
3734b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        @Override
3744b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        public void mouseMove(MouseEvent event) {
3754b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          handle_mouseMove(event);
3764b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
3774b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      });
3784b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
3794b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
3804b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // BEGIN ADT MODIFICATIONS
3814b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private void dismissHover() {
3824b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      int state = m_preferences.getState();
3834b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (state == IFlyoutPreferences.STATE_EXPANDED) {
3844b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        state = IFlyoutPreferences.STATE_COLLAPSED;
3854b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_preferences.setState(state);
3864b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        redraw();
3874b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        FlyoutControlComposite.this.layout();
3884b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (m_listener != null) {
3894b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            m_listener.stateChanged(IFlyoutPreferences.STATE_EXPANDED, state);
3904b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
3914b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
3924b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
3934b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // END END MODIFICATIONS
3944b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
3954b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
3964b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
3974b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // Events: mouse
3984b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
3994b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
4004b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private boolean m_resize;
4014b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private boolean m_stateHover;
4024b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
4034b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
4044b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * Handler for {@link SWT#MouseDown} event.
4054b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
4064b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private void handle_mouseDown(MouseEvent event) {
4074b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (m_stateHover) {
4084b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        int state = m_preferences.getState();
4094b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        // BEGIN ADT MODIFICATIONS
4104b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        int oldState = state;
4114b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        // END ADT MODIFICATIONS
4124b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (state == IFlyoutPreferences.STATE_OPEN) {
4134b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          state = IFlyoutPreferences.STATE_COLLAPSED;
4144b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        } else {
4154b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          state = IFlyoutPreferences.STATE_OPEN;
4164b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
4174b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_preferences.setState(state);
4184b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        redraw();
4194b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        FlyoutControlComposite.this.layout();
4204b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        // BEGIN ADT MODIFICATIONS
4214b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (m_listener != null) {
4224b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          m_listener.stateChanged(oldState, state);
4234b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
4244b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        // END ADT MODIFICATIONS
4254b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      } else if (getCursor() == ICursorConstants.SIZEWE || getCursor() == ICursorConstants.SIZENS) {
4264b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_resize = true;
4274b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      } else if (getCursor() == ICursorConstants.SIZEALL) {
4284b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        handleDocking();
4294b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
4304b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
4314b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
4324b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
4334b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * Handler for {@link SWT#MouseUp} event.
4344b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
4354b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private void handle_mouseUp(MouseEvent event) {
4364b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (m_resize) {
4374b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_resize = false;
4384b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        handle_mouseMove(event);
4394b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
4404b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
4414b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
4424b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
4434b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * Handler for {@link SWT#MouseMove} event.
4444b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
4454b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private void handle_mouseMove(MouseEvent event) {
4464b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      final FlyoutControlComposite container = FlyoutControlComposite.this;
4474b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (m_resize) {
4484b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        // prepare width
4494b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        int width;
4504b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (isHorizontal()) {
4514b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          width = getSize().x;
4524b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        } else {
4534b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          width = getSize().y;
4544b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
4554b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        // prepare new width
4564b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        int newWidth = width;
4574b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (isWest()) {
4584b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          newWidth = event.x + RESIZE_WIDTH / 2;
4594b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        } else if (isEast()) {
4604b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          newWidth = width - event.x + RESIZE_WIDTH / 2;
4614b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        } else if (isNorth()) {
4624b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          newWidth = event.y + RESIZE_WIDTH / 2;
4634b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        } else if (isSouth()) {
4644b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          newWidth = width - event.y + RESIZE_WIDTH / 2;
4654b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
4664b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        // update width
4674b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (newWidth != width) {
4684b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          m_preferences.setWidth(newWidth);
4694b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          redraw();
4704b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          container.layout();
4714b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
4724b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      } else {
4734b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        Rectangle clientArea = getClientArea();
4744b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        boolean inside = clientArea.contains(event.x, event.y);
4754b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        int x = event.x;
4764b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        int y = event.y;
4774b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (inside) {
4784b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          // check for state
4794b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          {
4804b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            boolean oldStateHover = m_stateHover;
4814b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            if (isEast()) {
4824b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              m_stateHover = x > clientArea.width - m_titleHeight && y < m_titleHeight;
4834b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            } else {
4844b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              m_stateHover = x < m_titleHeight && y < m_titleHeight;
4854b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            }
4864b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            if (m_stateHover != oldStateHover) {
4874b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              redraw();
4884b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            }
4894b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            if (m_stateHover) {
4904b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              setCursor(null);
4914b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              return;
4924b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            }
4934b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
4944b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          // check for resize band
4954b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          if (isOpenExpanded()) {
4964b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            if (isWest() && x >= clientArea.width - RESIZE_WIDTH) {
4974b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              setCursor(ICursorConstants.SIZEWE);
4984b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            } else if (isEast() && x <= RESIZE_WIDTH) {
4994b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              setCursor(ICursorConstants.SIZEWE);
5004b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            } else if (isNorth() && y >= clientArea.height - RESIZE_WIDTH) {
5014b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              setCursor(ICursorConstants.SIZENS);
5024b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            } else if (isSouth() && y <= RESIZE_WIDTH) {
5034b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              setCursor(ICursorConstants.SIZENS);
5044b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            } else {
5054b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              setCursor(null);
5064b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            }
5074b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
5084b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          // check for docking
5094b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          if (getCursor() == null) {
5104b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            setCursor(ICursorConstants.SIZEALL);
5114b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
5124b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        } else {
5134b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          setCursor(null);
5144b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
5154b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
5164b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
5174b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
5184b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
5194b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * Handler for {@link SWT#MouseHover} event - temporary expands flyout and collapse again when
5204b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * mouse moves above client.
5214b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
5224b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private void handle_mouseHover() {
5234b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (m_preferences.getState() == IFlyoutPreferences.STATE_COLLAPSED && !m_stateHover) {
5244b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_preferences.setState(IFlyoutPreferences.STATE_EXPANDED);
5254b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        //
5264b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        final FlyoutControlComposite container = FlyoutControlComposite.this;
5274b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        container.layout();
5284b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        // BEGIN ADT MODIFICATIONS
5294b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (m_listener != null) {
5304b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            m_listener.stateChanged(IFlyoutPreferences.STATE_COLLAPSED,
5314b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                    IFlyoutPreferences.STATE_EXPANDED);
5324b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
5334b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        // END ADT MODIFICATIONS
5344b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        // add listeners
5354b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        Listener listener = new Listener() {
5364b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          @Override
5374b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        public void handleEvent(Event event) {
5384b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            if (event.type == SWT.Dispose) {
5394b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              getDisplay().removeFilter(SWT.MouseMove, this);
5404b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            } else {
5414b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              Point p = ((Control) event.widget).toDisplay(event.x, event.y);
5424b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              // during resize mouse can be temporary outside of flyout - ignore
5434b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              if (m_resize) {
5444b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                return;
5454b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              }
5464b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              // mouse in in flyout container - ignore
5474b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              if (getClientArea().contains(toControl(p.x, p.y))) {
5484b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                return;
5494b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              }
5504b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              // mouse is in full container - collapse
5514b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              if (container.getClientArea().contains(container.toControl(p.x, p.y))) {
5524b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                getDisplay().removeFilter(SWT.MouseMove, this);
5534b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                // it is possible, that user restored (OPEN) flyout, so collapse only if we still in expand state
5544b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                if (m_preferences.getState() == IFlyoutPreferences.STATE_EXPANDED) {
5554b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                  m_preferences.setState(IFlyoutPreferences.STATE_COLLAPSED);
5564b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                  container.layout();
5574b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                  // BEGIN ADT MODIFICATIONS
5584b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                  if (m_listener != null) {
5594b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                      m_listener.stateChanged(IFlyoutPreferences.STATE_EXPANDED,
5604b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                              IFlyoutPreferences.STATE_COLLAPSED);
5614b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                  }
5624b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                  // END ADT MODIFICATIONS
5634b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                }
5644b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              }
5654b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            }
5664b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
5674b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        };
5684b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        addListener(SWT.Dispose, listener);
5694b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        getDisplay().addFilter(SWT.MouseMove, listener);
5704b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
5714b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
5724b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
5734b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
5744b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * Handler for docking.
5754b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
5764b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private void handleDocking() {
5774b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      final FlyoutControlComposite container = FlyoutControlComposite.this;
5784b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      final int width = m_preferences.getWidth();
5794b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      final int oldDockLocation = getDockLocation();
5804b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      final int[] newDockLocation = new int[]{oldDockLocation};
5814b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      final Tracker dockingTracker = new Tracker(container, SWT.NONE);
5824b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      dockingTracker.setRectangles(new Rectangle[]{getBounds()});
5834b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      dockingTracker.setStippled(true);
5844b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      dockingTracker.addListener(SWT.Move, new Listener() {
5854b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        @Override
5864b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        public void handleEvent(Event event2) {
5874b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          Rectangle clientArea = container.getClientArea();
5884b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          Point location = container.toControl(event2.x, event2.y);
5894b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          int h3 = clientArea.height / 3;
5904b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          // check locations
5914b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          if (location.y < h3 && isValidDockLocation(IFlyoutPreferences.DOCK_NORTH)) {
5924b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            dockingTracker.setRectangles(new Rectangle[]{new Rectangle(0,
5934b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                0,
5944b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                clientArea.width,
5954b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                width)});
5964b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            newDockLocation[0] = IFlyoutPreferences.DOCK_NORTH;
5974b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          } else if (location.y > 2 * h3 && isValidDockLocation(IFlyoutPreferences.DOCK_SOUTH)) {
5984b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            dockingTracker.setRectangles(new Rectangle[]{new Rectangle(0,
5994b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                clientArea.height - width,
6004b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                clientArea.width,
6014b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                width)});
6024b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            newDockLocation[0] = IFlyoutPreferences.DOCK_SOUTH;
6034b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          } else if (location.x < clientArea.width / 2
6044b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              && isValidDockLocation(IFlyoutPreferences.DOCK_WEST)) {
6054b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            dockingTracker.setRectangles(new Rectangle[]{new Rectangle(0,
6064b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                0,
6074b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                width,
6084b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                clientArea.height)});
6094b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            newDockLocation[0] = IFlyoutPreferences.DOCK_WEST;
6104b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          } else if (isValidDockLocation(IFlyoutPreferences.DOCK_EAST)) {
6114b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            dockingTracker.setRectangles(new Rectangle[]{new Rectangle(clientArea.width - width,
6124b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                0,
6134b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                width,
6144b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye                clientArea.height)});
6154b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            newDockLocation[0] = IFlyoutPreferences.DOCK_EAST;
6164b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          } else {
6174b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            dockingTracker.setRectangles(new Rectangle[]{getBounds()});
6184b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            newDockLocation[0] = oldDockLocation;
6194b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
6204b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
6214b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      });
6224b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // start tracking
6234b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (dockingTracker.open()) {
6244b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        setDockLocation(newDockLocation[0]);
6254b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
6264b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // dispose tracker
6274b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      dockingTracker.dispose();
6284b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
6294b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
6304b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
6314b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
6324b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // Access
6334b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
6344b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
6354b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
6364b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * @return the {@link Control} installed on this {@link FlyoutControlComposite}, or
6374b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     *         <code>null</code> if there are no any {@link Control}.
6384b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
6394b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private Control getControl() {
6404b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      Control[] children = getChildren();
6414b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      return children.length == 1 ? children[0] : null;
6424b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
6434b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
6444b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
6454b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * Sets the text of title.
6464b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
6474b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    public void setTitleText(String text) {
6484b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      updateTitleImage(text);
6494b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
6504b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
6514b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
6524b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
6534b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // Layout
6544b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
6554b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
6564b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    @Override
6574b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    public void layout() {
6584b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      Control control = getControl();
6594b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (control == null) {
6604b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        return;
6614b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
6624b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // OK, we have control, so can continue layout
6634b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      Rectangle clientArea = getClientArea();
6644b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (isOpenExpanded()) {
6654b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (isWest()) {
6664b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          int y = m_titleHeight;
6674b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          control.setBounds(0, y, clientArea.width - RESIZE_WIDTH, clientArea.height - y);
6684b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        } else if (isEast()) {
6694b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          int y = m_titleHeight;
6704b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          control.setBounds(RESIZE_WIDTH, y, clientArea.width - RESIZE_WIDTH, clientArea.height - y);
6714b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        } else if (isNorth()) {
6724b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          int y = m_titleHeight;
6734b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          control.setBounds(0, y, clientArea.width, clientArea.height - y - RESIZE_WIDTH);
6744b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        } else if (isSouth()) {
6754b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          int y = RESIZE_WIDTH + m_titleHeight;
6764b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          control.setBounds(0, y, clientArea.width, clientArea.height - y);
6774b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
6784b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      } else {
6794b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        control.setBounds(0, 0, 0, 0);
6804b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
6814b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
6824b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
6834b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
6844b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
6854b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // Paint
6864b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
6874b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
6884b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private Image m_backImage;
6894b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
6904b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
6914b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * Handler for {@link SWT#Paint} event.
6924b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
6934b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private void handlePaint(GC paintGC) {
6944b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      Rectangle clientArea = getClientArea();
6954b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // prepare back image
6964b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      GC gc;
6974b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      {
6984b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (m_backImage == null || !m_backImage.getBounds().equals(clientArea)) {
6994b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          if (m_backImage != null) {
7004b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            m_backImage.dispose();
7014b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
7024b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          m_backImage = new Image(getDisplay(), clientArea.width, clientArea.height);
7034b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
7044b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        // prepare GC
7054b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        gc = new GC(m_backImage);
7064b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        gc.setBackground(paintGC.getBackground());
7074b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        gc.setForeground(paintGC.getForeground());
7084b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        gc.fillRectangle(clientArea);
7094b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
7104b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      //
7114b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (isOpenExpanded()) {
7124b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        // draw header
7134b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        {
7144b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          // draw title
7154b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          if (isWest()) {
7164b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            drawStateImage(gc, 0, 0);
7174b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            gc.drawImage(m_titleImage, m_titleHeight, 0);
7184b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          } else if (isEast()) {
7194b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            int x = clientArea.width - m_titleHeight;
7204b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            drawStateImage(gc, x, 0);
7214b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            gc.drawImage(m_titleImage, x - m_titleWidth, 0);
7224b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          } else if (isNorth()) {
7234b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            drawStateImage(gc, 0, 0);
7244b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            gc.drawImage(m_titleImage, m_titleHeight, 0);
7254b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          } else if (isSouth()) {
7264b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            int y = RESIZE_WIDTH;
7274b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            drawStateImage(gc, 0, y);
7284b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            gc.drawImage(m_titleImage, m_titleHeight, y);
7294b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
7304b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
7314b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        // draw resize band
7324b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        drawResizeBand(gc);
7334b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      } else {
7344b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (isHorizontal()) {
7354b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          drawStateImage(gc, 0, 0);
7364b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          gc.drawImage(m_titleImageRotated, 0, m_titleHeight);
7374b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        } else {
7384b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          drawStateImage(gc, 0, 0);
7394b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          gc.drawImage(m_titleImage, m_titleHeight, 0);
7404b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
7414b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        DrawUtils.drawHighlightRectangle(gc, 0, 0, clientArea.width, clientArea.height);
7424b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
7434b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // flush back image
7444b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      {
7454b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        gc.dispose();
7464b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        paintGC.drawImage(m_backImage, 0, 0);
7474b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
7484b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
7494b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
7504b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
7514b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * Draws the state image (arrow) at given location.
7524b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
7534b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private void drawStateImage(GC gc, int x, int y) {
7544b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      DrawUtils.drawImageCHCV(gc, getStateImage(), x, y, m_titleHeight, m_titleHeight);
7554b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (m_stateHover) {
7564b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        DrawUtils.drawHighlightRectangle(gc, x, y, m_titleHeight, m_titleHeight);
7574b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
7584b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
7594b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
7604b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
7614b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * @return the {@link Image} corresponding to current state (open or collapsed).
7624b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
7634b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private Image getStateImage() {
7644b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      int location = getDockLocation();
7654b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      int state = m_preferences.getState();
7664b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (state == IFlyoutPreferences.STATE_OPEN) {
7674b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        switch (location) {
7684b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          case IFlyoutPreferences.DOCK_WEST :
7694b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            return ARROW_LEFT;
7704b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          case IFlyoutPreferences.DOCK_EAST :
7714b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            return ARROW_RIGHT;
7724b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          case IFlyoutPreferences.DOCK_NORTH :
7734b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            return ARROW_TOP;
7744b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          case IFlyoutPreferences.DOCK_SOUTH :
7754b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            return ARROW_BOTTOM;
7764b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
7774b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      } else if (state == IFlyoutPreferences.STATE_EXPANDED) {
7784b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        return PIN;
7794b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      } else {
7804b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        switch (location) {
7814b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          case IFlyoutPreferences.DOCK_WEST :
7824b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            return ARROW_RIGHT;
7834b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          case IFlyoutPreferences.DOCK_EAST :
7844b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            return ARROW_LEFT;
7854b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          case IFlyoutPreferences.DOCK_NORTH :
7864b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            return ARROW_BOTTOM;
7874b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          case IFlyoutPreferences.DOCK_SOUTH :
7884b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            return ARROW_TOP;
7894b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
7904b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
7914b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      //
7924b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      return null;
7934b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
7944b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
7954b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
7964b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * Draws that resize band, {@link Sash} like.
7974b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
7984b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private void drawResizeBand(GC gc) {
7994b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      Rectangle clientArea = getClientArea();
8004b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // prepare locations
8014b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      int x, y, width, height;
8024b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (isHorizontal()) {
8034b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (isWest()) {
8044b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          x = clientArea.width - RESIZE_WIDTH;
8054b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        } else {
8064b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          x = 0;
8074b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
8084b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        y = 0;
8094b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        width = RESIZE_WIDTH;
8104b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        height = clientArea.height;
8114b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      } else {
8124b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        x = 0;
8134b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        if (isNorth()) {
8144b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          y = clientArea.height - RESIZE_WIDTH;
8154b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        } else {
8164b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          y = 0;
8174b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
8184b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        width = clientArea.width;
8194b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        height = RESIZE_WIDTH;
8204b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
8214b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // draw band
8224b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      DrawUtils.drawHighlightRectangle(gc, x, y, width, height);
8234b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
8244b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
8254b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
8264b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * @return <code>true</code> if flyout is open or expanded.
8274b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
8284b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private boolean isOpenExpanded() {
8294b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      int state = m_preferences.getState();
8304b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      return state == IFlyoutPreferences.STATE_OPEN || state == IFlyoutPreferences.STATE_EXPANDED;
8314b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
8324b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
8334b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
8344b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
8354b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // Title image
8364b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
8374b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
8384b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private int m_titleWidth;
8394b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private int m_titleHeight;
8404b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private Image m_titleImage;
8414b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private Image m_titleImageRotated;
8424b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
8434b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
8444b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * Creates {@link Image} for given title text.
8454b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
8464b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private void updateTitleImage(String text) {
8474b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // prepare size of text
8484b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      Point textSize;
8494b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      {
8504b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        GC gc = new GC(this);
8514b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        gc.setFont(TITLE_FONT);
8524b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        textSize = gc.textExtent(text);
8534b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        gc.dispose();
8544b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
8554b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // dispose existing image
8564b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      if (m_titleImage != null) {
8574b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_titleImage.dispose();
8584b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_titleImageRotated.dispose();
8594b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
8604b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // prepare new image
8614b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      {
8624b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_titleWidth = textSize.x + 2 * TITLE_LINES + 4 * TITLE_MARGIN;
8634b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_titleHeight = textSize.y;
8644b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        m_titleImage = new Image(getDisplay(), m_titleWidth, m_titleHeight);
8654b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        GC gc = new GC(m_titleImage);
8664b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        try {
8674b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          gc.setBackground(getBackground());
8684b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          gc.fillRectangle(0, 0, m_titleWidth, m_titleHeight);
8694b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          int x = 0;
8704b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          // draw left lines
8714b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          {
8724b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            x += TITLE_MARGIN;
8734b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            drawTitleLines(gc, x, m_titleHeight, TITLE_LINES);
8744b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            x += TITLE_LINES + TITLE_MARGIN;
8754b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
8764b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          // draw text
8774b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          {
8784b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            gc.setForeground(IColorConstants.black);
8794b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            gc.setFont(TITLE_FONT);
8804b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            gc.drawText(text, x, 0);
8814b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            x += textSize.x;
8824b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
8834b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          // draw right lines
8844b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          {
8854b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            x += TITLE_MARGIN;
8864b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            drawTitleLines(gc, x, m_titleHeight, TITLE_LINES);
8874b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
8884b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        } finally {
8894b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          gc.dispose();
8904b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
8914b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      }
8924b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // prepare rotated image
8934b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      m_titleImageRotated = DrawUtils.createRotatedImage(m_titleImage);
8944b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
8954b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
8964b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
8974b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * Draws two title lines.
8984b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
8994b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private void drawTitleLines(GC gc, int x, int height, int width) {
9004b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      drawTitleLine(gc, x, height / 3, width);
9014b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      drawTitleLine(gc, x, 2 * height / 3, width);
9024b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
9034b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
9044b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    /**
9054b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     * Draws single title line.
9064b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye     */
9074b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private void drawTitleLine(GC gc, int x, int y, int width) {
9084b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      int right = x + TITLE_LINES;
9094b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      //
9104b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      gc.setForeground(IColorConstants.buttonLightest);
9114b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      gc.drawLine(x, y, right - 2, y);
9124b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      gc.drawLine(x, y + 1, right - 2, y + 1);
9134b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      //
9144b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      gc.setForeground(IColorConstants.buttonDarker);
9154b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      gc.drawLine(right - 2, y, right - 1, y);
9164b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      gc.drawLine(x + 2, y + 1, right - 2, y + 1);
9174b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
9184b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
9194b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
9204b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
9214b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // Menu
9224b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
9234b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
9244b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private void configureMenu() {
9254b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      final MenuManager manager = new MenuManager();
9264b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      manager.setRemoveAllWhenShown(true);
9274b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      manager.addMenuListener(new IMenuListener() {
9284b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        @Override
9294b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        public void menuAboutToShow(IMenuManager menuMgr) {
9304b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          addDockActions();
9314b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          for (IFlyoutMenuContributor contributor : m_menuContributors) {
9324b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            contributor.contribute(manager);
9334b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
9344b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
9354b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
9364b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        private void addDockActions() {
9374b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          MenuManager dockManager = new MenuManager(Messages.FlyoutControlComposite_dockManager);
9384b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          addDockAction(
9394b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              dockManager,
9404b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              Messages.FlyoutControlComposite_dockLeft,
9414b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              IFlyoutPreferences.DOCK_WEST);
9424b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          addDockAction(
9434b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              dockManager,
9444b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              Messages.FlyoutControlComposite_dockRight,
9454b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              IFlyoutPreferences.DOCK_EAST);
9464b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          addDockAction(
9474b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              dockManager,
9484b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              Messages.FlyoutControlComposite_dockTop,
9494b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              IFlyoutPreferences.DOCK_NORTH);
9504b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          addDockAction(
9514b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              dockManager,
9524b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              Messages.FlyoutControlComposite_dockBottom,
9534b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye              IFlyoutPreferences.DOCK_SOUTH);
9544b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          manager.add(dockManager);
9554b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
9564b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
9574b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        private void addDockAction(MenuManager dockManager, String text, int location) {
9584b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          if ((m_validDockLocations & location) != 0) {
9594b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye            dockManager.add(new DockAction(text, location));
9604b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          }
9614b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
9624b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      });
9634b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // set menu
9644b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      setMenu(manager.createContextMenu(this));
9654b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      // dispose it later
9664b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      addDisposeListener(new DisposeListener() {
9674b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        @Override
9684b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        public void widgetDisposed(DisposeEvent e) {
9694b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye          manager.dispose();
9704b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye        }
9714b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      });
9724b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
9734b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
9744b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
9754b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
9764b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  // DockAction
9774b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  //
9784b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  ////////////////////////////////////////////////////////////////////////////
9794b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  private class DockAction extends Action {
9804b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    private final int m_location;
9814b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
9824b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
9834b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
9844b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // Constructor
9854b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
9864b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
9874b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    public DockAction(String text, int location) {
9884b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      super(text, AS_RADIO_BUTTON);
9894b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      m_location = location;
9904b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
9914b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
9924b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
9934b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
9944b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    // Action
9954b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    //
9964b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    ////////////////////////////////////////////////////////////////////////////
9974b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    @Override
9984b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    public boolean isChecked() {
9994b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      return getDockLocation() == m_location;
10004b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
10014b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye
10024b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    @Override
10034b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    public void run() {
10044b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye      setDockLocation(m_location);
10054b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye    }
10064b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye  }
10074b1a9d7baa71df312585022c22e8025fafaba95aTor Norbye}
1008