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