1765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye/*******************************************************************************
2765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Copyright (c) 2011 Google, Inc.
3765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * All rights reserved. This program and the accompanying materials
4765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * are made available under the terms of the Eclipse Public License v1.0
5765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * which accompanies this distribution, and is available at
6765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * http://www.eclipse.org/legal/epl-v10.html
7765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye *
8765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Contributors:
9765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye *    Google, Inc. - initial API and implementation
10765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye *******************************************************************************/
11765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyepackage org.eclipse.wb.internal.core.model.property.table;
12765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
13765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.SWT;
14765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.graphics.Point;
15765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.widgets.Control;
16765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.widgets.Display;
17765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.widgets.Event;
18765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.widgets.Listener;
19765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.swt.widgets.Shell;
20765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.wb.internal.core.EnvironmentUtils;
21765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.wb.internal.core.model.property.Property;
22765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.wb.internal.core.utils.ui.GridLayoutFactory;
23765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
24765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye/**
25765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Helper class for displaying tooltips.
26765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye *
27765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @author scheglov_ke
28765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @coverage core.model.property.table
29765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */
30765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeclass PropertyTableTooltipHelper implements IPropertyTooltipSite {
31765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private final PropertyTable m_table;
32765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private Shell m_tooltip;
33765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
34765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
35765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
36765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // Constructor
37765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
38765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
39765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  public PropertyTableTooltipHelper(PropertyTable table) {
40765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_table = table;
41765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_table.addListener(SWT.MouseHover, new Listener() {
42765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      @Override
43765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    public void handleEvent(Event event) {
44765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        if (event.stateMask == 0) {
45765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          showTooltip();
46765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        }
47765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
48765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    });
49765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_table.addListener(SWT.MouseExit, new Listener() {
50765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      @Override
51765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    public void handleEvent(Event event) {
52765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        // check, may be cursor is now on tooltip, so ignore this MouseExit
53765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        {
54765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          Control control = Display.getCurrent().getCursorControl();
55765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          while (control != null) {
56765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye            if (control == m_tooltip) {
57765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye              return;
58765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye            }
59765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye            control = control.getParent();
60765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye          }
61765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        }
62765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        // no, we should hide tooltip
63765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        hideTooltip();
64765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
65765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    });
66765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
67765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
68765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
69765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
70765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // Access
71765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
72765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
73765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private Property m_property;
74765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private boolean m_onTitle;
75765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private boolean m_onValue;
76765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private int m_beginX;
77765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private int m_endX;
78765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private int m_y;
79765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private int m_rowHeight;
80765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
81765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
82765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * {@link PropertyTable} call this method to inform that cursor location was changed.
83765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
84765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  public void update(Property property,
85765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      boolean onTitle,
86765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      boolean onValue,
87765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      int beginX,
88765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      int endX,
89765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      int y,
90765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      int rowHeight) {
91765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_property = property;
92765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_onTitle = onTitle;
93765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_onValue = onValue;
94765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_beginX = beginX;
95765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_endX = endX;
96765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_y = y;
97765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_rowHeight = rowHeight;
98765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
99765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
100765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
101765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
102765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // IPropertyTooltipSite
103765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
104765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
105765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  @Override
106765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyepublic PropertyTable getTable() {
107765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    return m_table;
108765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
109765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
110765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  @Override
111765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyepublic void hideTooltip() {
112765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    if (m_tooltip != null && !m_tooltip.isDisposed()) {
113765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_tooltip.dispose();
114765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
115765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    m_tooltip = null;
116765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
117765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
118765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
119765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
120765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // Showing tooltip
121765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
122765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
123765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private void showTooltip() {
124765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    hideTooltip();
125765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    // check for property
126765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    if (m_property == null) {
127765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      return;
128765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
129765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    //
130765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    if (m_onTitle) {
131765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      showTooltip(m_property.getAdapter(PropertyTooltipProvider.class), m_beginX, m_endX);
132765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
133765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    if (m_onValue) {
134765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      showTooltip(m_property.getEditor().getAdapter(PropertyTooltipProvider.class),
135765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye              m_beginX, m_endX);
136765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
137765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
138765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
139765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private void showTooltip(PropertyTooltipProvider provider, int startX, int endX) {
140765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (provider == null) {
141765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        return;
142765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
143765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    // create Shell
144765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    {
145765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_tooltip = new Shell(m_table.getShell(), SWT.NO_FOCUS | SWT.ON_TOP | SWT.TOOL | SWT.SINGLE);
146765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      configureColors(m_tooltip);
147765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      GridLayoutFactory.create(m_tooltip).noMargins();
148765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
149765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    // prepare control
150765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    Control control = provider.createTooltipControl(m_property, m_tooltip, endX - startX, this);
151765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    if (control == null) {
152765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      hideTooltip();
153765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      return;
154765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
155765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    // show Shell
156765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    {
157765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // prepare tooltip location
158765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      Point tooltipLocation;
159765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (provider.getTooltipPosition() == PropertyTooltipProvider.ON) {
160765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        tooltipLocation = m_table.toDisplay(new Point(startX, m_y));
161765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      } else {
162765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        tooltipLocation = m_table.toDisplay(new Point(startX, m_y + m_rowHeight));
163765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
164765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // set location/size and open
165765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_tooltip.setLocation(tooltipLocation.x, tooltipLocation.y);
166765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // for non-windows systems the tooltip may have invalid tooltip bounds
167765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // because some widget's API functions may fail if tooltip content is not visible
168765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // ex., on MacOSX tree widget's items has zero bounds since they are not yet visible.
169765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      // the workaround is to preset tooltip size to big values before any computeSize called.
170765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      if (!EnvironmentUtils.IS_WINDOWS) {
171765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye        m_tooltip.setSize(1000, 1000);
172765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      }
173765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      m_tooltip.setSize(m_tooltip.computeSize(SWT.DEFAULT, SWT.DEFAULT));
174765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye      provider.show(m_tooltip);
175765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    }
176765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
177765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye
178765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
179765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
180765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  // Utils
181765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  //
182765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  ////////////////////////////////////////////////////////////////////////////
183765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  /**
184765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   * Sets given {@link Control} correct background/foreground for tooltips.
185765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye   */
186765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  private void configureColors(Control control) {
187765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    Display display = Display.getCurrent();
188765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    control.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
189765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye    control.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
190765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye  }
191765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye}
192