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
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
14 *****************************************************************************/
15 package org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
;
17 import java
.util
.Iterator
;
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
;
42 * Handler for the tool tips in the generic time graph view.
45 * @author Alvaro Sanchez-Leon
46 * @author Patrick Tasse
48 public class TimeGraphTooltipHandler
{
50 private Shell _tipShell
;
51 private Table _tipTable
;
52 private Point _tipPosition
;
53 private final ITimeDataProvider _timeDataProvider
;
54 ITimeGraphPresentationProvider _utilImp
= null;
57 * Standard constructor
60 * The parent shell (unused, can be null)
62 * The presentation provider
66 public TimeGraphTooltipHandler(Shell parent
, ITimeGraphPresentationProvider rUtilImpl
,
67 ITimeDataProvider timeProv
) {
69 this._utilImp
= rUtilImpl
;
70 this._timeDataProvider
= timeProv
;
73 private void createTooltipShell(Shell parent
) {
74 final Display display
= parent
.getDisplay();
75 if (_tipShell
!= null && ! _tipShell
.isDisposed()) {
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
));
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);
96 _tipTable
.addMouseListener(new MouseAdapter() {
98 public void mouseDown(MouseEvent e
) {
103 _tipTable
.addMouseTrackListener(new MouseTrackAdapter() {
105 public void mouseExit(MouseEvent e
) {
110 _tipTable
.addMouseMoveListener(new MouseMoveListener() {
112 public void mouseMove(MouseEvent e
) {
119 * Callback for the mouse-over tooltip
122 * The control object to use
124 public void activateHoverHelp(final Control control
) {
125 control
.addMouseListener(new MouseAdapter() {
127 public void mouseDown(MouseEvent e
) {
128 if (_tipShell
!= null && ! _tipShell
.isDisposed()) {
134 control
.addMouseMoveListener(new MouseMoveListener() {
136 public void mouseMove(MouseEvent e
) {
137 if (_tipShell
!= null && ! _tipShell
.isDisposed()) {
143 control
.addMouseTrackListener(new MouseTrackAdapter() {
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
)) {
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
);
160 private void fillValues(Point pt
, TimeGraphControl timeGraphControl
, ITimeGraphEntry entry
) {
164 if (entry
.hasTimeEvents()) {
165 long currPixelTime
= timeGraphControl
.getTimeAtX(pt
.x
);
166 long nextPixelTime
= timeGraphControl
.getTimeAtX(pt
.x
+ 1);
167 if (nextPixelTime
== currPixelTime
) {
170 ITimeEvent currEvent
= Utils
.findEvent(entry
, currPixelTime
, 0);
171 ITimeEvent nextEvent
= Utils
.findEvent(entry
, currPixelTime
, 1);
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
;
183 String stateTypeName
= _utilImp
.getStateTypeName(entry
);
184 String entryName
= entry
.getName();
185 if (stateTypeName
== null) {
186 stateTypeName
= _utilImp
.getStateTypeName();
189 if (!entryName
.isEmpty()) {
190 addItem(stateTypeName
, entry
.getName());
193 if (currEvent
== null) {
198 String state
= _utilImp
.getEventName(currEvent
);
200 addItem(Messages
.TmfTimeTipHandler_TRACE_STATE
, state
);
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
));
212 long eventStartTime
= -1;
213 long eventDuration
= -1;
214 long eventEndTime
= -1;
216 eventStartTime
= currEvent
.getTime();
217 eventDuration
= currEvent
.getDuration();
218 if (eventDuration
< 0 && nextEvent
!= null) {
219 eventEndTime
= nextEvent
.getTime();
220 eventDuration
= eventEndTime
- eventStartTime
;
222 eventEndTime
= eventStartTime
+ eventDuration
;
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$
235 addItem(Messages
.TmfTimeTipHandler_TRACE_STOP_TIME
, eventEndTime
> -1 ?
236 Utils
.formatTime(eventEndTime
, TimeFormat
.ABSOLUTE
, res
)
237 : "?"); //$NON-NLS-1$
239 addItem(Messages
.TmfTimeTipHandler_TRACE_EVENT_TIME
, eventStartTime
> -1 ?
240 Utils
.formatTime(eventStartTime
, TimeFormat
.ABSOLUTE
, res
)
241 : "?"); //$NON-NLS-1$
244 if (eventDuration
> 0) {
245 addItem(Messages
.TmfTimeTipHandler_TRACE_START_TIME
, eventStartTime
> -1 ?
246 Utils
.formatTime(eventStartTime
, TimeFormat
.RELATIVE
, res
)
247 : "?"); //$NON-NLS-1$
249 addItem(Messages
.TmfTimeTipHandler_TRACE_STOP_TIME
, eventEndTime
> -1 ?
250 Utils
.formatTime(eventEndTime
, TimeFormat
.RELATIVE
, res
)
251 : "?"); //$NON-NLS-1$
253 addItem(Messages
.TmfTimeTipHandler_TRACE_EVENT_TIME
, eventStartTime
> -1 ?
254 Utils
.formatTime(eventStartTime
, TimeFormat
.RELATIVE
, res
)
255 : "?"); //$NON-NLS-1$
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$
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) {
279 _tipTable
.getColumn(0).pack();
280 _tipTable
.getColumn(1).pack();
282 _tipPosition
= control
.toDisplay(pt
);
284 setHoverLocation(_tipShell
, _tipPosition
);
285 _tipShell
.setVisible(true);
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;
296 shellBounds
.x
= Math
.max(Math
.min(position
.x
+ 16, displayBounds
.width
- shellBounds
.width
), 0);
298 if (position
.y
+ shellBounds
.height
+ 16 > displayBounds
.height
&& position
.y
- shellBounds
.height
- 16 >= 0) {
299 shellBounds
.y
= position
.y
- shellBounds
.height
- 16;
301 shellBounds
.y
= Math
.max(Math
.min(position
.y
+ 16, displayBounds
.height
- shellBounds
.height
), 0);
303 shell
.setBounds(shellBounds
);