-/*****************************************************************************\r
- * Copyright (c) 2007 Intel Corporation, 2009, 2012 Ericsson.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * Intel Corporation - Initial API and implementation\r
- * Vitaly A. Provodin, Intel - Initial API and implementation\r
- * Alvaro Sanchez-Leon - Updated for TMF\r
- * Patrick Tasse - Refactoring\r
- *\r
- *****************************************************************************/\r
-package org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets;\r
-\r
-import java.util.Iterator;\r
-import java.util.Map;\r
-\r
-import org.eclipse.linuxtools.internal.tmf.ui.Messages;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.Resolution;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.events.MouseAdapter;\r
-import org.eclipse.swt.events.MouseEvent;\r
-import org.eclipse.swt.events.MouseMoveListener;\r
-import org.eclipse.swt.events.MouseTrackAdapter;\r
-import org.eclipse.swt.graphics.Point;\r
-import org.eclipse.swt.graphics.Rectangle;\r
-import org.eclipse.swt.layout.GridData;\r
-import org.eclipse.swt.layout.GridLayout;\r
-import org.eclipse.swt.widgets.Control;\r
-import org.eclipse.swt.widgets.Display;\r
-import org.eclipse.swt.widgets.Shell;\r
-import org.eclipse.swt.widgets.Table;\r
-import org.eclipse.swt.widgets.TableColumn;\r
-import org.eclipse.swt.widgets.TableItem;\r
-\r
-\r
-public class TimeGraphTooltipHandler {\r
-\r
- private Shell _tipShell;\r
- private Table _tipTable;\r
- private Point _tipPosition;\r
- private ITimeDataProvider _timeDataProvider;\r
- ITimeGraphPresentationProvider _utilImp = null;\r
-\r
- public TimeGraphTooltipHandler(Shell parent, ITimeGraphPresentationProvider rUtilImpl,\r
- ITimeDataProvider timeProv) {\r
- final Display display = parent.getDisplay();\r
-\r
- this._utilImp = rUtilImpl;\r
- this._timeDataProvider = timeProv;\r
- _tipShell = new Shell(parent, SWT.ON_TOP | SWT.TOOL);\r
- GridLayout gridLayout = new GridLayout();\r
- gridLayout.numColumns = 2;\r
- gridLayout.marginWidth = 2;\r
- gridLayout.marginHeight = 2;\r
- _tipShell.setLayout(gridLayout);\r
- GridData data = new GridData(GridData.BEGINNING, GridData.BEGINNING,\r
- true, true);\r
- _tipShell.setLayoutData(data);\r
- _tipShell.setBackground(display\r
- .getSystemColor(SWT.COLOR_INFO_BACKGROUND));\r
-\r
- _tipTable = new Table(_tipShell, SWT.NONE);\r
- new TableColumn(_tipTable, SWT.NONE);\r
- new TableColumn(_tipTable, SWT.NONE);\r
- _tipTable.setForeground(display\r
- .getSystemColor(SWT.COLOR_INFO_FOREGROUND));\r
- _tipTable.setBackground(display\r
- .getSystemColor(SWT.COLOR_INFO_BACKGROUND));\r
- _tipTable.setHeaderVisible(false);\r
- _tipTable.setLinesVisible(false);\r
-\r
- // tipTable.setLayoutData(new GridData(GridData.FILL_HORIZONTAL\r
- // | GridData.VERTICAL_ALIGN_CENTER));\r
- }\r
-\r
- public void activateHoverHelp(final Control control) {\r
- //FIXME: remove old listeners\r
- control.addMouseListener(new MouseAdapter() {\r
- @Override\r
- public void mouseDown(MouseEvent e) {\r
- if (_tipShell.isVisible()) {\r
- _tipShell.setVisible(false);\r
- }\r
- }\r
- });\r
-\r
- control.addMouseMoveListener(new MouseMoveListener() {\r
- @Override\r
- public void mouseMove(MouseEvent e) {\r
- if (_tipShell.isVisible()) {\r
- _tipShell.setVisible(false);\r
- }\r
- }\r
- });\r
-\r
- control.addMouseTrackListener(new MouseTrackAdapter() {\r
- @Override\r
- public void mouseExit(MouseEvent e) {\r
- if (_tipShell.isVisible()) {\r
- _tipShell.setVisible(false);\r
- }\r
- }\r
-\r
- private void addItem(String name, String value) {\r
- TableItem line = new TableItem(_tipTable, SWT.NONE);\r
- line.setText(0, name);\r
- line.setText(1, value);\r
- }\r
-\r
- private void fillValues(Point pt, TimeGraphControl threadStates, ITimeGraphEntry entry) {\r
- if (entry == null) {\r
- return;\r
- }\r
- if (entry.hasTimeEvents()) {\r
- ITimeEvent threadEvent = Utils.findEvent(entry, threadStates.getTimeAtX(pt.x), 2);\r
- ITimeEvent nextEvent = Utils.findEvent(entry, threadStates.getTimeAtX(pt.x), 1);\r
- // state name\r
- addItem(_utilImp.getStateTypeName(), entry.getName());\r
- if (threadEvent == null) {\r
- return;\r
- }\r
- // thread state\r
- String state = _utilImp.getEventName(threadEvent);\r
- if (state != null) {\r
- addItem(Messages.TmfTimeTipHandler_TRACE_STATE, state);\r
- }\r
-\r
- // This block receives a\r
- // list of <String, String> values to be added to the tip\r
- // table\r
- Map<String, String> eventAddOns = _utilImp.getEventHoverToolTipInfo(threadEvent);\r
- if (eventAddOns != null) {\r
- for (Iterator<String> iter = eventAddOns.keySet().iterator(); iter.hasNext();) {\r
- String message = (String) iter.next();\r
- addItem(message, eventAddOns.get(message));\r
- }\r
- }\r
-\r
- long eventStartTime = -1;\r
- long eventDuration = -1;\r
- long eventEndTime = -1;\r
-\r
- if (threadEvent != null) {\r
- eventStartTime = threadEvent.getTime();\r
- eventDuration = threadEvent.getDuration();\r
- if (eventDuration < 0 && nextEvent != null) {\r
- eventEndTime = nextEvent.getTime();\r
- eventDuration = eventEndTime - eventStartTime;\r
- } else {\r
- eventEndTime = eventStartTime + eventDuration;\r
- }\r
- }\r
-\r
- // TODO: Check if we need "format" \r
- // TimeFormat format = TimeFormat.RELATIVE;\r
- Resolution res = Resolution.NANOSEC;\r
- if (_timeDataProvider.isCalendarFormat()) {\r
- // format = TimeFormat.ABSOLUTE; // Absolute format\r
- // // (calendar)\r
- // Add Date\r
- addItem(Messages.TmfTimeTipHandler_TRACE_DATE, eventStartTime > -1 ?\r
- Utils.formatDate(eventStartTime)\r
- : "?"); //$NON-NLS-1$\r
- if (eventDuration > 0) {\r
- addItem(Messages.TmfTimeTipHandler_TRACE_START_TIME, eventStartTime > -1 ?\r
- Utils.formatTime(eventStartTime, TimeFormat.ABSOLUTE, res)\r
- : "?"); //$NON-NLS-1$\r
-\r
- addItem(Messages.TmfTimeTipHandler_TRACE_STOP_TIME, eventEndTime > -1 ?\r
- Utils.formatTime(eventEndTime, TimeFormat.ABSOLUTE, res)\r
- : "?"); //$NON-NLS-1$\r
- } else {\r
- addItem(Messages.TmfTimeTipHandler_TRACE_EVENT_TIME, eventStartTime > -1 ?\r
- Utils.formatTime(eventStartTime, TimeFormat.ABSOLUTE, res)\r
- : "?"); //$NON-NLS-1$\r
- }\r
- } else {\r
- if (eventDuration > 0) {\r
- addItem(Messages.TmfTimeTipHandler_TRACE_START_TIME, eventStartTime > -1 ?\r
- Utils.formatTime(eventStartTime, TimeFormat.RELATIVE, res)\r
- : "?"); //$NON-NLS-1$\r
-\r
- addItem(Messages.TmfTimeTipHandler_TRACE_STOP_TIME, eventEndTime > -1 ?\r
- Utils.formatTime(eventEndTime, TimeFormat.RELATIVE, res)\r
- : "?"); //$NON-NLS-1$\r
- } else {\r
- addItem(Messages.TmfTimeTipHandler_TRACE_EVENT_TIME, eventStartTime > -1 ?\r
- Utils.formatTime(eventStartTime, TimeFormat.RELATIVE, res)\r
- : "?"); //$NON-NLS-1$\r
- }\r
- }\r
-\r
- if (eventDuration > 0) {\r
- // Duration in relative format in any case\r
- addItem(Messages.TmfTimeTipHandler_DURATION, eventDuration > -1 ?\r
- Utils.formatTime(eventDuration, TimeFormat.RELATIVE, res)\r
- : "?"); //$NON-NLS-1$\r
- }\r
- }\r
- }\r
-\r
- @Override\r
- public void mouseHover(MouseEvent event) {\r
- Point pt = new Point(event.x, event.y);\r
- TimeGraphControl threadStates = (TimeGraphControl) event.widget;\r
- ITimeGraphEntry entry = threadStates.getEntry(pt);\r
- _tipTable.remove(0, _tipTable.getItemCount() - 1);\r
- fillValues(pt, threadStates, entry);\r
- if (_tipTable.getItemCount() == 0) {\r
- return;\r
- }\r
- _tipTable.getColumn(0).pack();\r
- _tipTable.getColumn(1).pack();\r
- _tipShell.pack();\r
- _tipPosition = control.toDisplay(pt);\r
- _tipShell.pack();\r
- setHoverLocation(_tipShell, _tipPosition);\r
- _tipShell.setVisible(true);\r
- }\r
- });\r
- }\r
-\r
- private void setHoverLocation(Shell shell, Point position) {\r
- Rectangle displayBounds = shell.getDisplay().getBounds();\r
- Rectangle shellBounds = shell.getBounds();\r
- shellBounds.x = Math.max(Math.min(position.x, displayBounds.width\r
- - shellBounds.width), 0);\r
- shellBounds.y = Math.max(Math.min(position.y + 16, displayBounds.height\r
- - shellBounds.height), 0);\r
- shell.setBounds(shellBounds);\r
- }\r
-\r
+/*****************************************************************************
+ * Copyright (c) 2007, 2013 Intel Corporation, Ericsson
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Intel Corporation - Initial API and implementation
+ * Vitaly A. Provodin, Intel - Initial API and implementation
+ * Alvaro Sanchez-Leon - Updated for TMF
+ * Patrick Tasse - Refactoring
+ *****************************************************************************/
+
+package org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.linuxtools.internal.tmf.ui.Messages;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.Resolution;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.MouseTrackAdapter;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Handler for the tool tips in the generic time graph view.
+ *
+ * @version 1.0
+ * @author Alvaro Sanchez-Leon
+ * @author Patrick Tasse
+ */
+public class TimeGraphTooltipHandler {
+
+ private Shell _tipShell;
+ private Composite _tipComposite;
+ private Point _tipPosition;
+ private final ITimeDataProvider _timeDataProvider;
+ ITimeGraphPresentationProvider _utilImp = null;
+
+ /**
+ * Standard constructor
+ *
+ * @param parent
+ * The parent shell (unused, can be null)
+ * @param rUtilImpl
+ * The presentation provider
+ * @param timeProv
+ * The time provider
+ */
+ public TimeGraphTooltipHandler(Shell parent, ITimeGraphPresentationProvider rUtilImpl,
+ ITimeDataProvider timeProv) {
+
+ this._utilImp = rUtilImpl;
+ this._timeDataProvider = timeProv;
+ }
+
+ private void createTooltipShell(Shell parent) {
+ final Display display = parent.getDisplay();
+ if (_tipShell != null && ! _tipShell.isDisposed()) {
+ _tipShell.dispose();
+ }
+ _tipShell = new Shell(parent, SWT.ON_TOP | SWT.TOOL);
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.numColumns = 2;
+ gridLayout.marginWidth = 2;
+ gridLayout.marginHeight = 2;
+ _tipShell.setLayout(gridLayout);
+ _tipShell.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+
+ _tipComposite = new Composite(_tipShell, SWT.NONE);
+ _tipComposite.setLayout(new GridLayout(3, false));
+ setupControl(_tipComposite);
+
+ }
+
+ /**
+ * Callback for the mouse-over tooltip
+ *
+ * @param control
+ * The control object to use
+ */
+ public void activateHoverHelp(final Control control) {
+ control.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ if (_tipShell != null && ! _tipShell.isDisposed()) {
+ _tipShell.dispose();
+ }
+ }
+ });
+
+ control.addMouseMoveListener(new MouseMoveListener() {
+ @Override
+ public void mouseMove(MouseEvent e) {
+ if (_tipShell != null && ! _tipShell.isDisposed()) {
+ _tipShell.dispose();
+ }
+ }
+ });
+
+ control.addMouseTrackListener(new MouseTrackAdapter() {
+ @Override
+ public void mouseExit(MouseEvent e) {
+ if (_tipShell != null && ! _tipShell.isDisposed()) {
+ Point pt = control.toDisplay(e.x, e.y);
+ if (! _tipShell.getBounds().contains(pt)) {
+ _tipShell.dispose();
+ }
+ }
+ }
+
+ private void addItem(String name, String value) {
+ Label nameLabel = new Label(_tipComposite, SWT.NO_FOCUS);
+ nameLabel.setText(name);
+ setupControl(nameLabel);
+ Label separator = new Label(_tipComposite, SWT.NO_FOCUS | SWT.SEPARATOR | SWT.VERTICAL);
+ GridData gd = new GridData(SWT.CENTER, SWT.CENTER, false, false);
+ gd.heightHint = nameLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
+ separator.setLayoutData(gd);
+ setupControl(separator);
+ Label valueLabel = new Label(_tipComposite, SWT.NO_FOCUS);
+ valueLabel.setText(value);
+ setupControl(valueLabel);
+ }
+
+ private void fillValues(Point pt, TimeGraphControl timeGraphControl, ITimeGraphEntry entry) {
+ if (entry == null) {
+ return;
+ }
+ if (entry.hasTimeEvents()) {
+ long currPixelTime = timeGraphControl.getTimeAtX(pt.x);
+ long nextPixelTime = timeGraphControl.getTimeAtX(pt.x + 1);
+ if (nextPixelTime == currPixelTime) {
+ nextPixelTime++;
+ }
+ ITimeEvent currEvent = Utils.findEvent(entry, currPixelTime, 0);
+ ITimeEvent nextEvent = Utils.findEvent(entry, currPixelTime, 1);
+
+ // if there is no current event at the start of the current pixel range,
+ // or if the current event starts before the current pixel range,
+ // use the next event as long as it starts within the current pixel range
+ if (currEvent == null || currEvent.getTime() < currPixelTime) {
+ if (nextEvent != null && nextEvent.getTime() < nextPixelTime) {
+ currEvent = nextEvent;
+ currPixelTime = nextEvent.getTime();
+ }
+ }
+
+ // state name
+ String stateTypeName = _utilImp.getStateTypeName(entry);
+ String entryName = entry.getName();
+ if (stateTypeName == null) {
+ stateTypeName = _utilImp.getStateTypeName();
+ }
+
+ if (!entryName.isEmpty()) {
+ addItem(stateTypeName, entry.getName());
+ }
+
+ if (currEvent == null) {
+ return;
+ }
+
+ // state
+ String state = _utilImp.getEventName(currEvent);
+ if (state != null) {
+ addItem(Messages.TmfTimeTipHandler_TRACE_STATE, state);
+ }
+
+ // This block receives a list of <String, String> values to be added to the tip table
+ Map<String, String> eventAddOns = _utilImp.getEventHoverToolTipInfo(currEvent, currPixelTime);
+ if (eventAddOns != null) {
+ for (Iterator<String> iter = eventAddOns.keySet().iterator(); iter.hasNext();) {
+ String message = iter.next();
+ addItem(message, eventAddOns.get(message));
+ }
+ }
+
+ long eventStartTime = -1;
+ long eventDuration = -1;
+ long eventEndTime = -1;
+
+ eventStartTime = currEvent.getTime();
+ eventDuration = currEvent.getDuration();
+ if (eventDuration < 0 && nextEvent != null) {
+ eventEndTime = nextEvent.getTime();
+ eventDuration = eventEndTime - eventStartTime;
+ } else {
+ eventEndTime = eventStartTime + eventDuration;
+ }
+
+ Resolution res = Resolution.NANOSEC;
+ TimeFormat tf = _timeDataProvider.getTimeFormat();
+ if (tf == TimeFormat.CALENDAR) {
+ addItem(Messages.TmfTimeTipHandler_TRACE_DATE, eventStartTime > -1 ?
+ Utils.formatDate(eventStartTime)
+ : "?"); //$NON-NLS-1$
+ }
+ if (eventDuration > 0) {
+ addItem(Messages.TmfTimeTipHandler_TRACE_START_TIME, eventStartTime > -1 ?
+ Utils.formatTime(eventStartTime, tf, res)
+ : "?"); //$NON-NLS-1$
+
+ addItem(Messages.TmfTimeTipHandler_TRACE_STOP_TIME, eventEndTime > -1 ?
+ Utils.formatTime(eventEndTime, tf, res)
+ : "?"); //$NON-NLS-1$
+ } else {
+ addItem(Messages.TmfTimeTipHandler_TRACE_EVENT_TIME, eventStartTime > -1 ?
+ Utils.formatTime(eventStartTime, tf, res)
+ : "?"); //$NON-NLS-1$
+ }
+
+ if (eventDuration > 0) {
+ // Duration in relative format in any case
+ if (tf == TimeFormat.CALENDAR) {
+ tf = TimeFormat.RELATIVE;
+ }
+ addItem(Messages.TmfTimeTipHandler_DURATION, eventDuration > -1 ?
+ Utils.formatTime(eventDuration, tf, res)
+ : "?"); //$NON-NLS-1$
+ }
+ }
+ }
+
+ @Override
+ public void mouseHover(MouseEvent event) {
+ if ((event.stateMask & SWT.BUTTON_MASK) != 0) {
+ return;
+ }
+ Point pt = new Point(event.x, event.y);
+ TimeGraphControl timeGraphControl = (TimeGraphControl) event.widget;
+ createTooltipShell(timeGraphControl.getShell());
+ ITimeGraphEntry entry = timeGraphControl.getEntry(pt);
+ for (Control child : _tipComposite.getChildren()) {
+ child.dispose();
+ }
+ fillValues(pt, timeGraphControl, entry);
+ if (_tipComposite.getChildren().length == 0) {
+ return;
+ }
+ _tipShell.pack();
+ _tipPosition = control.toDisplay(pt);
+ _tipShell.pack();
+ setHoverLocation(_tipShell, _tipPosition);
+ _tipShell.setVisible(true);
+ }
+ });
+ }
+
+ private static void setHoverLocation(Shell shell, Point position) {
+ Rectangle displayBounds = shell.getDisplay().getBounds();
+ Rectangle shellBounds = shell.getBounds();
+ if (position.x + shellBounds.width + 16 > displayBounds.width && position.x - shellBounds.width - 16 >= 0) {
+ shellBounds.x = position.x - shellBounds.width - 16;
+ } else {
+ shellBounds.x = Math.max(Math.min(position.x + 16, displayBounds.width - shellBounds.width), 0);
+ }
+ if (position.y + shellBounds.height + 16 > displayBounds.height && position.y - shellBounds.height - 16 >= 0) {
+ shellBounds.y = position.y - shellBounds.height - 16;
+ } else {
+ shellBounds.y = Math.max(Math.min(position.y + 16, displayBounds.height - shellBounds.height), 0);
+ }
+ shell.setBounds(shellBounds);
+ }
+
+ private void setupControl(Control control) {
+ control.setForeground(_tipShell.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+ control.setBackground(_tipShell.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+
+ control.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseDown(MouseEvent e) {
+ _tipShell.dispose();
+ }
+ });
+
+ control.addMouseTrackListener(new MouseTrackAdapter() {
+ @Override
+ public void mouseExit(MouseEvent e) {
+ _tipShell.dispose();
+ }
+ });
+
+ control.addMouseMoveListener(new MouseMoveListener() {
+ @Override
+ public void mouseMove(MouseEvent e) {
+ _tipShell.dispose();
+ }
+ });
+ }
}