1 /*****************************************************************************
2 * Copyright (c) 2007, 2013 Intel Corporation, 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
13 *****************************************************************************/
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
.model
.NullTimeEvent
;
25 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.Resolution
;
26 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.widgets
.Utils
.TimeFormat
;
27 import org
.eclipse
.swt
.SWT
;
28 import org
.eclipse
.swt
.events
.MouseAdapter
;
29 import org
.eclipse
.swt
.events
.MouseEvent
;
30 import org
.eclipse
.swt
.events
.MouseMoveListener
;
31 import org
.eclipse
.swt
.events
.MouseTrackAdapter
;
32 import org
.eclipse
.swt
.graphics
.Point
;
33 import org
.eclipse
.swt
.graphics
.Rectangle
;
34 import org
.eclipse
.swt
.layout
.GridData
;
35 import org
.eclipse
.swt
.layout
.GridLayout
;
36 import org
.eclipse
.swt
.widgets
.Composite
;
37 import org
.eclipse
.swt
.widgets
.Control
;
38 import org
.eclipse
.swt
.widgets
.Display
;
39 import org
.eclipse
.swt
.widgets
.Label
;
40 import org
.eclipse
.swt
.widgets
.Shell
;
43 * Handler for the tool tips in the generic time graph view.
46 * @author Alvaro Sanchez-Leon
47 * @author Patrick Tasse
49 public class TimeGraphTooltipHandler
{
51 private static final int OFFSET
= 16;
53 private Shell fTipShell
;
54 private Composite fTipComposite
;
55 private final ITimeDataProvider fTimeDataProvider
;
56 private ITimeGraphPresentationProvider fTimeGraphProvider
= null;
59 * Standard constructor
62 * The presentation provider
68 public TimeGraphTooltipHandler(ITimeGraphPresentationProvider graphProv
,
69 ITimeDataProvider timeProv
) {
71 this.fTimeGraphProvider
= graphProv
;
72 this.fTimeDataProvider
= timeProv
;
75 private void createTooltipShell(Shell parent
) {
76 final Display display
= parent
.getDisplay();
77 if (fTipShell
!= null && ! fTipShell
.isDisposed()) {
80 fTipShell
= new Shell(parent
, SWT
.ON_TOP
| SWT
.TOOL
);
81 GridLayout gridLayout
= new GridLayout();
82 gridLayout
.numColumns
= 2;
83 gridLayout
.marginWidth
= 2;
84 gridLayout
.marginHeight
= 2;
85 fTipShell
.setLayout(gridLayout
);
86 fTipShell
.setBackground(display
.getSystemColor(SWT
.COLOR_INFO_BACKGROUND
));
88 fTipComposite
= new Composite(fTipShell
, SWT
.NONE
);
89 fTipComposite
.setLayout(new GridLayout(3, false));
90 setupControl(fTipComposite
);
95 * Callback for the mouse-over tooltip
98 * The control object to use
100 public void activateHoverHelp(final Control control
) {
101 control
.addMouseListener(new MouseAdapter() {
103 public void mouseDown(MouseEvent e
) {
104 if (fTipShell
!= null && ! fTipShell
.isDisposed()) {
110 control
.addMouseMoveListener(new MouseMoveListener() {
112 public void mouseMove(MouseEvent e
) {
113 if (fTipShell
!= null && ! fTipShell
.isDisposed()) {
119 control
.addMouseTrackListener(new MouseTrackAdapter() {
121 public void mouseExit(MouseEvent e
) {
122 if (fTipShell
!= null && ! fTipShell
.isDisposed()) {
123 Point pt
= control
.toDisplay(e
.x
, e
.y
);
124 if (! fTipShell
.getBounds().contains(pt
)) {
130 private void addItem(String name
, String value
) {
131 Label nameLabel
= new Label(fTipComposite
, SWT
.NO_FOCUS
);
132 nameLabel
.setText(name
);
133 setupControl(nameLabel
);
134 Label separator
= new Label(fTipComposite
, SWT
.NO_FOCUS
| SWT
.SEPARATOR
| SWT
.VERTICAL
);
135 GridData gd
= new GridData(SWT
.CENTER
, SWT
.CENTER
, false, false);
136 gd
.heightHint
= nameLabel
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
).y
;
137 separator
.setLayoutData(gd
);
138 setupControl(separator
);
139 Label valueLabel
= new Label(fTipComposite
, SWT
.NO_FOCUS
);
140 valueLabel
.setText(value
);
141 setupControl(valueLabel
);
144 private void fillValues(Point pt
, TimeGraphControl timeGraphControl
, ITimeGraphEntry entry
) {
148 if (entry
.hasTimeEvents()) {
149 long currPixelTime
= timeGraphControl
.getTimeAtX(pt
.x
);
150 long nextPixelTime
= timeGraphControl
.getTimeAtX(pt
.x
+ 1);
151 if (nextPixelTime
== currPixelTime
) {
154 ITimeEvent currEvent
= Utils
.findEvent(entry
, currPixelTime
, 0);
155 ITimeEvent nextEvent
= Utils
.findEvent(entry
, currPixelTime
, 1);
157 // if there is no current event at the start of the current pixel range,
158 // or if the current event starts before the current pixel range,
159 // use the next event as long as it starts within the current pixel range
160 if ((currEvent
== null || currEvent
.getTime() < currPixelTime
) &&
161 (nextEvent
!= null && nextEvent
.getTime() < nextPixelTime
)) {
162 currEvent
= nextEvent
;
163 currPixelTime
= nextEvent
.getTime();
167 String stateTypeName
= fTimeGraphProvider
.getStateTypeName(entry
);
168 String entryName
= entry
.getName();
169 if (stateTypeName
== null) {
170 stateTypeName
= fTimeGraphProvider
.getStateTypeName();
173 if (!entryName
.isEmpty()) {
174 addItem(stateTypeName
, entry
.getName());
177 if (currEvent
== null || currEvent
instanceof NullTimeEvent
) {
182 String state
= fTimeGraphProvider
.getEventName(currEvent
);
184 addItem(Messages
.TmfTimeTipHandler_TRACE_STATE
, state
);
187 // This block receives a list of <String, String> values to be added to the tip table
188 Map
<String
, String
> eventAddOns
= fTimeGraphProvider
.getEventHoverToolTipInfo(currEvent
, currPixelTime
);
189 if (eventAddOns
!= null) {
190 for (Iterator
<String
> iter
= eventAddOns
.keySet().iterator(); iter
.hasNext();) {
191 String message
= iter
.next();
192 addItem(message
, eventAddOns
.get(message
));
195 if (fTimeGraphProvider
.displayTimesInTooltip()) {
196 long eventStartTime
= -1;
197 long eventDuration
= -1;
198 long eventEndTime
= -1;
200 eventStartTime
= currEvent
.getTime();
201 eventDuration
= currEvent
.getDuration();
202 if (eventDuration
< 0 && nextEvent
!= null) {
203 eventEndTime
= nextEvent
.getTime();
204 eventDuration
= eventEndTime
- eventStartTime
;
206 eventEndTime
= eventStartTime
+ eventDuration
;
209 Resolution res
= Resolution
.NANOSEC
;
210 TimeFormat tf
= fTimeDataProvider
.getTimeFormat();
211 if (tf
== TimeFormat
.CALENDAR
) {
212 addItem(Messages
.TmfTimeTipHandler_TRACE_DATE
, eventStartTime
> -1 ?
213 Utils
.formatDate(eventStartTime
)
214 : "?"); //$NON-NLS-1$
216 if (eventDuration
> 0) {
217 addItem(Messages
.TmfTimeTipHandler_TRACE_START_TIME
, eventStartTime
> -1 ?
218 Utils
.formatTime(eventStartTime
, tf
, res
)
219 : "?"); //$NON-NLS-1$
221 addItem(Messages
.TmfTimeTipHandler_TRACE_STOP_TIME
, eventEndTime
> -1 ?
222 Utils
.formatTime(eventEndTime
, tf
, res
)
223 : "?"); //$NON-NLS-1$
225 addItem(Messages
.TmfTimeTipHandler_TRACE_EVENT_TIME
, eventStartTime
> -1 ?
226 Utils
.formatTime(eventStartTime
, tf
, res
)
227 : "?"); //$NON-NLS-1$
230 if (eventDuration
> 0) {
231 // Duration in relative format in any case
232 if (tf
== TimeFormat
.CALENDAR
) {
233 tf
= TimeFormat
.RELATIVE
;
235 addItem(Messages
.TmfTimeTipHandler_DURATION
, eventDuration
> -1 ?
236 Utils
.formatTime(eventDuration
, tf
, res
)
237 : "?"); //$NON-NLS-1$
244 public void mouseHover(MouseEvent event
) {
245 if ((event
.stateMask
& SWT
.BUTTON_MASK
) != 0) {
248 Point pt
= new Point(event
.x
, event
.y
);
249 TimeGraphControl timeGraphControl
= (TimeGraphControl
) event
.widget
;
250 createTooltipShell(timeGraphControl
.getShell());
251 ITimeGraphEntry entry
= timeGraphControl
.getEntry(pt
);
252 for (Control child
: fTipComposite
.getChildren()) {
255 fillValues(pt
, timeGraphControl
, entry
);
256 if (fTipComposite
.getChildren().length
== 0) {
260 Point tipPosition
= control
.toDisplay(pt
);
262 setHoverLocation(fTipShell
, tipPosition
);
263 fTipShell
.setVisible(true);
268 private static void setHoverLocation(Shell shell
, Point position
) {
269 Rectangle displayBounds
= shell
.getDisplay().getBounds();
270 Rectangle shellBounds
= shell
.getBounds();
271 if (position
.x
+ shellBounds
.width
+ OFFSET
> displayBounds
.width
&& position
.x
- shellBounds
.width
- OFFSET
>= 0) {
272 shellBounds
.x
= position
.x
- shellBounds
.width
- OFFSET
;
274 shellBounds
.x
= Math
.max(Math
.min(position
.x
+ OFFSET
, displayBounds
.width
- shellBounds
.width
), 0);
276 if (position
.y
+ shellBounds
.height
+ OFFSET
> displayBounds
.height
&& position
.y
- shellBounds
.height
- OFFSET
>= 0) {
277 shellBounds
.y
= position
.y
- shellBounds
.height
- OFFSET
;
279 shellBounds
.y
= Math
.max(Math
.min(position
.y
+ OFFSET
, displayBounds
.height
- shellBounds
.height
), 0);
281 shell
.setBounds(shellBounds
);
284 private void setupControl(Control control
) {
285 control
.setForeground(fTipShell
.getDisplay().getSystemColor(SWT
.COLOR_INFO_FOREGROUND
));
286 control
.setBackground(fTipShell
.getDisplay().getSystemColor(SWT
.COLOR_INFO_BACKGROUND
));
288 control
.addMouseListener(new MouseAdapter() {
290 public void mouseDown(MouseEvent e
) {
295 control
.addMouseTrackListener(new MouseTrackAdapter() {
297 public void mouseExit(MouseEvent e
) {
302 control
.addMouseMoveListener(new MouseMoveListener() {
304 public void mouseMove(MouseEvent e
) {