Merge branch 'master' into lttng-kepler
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / widgets / timegraph / widgets / TimeGraphTooltipHandler.java
1 /*****************************************************************************
2 * Copyright (c) 2007 Intel Corporation, 2009, 2012 Ericsson.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Intel Corporation - Initial API and implementation
10 * Vitaly A. Provodin, Intel - Initial API and implementation
11 * Alvaro Sanchez-Leon - Updated for TMF
12 * Patrick Tasse - Refactoring
13 *
14 *****************************************************************************/
15 package org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets;
16
17 import java.util.Iterator;
18 import java.util.Map;
19
20 import org.eclipse.linuxtools.internal.tmf.ui.Messages;
21 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider;
22 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
23 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
24 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.Resolution;
25 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
26 import org.eclipse.swt.SWT;
27 import org.eclipse.swt.events.MouseAdapter;
28 import org.eclipse.swt.events.MouseEvent;
29 import org.eclipse.swt.events.MouseMoveListener;
30 import org.eclipse.swt.events.MouseTrackAdapter;
31 import org.eclipse.swt.graphics.Point;
32 import org.eclipse.swt.graphics.Rectangle;
33 import org.eclipse.swt.layout.GridLayout;
34 import org.eclipse.swt.widgets.Control;
35 import org.eclipse.swt.widgets.Display;
36 import org.eclipse.swt.widgets.Shell;
37 import org.eclipse.swt.widgets.Table;
38 import org.eclipse.swt.widgets.TableColumn;
39 import org.eclipse.swt.widgets.TableItem;
40
41 /**
42 * Handler for the tool tips in the generic time graph view.
43 *
44 * @version 1.0
45 * @author Alvaro Sanchez-Leon
46 * @author Patrick Tasse
47 */
48 public class TimeGraphTooltipHandler {
49
50 private Shell _tipShell;
51 private Table _tipTable;
52 private Point _tipPosition;
53 private final ITimeDataProvider _timeDataProvider;
54 ITimeGraphPresentationProvider _utilImp = null;
55
56 /**
57 * Standard constructor
58 *
59 * @param parent
60 * The parent shell (unused, can be null)
61 * @param rUtilImpl
62 * The presentation provider
63 * @param timeProv
64 * The time provider
65 */
66 public TimeGraphTooltipHandler(Shell parent, ITimeGraphPresentationProvider rUtilImpl,
67 ITimeDataProvider timeProv) {
68
69 this._utilImp = rUtilImpl;
70 this._timeDataProvider = timeProv;
71 }
72
73 private void createTooltipShell(Shell parent) {
74 final Display display = parent.getDisplay();
75 if (_tipShell != null && ! _tipShell.isDisposed()) {
76 _tipShell.dispose();
77 }
78 _tipShell = new Shell(parent, SWT.ON_TOP | SWT.TOOL);
79 GridLayout gridLayout = new GridLayout();
80 gridLayout.numColumns = 2;
81 gridLayout.marginWidth = 2;
82 gridLayout.marginHeight = 2;
83 _tipShell.setLayout(gridLayout);
84 _tipShell.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
85
86 _tipTable = new Table(_tipShell, SWT.NONE);
87 new TableColumn(_tipTable, SWT.NONE);
88 new TableColumn(_tipTable, SWT.NONE);
89 _tipTable.setForeground(display
90 .getSystemColor(SWT.COLOR_INFO_FOREGROUND));
91 _tipTable.setBackground(display
92 .getSystemColor(SWT.COLOR_INFO_BACKGROUND));
93 _tipTable.setHeaderVisible(false);
94 _tipTable.setLinesVisible(false);
95
96 _tipTable.addMouseListener(new MouseAdapter() {
97 @Override
98 public void mouseDown(MouseEvent e) {
99 _tipShell.dispose();
100 }
101 });
102
103 _tipTable.addMouseTrackListener(new MouseTrackAdapter() {
104 @Override
105 public void mouseExit(MouseEvent e) {
106 _tipShell.dispose();
107 }
108 });
109
110 _tipTable.addMouseMoveListener(new MouseMoveListener() {
111 @Override
112 public void mouseMove(MouseEvent e) {
113 _tipShell.dispose();
114 }
115 });
116 }
117
118 /**
119 * Callback for the mouse-over tooltip
120 *
121 * @param control
122 * The control object to use
123 */
124 public void activateHoverHelp(final Control control) {
125 control.addMouseListener(new MouseAdapter() {
126 @Override
127 public void mouseDown(MouseEvent e) {
128 if (_tipShell != null && ! _tipShell.isDisposed()) {
129 _tipShell.dispose();
130 }
131 }
132 });
133
134 control.addMouseMoveListener(new MouseMoveListener() {
135 @Override
136 public void mouseMove(MouseEvent e) {
137 if (_tipShell != null && ! _tipShell.isDisposed()) {
138 _tipShell.dispose();
139 }
140 }
141 });
142
143 control.addMouseTrackListener(new MouseTrackAdapter() {
144 @Override
145 public void mouseExit(MouseEvent e) {
146 if (_tipShell != null && ! _tipShell.isDisposed()) {
147 Point pt = control.toDisplay(e.x, e.y);
148 if (! _tipShell.getBounds().contains(pt)) {
149 _tipShell.dispose();
150 }
151 }
152 }
153
154 private void addItem(String name, String value) {
155 TableItem line = new TableItem(_tipTable, SWT.NONE);
156 line.setText(0, name);
157 line.setText(1, value);
158 }
159
160 private void fillValues(Point pt, TimeGraphControl timeGraphControl, ITimeGraphEntry entry) {
161 if (entry == null) {
162 return;
163 }
164 if (entry.hasTimeEvents()) {
165 long currPixelTime = timeGraphControl.getTimeAtX(pt.x);
166 long nextPixelTime = timeGraphControl.getTimeAtX(pt.x + 1);
167 if (nextPixelTime == currPixelTime) {
168 nextPixelTime++;
169 }
170 ITimeEvent currEvent = Utils.findEvent(entry, currPixelTime, 0);
171 ITimeEvent nextEvent = Utils.findEvent(entry, currPixelTime, 1);
172
173 // if there is no current event at the start of the current pixel range,
174 // or if the current event starts before the current pixel range,
175 // use the next event as long as it starts within the current pixel range
176 if (currEvent == null || currEvent.getTime() < currPixelTime) {
177 if (nextEvent != null && nextEvent.getTime() < nextPixelTime) {
178 currEvent = nextEvent;
179 }
180 }
181
182 // state name
183 String stateTypeName = _utilImp.getStateTypeName(entry);
184 String entryName = entry.getName();
185 if (stateTypeName == null) {
186 stateTypeName = _utilImp.getStateTypeName();
187 }
188
189 if (!entryName.isEmpty()) {
190 addItem(stateTypeName, entry.getName());
191 }
192
193 if (currEvent == null) {
194 return;
195 }
196
197 // state
198 String state = _utilImp.getEventName(currEvent);
199 if (state != null) {
200 addItem(Messages.TmfTimeTipHandler_TRACE_STATE, state);
201 }
202
203 // This block receives a list of <String, String> values to be added to the tip table
204 Map<String, String> eventAddOns = _utilImp.getEventHoverToolTipInfo(currEvent);
205 if (eventAddOns != null) {
206 for (Iterator<String> iter = eventAddOns.keySet().iterator(); iter.hasNext();) {
207 String message = iter.next();
208 addItem(message, eventAddOns.get(message));
209 }
210 }
211
212 long eventStartTime = -1;
213 long eventDuration = -1;
214 long eventEndTime = -1;
215
216 eventStartTime = currEvent.getTime();
217 eventDuration = currEvent.getDuration();
218 if (eventDuration < 0 && nextEvent != null) {
219 eventEndTime = nextEvent.getTime();
220 eventDuration = eventEndTime - eventStartTime;
221 } else {
222 eventEndTime = eventStartTime + eventDuration;
223 }
224
225 Resolution res = Resolution.NANOSEC;
226 if (_timeDataProvider.isCalendarFormat()) {
227 addItem(Messages.TmfTimeTipHandler_TRACE_DATE, eventStartTime > -1 ?
228 Utils.formatDate(eventStartTime)
229 : "?"); //$NON-NLS-1$
230 if (eventDuration > 0) {
231 addItem(Messages.TmfTimeTipHandler_TRACE_START_TIME, eventStartTime > -1 ?
232 Utils.formatTime(eventStartTime, TimeFormat.ABSOLUTE, res)
233 : "?"); //$NON-NLS-1$
234
235 addItem(Messages.TmfTimeTipHandler_TRACE_STOP_TIME, eventEndTime > -1 ?
236 Utils.formatTime(eventEndTime, TimeFormat.ABSOLUTE, res)
237 : "?"); //$NON-NLS-1$
238 } else {
239 addItem(Messages.TmfTimeTipHandler_TRACE_EVENT_TIME, eventStartTime > -1 ?
240 Utils.formatTime(eventStartTime, TimeFormat.ABSOLUTE, res)
241 : "?"); //$NON-NLS-1$
242 }
243 } else {
244 if (eventDuration > 0) {
245 addItem(Messages.TmfTimeTipHandler_TRACE_START_TIME, eventStartTime > -1 ?
246 Utils.formatTime(eventStartTime, TimeFormat.RELATIVE, res)
247 : "?"); //$NON-NLS-1$
248
249 addItem(Messages.TmfTimeTipHandler_TRACE_STOP_TIME, eventEndTime > -1 ?
250 Utils.formatTime(eventEndTime, TimeFormat.RELATIVE, res)
251 : "?"); //$NON-NLS-1$
252 } else {
253 addItem(Messages.TmfTimeTipHandler_TRACE_EVENT_TIME, eventStartTime > -1 ?
254 Utils.formatTime(eventStartTime, TimeFormat.RELATIVE, res)
255 : "?"); //$NON-NLS-1$
256 }
257 }
258
259 if (eventDuration > 0) {
260 // Duration in relative format in any case
261 addItem(Messages.TmfTimeTipHandler_DURATION, eventDuration > -1 ?
262 Utils.formatTime(eventDuration, TimeFormat.RELATIVE, res)
263 : "?"); //$NON-NLS-1$
264 }
265 }
266 }
267
268 @Override
269 public void mouseHover(MouseEvent event) {
270 Point pt = new Point(event.x, event.y);
271 TimeGraphControl timeGraphControl = (TimeGraphControl) event.widget;
272 createTooltipShell(timeGraphControl.getShell());
273 ITimeGraphEntry entry = timeGraphControl.getEntry(pt);
274 _tipTable.remove(0, _tipTable.getItemCount() - 1);
275 fillValues(pt, timeGraphControl, entry);
276 if (_tipTable.getItemCount() == 0) {
277 return;
278 }
279 _tipTable.getColumn(0).pack();
280 _tipTable.getColumn(1).pack();
281 _tipShell.pack();
282 _tipPosition = control.toDisplay(pt);
283 _tipShell.pack();
284 setHoverLocation(_tipShell, _tipPosition);
285 _tipShell.setVisible(true);
286 }
287 });
288 }
289
290 private static void setHoverLocation(Shell shell, Point position) {
291 Rectangle displayBounds = shell.getDisplay().getBounds();
292 Rectangle shellBounds = shell.getBounds();
293 if (position.x + shellBounds.width + 16 > displayBounds.width && position.x - shellBounds.width - 16 >= 0) {
294 shellBounds.x = position.x - shellBounds.width - 16;
295 } else {
296 shellBounds.x = Math.max(Math.min(position.x + 16, displayBounds.width - shellBounds.width), 0);
297 }
298 if (position.y + shellBounds.height + 16 > displayBounds.height && position.y - shellBounds.height - 16 >= 0) {
299 shellBounds.y = position.y - shellBounds.height - 16;
300 } else {
301 shellBounds.y = Math.max(Math.min(position.y + 16, displayBounds.height - shellBounds.height), 0);
302 }
303 shell.setBounds(shellBounds);
304 }
305
306 }
This page took 0.038734 seconds and 6 git commands to generate.