| /********************************************************************** |
| * Copyright (c) 2013, 2019 Ericsson, École Polytechnique de Montréal, Draeger |
| * |
| * All rights reserved. This program and the accompanying materials are |
| * made available under the terms of the Eclipse Public License 2.0 which |
| * accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Bernd Hufmann - Initial API and implementation |
| * Geneviève Bastien - Moved some methods to TmfTimeViewer |
| * Patrick Tasse - Fix setFocus |
| * Ivan Grinenko - Add ability to set fixed range for Y axis. |
| **********************************************************************/ |
| package org.eclipse.tracecompass.tmf.ui.viewers.xycharts; |
| |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.jdt.annotation.Nullable; |
| import org.eclipse.jface.action.IStatusLineManager; |
| import org.eclipse.jface.layout.GridDataFactory; |
| import org.eclipse.jface.layout.GridLayoutFactory; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.FocusListener; |
| import org.eclipse.swt.events.MouseAdapter; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.PaintEvent; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.GC; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.graphics.Rectangle; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.tracecompass.internal.tmf.ui.viewers.xycharts.TmfXYChartTimeAdapter; |
| import org.eclipse.tracecompass.internal.tmf.ui.viewers.xycharts.TmfXyUiUtils; |
| import org.eclipse.tracecompass.internal.tmf.ui.views.ITmfTimeNavigationProvider; |
| import org.eclipse.tracecompass.internal.tmf.ui.views.ITmfTimeZoomProvider; |
| import org.eclipse.tracecompass.internal.tmf.ui.views.ITmfZoomToSelectionProvider; |
| import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal; |
| import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; |
| import org.eclipse.tracecompass.tmf.core.signal.TmfTimestampFormatUpdateSignal; |
| import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal; |
| import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimePreferencesConstants; |
| import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimePreferences; |
| import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; |
| import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext; |
| import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; |
| import org.eclipse.tracecompass.tmf.ui.viewers.IImageSave; |
| import org.eclipse.tracecompass.tmf.ui.viewers.TmfTimeViewer; |
| import org.eclipse.tracecompass.tmf.ui.views.FormatTimeUtils; |
| import org.eclipse.tracecompass.tmf.ui.views.FormatTimeUtils.Resolution; |
| import org.eclipse.tracecompass.tmf.ui.views.FormatTimeUtils.TimeFormat; |
| import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphColorScheme; |
| import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphScale; |
| import org.swtchart.Chart; |
| import org.swtchart.IAxis; |
| import org.swtchart.ICustomPaintListener; |
| import org.swtchart.IPlotArea; |
| import org.swtchart.ISeries; |
| import org.swtchart.ISeriesSet; |
| import org.swtchart.ITitle; |
| import org.swtchart.LineStyle; |
| import org.swtchart.Range; |
| |
| import com.google.common.annotations.VisibleForTesting; |
| |
| /** |
| * Base class for a XY-Chart based on SWT chart. It provides a methods to define |
| * zoom, selection and tool tip providers. It also provides call backs to be |
| * notified by any changes caused by selection and zoom. |
| * |
| * @author Bernd Hufmann |
| */ |
| public abstract class TmfXYChartViewer extends TmfTimeViewer implements ITmfChartTimeProvider, IImageSave, IAdaptable { |
| |
| // ------------------------------------------------------------------------ |
| // Attributes |
| // ------------------------------------------------------------------------ |
| private static final int DEFAULT_SCALE_HEIGHT = 22; |
| |
| /** The color scheme for the chart */ |
| private @NonNull TimeGraphColorScheme fColorScheme = new TimeGraphColorScheme(); |
| /** The SWT Chart reference */ |
| private Chart fSwtChart; |
| /** The X axis for the chart */ |
| private TimeGraphScale fTimeScaleCtrl; |
| /** The time format */ |
| private @Nullable TimeFormat fTimeFormat = null; |
| /** The mouse selection provider */ |
| private TmfBaseProvider fMouseSelectionProvider; |
| /** The mouse drag zoom provider */ |
| private TmfBaseProvider fMouseDragZoomProvider; |
| /** The mouse wheel zoom provider */ |
| private TmfBaseProvider fMouseWheelZoomProvider; |
| /** The tooltip provider */ |
| private TmfBaseProvider fToolTipProvider; |
| /** The middle mouse drag provider */ |
| private TmfBaseProvider fMouseDragProvider; |
| /** |
| * Whether or not to send time alignment signals. This should be set to true for |
| * viewers that are part of an aligned view. |
| */ |
| private boolean fSendTimeAlignSignals = false; |
| |
| private final TmfXYChartTimeAdapter fDataProvider; |
| |
| private AxisRange fFixedYRange = null; |
| |
| private IStatusLineManager fStatusLineManager; |
| // ------------------------------------------------------------------------ |
| // Constructors |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Constructs a TmfXYChartViewer. |
| * |
| * @param parent |
| * The parent composite |
| * @param title |
| * The title of the viewer |
| * @param xLabel |
| * The label of the xAxis |
| * @param yLabel |
| * The label of the yAXIS |
| */ |
| public TmfXYChartViewer(Composite parent, String title, String xLabel, String yLabel) { |
| Composite commonComposite = new Composite(parent, parent.getStyle()) { |
| @Override |
| public void redraw() { |
| fSwtChart.redraw(); |
| fTimeScaleCtrl.redraw(); |
| } |
| }; |
| commonComposite.addDisposeListener(e -> { |
| fColorScheme.dispose(); |
| }); |
| commonComposite.setLayout(GridLayoutFactory.fillDefaults().spacing(0, 0).margins(0, 0).create()); |
| commonComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create()); |
| fSwtChart = new Chart(commonComposite, SWT.NONE) { |
| @Override |
| public void addFocusListener(FocusListener listener) { |
| fSwtChart.getPlotArea().addFocusListener(listener); |
| } |
| @Override |
| public void removeFocusListener(FocusListener listener) { |
| fSwtChart.getPlotArea().removeFocusListener(listener); |
| } |
| @Override |
| public boolean setFocus() { |
| return fSwtChart.getPlotArea().setFocus(); |
| } |
| @Override |
| public boolean forceFocus() { |
| return fSwtChart.getPlotArea().forceFocus(); |
| } |
| }; |
| fSwtChart.getAxisSet().getXAxis(0).getGrid().setStyle(LineStyle.NONE); |
| ((IPlotArea) fSwtChart.getPlotArea()).addCustomPaintListener(new ICustomPaintListener() { |
| |
| @Override |
| public void paintControl(PaintEvent e) { |
| drawGridLines(e.gc); |
| } |
| |
| @Override |
| public boolean drawBehindSeries() { |
| return true; |
| } |
| }); |
| |
| fSwtChart.addPaintListener(e -> { |
| Rectangle bounds = fSwtChart.getPlotArea().getBounds(); |
| int y = fTimeScaleCtrl.getLocation().y; |
| fTimeScaleCtrl.setBounds(bounds.x, y, bounds.width, DEFAULT_SCALE_HEIGHT); |
| fTimeScaleCtrl.redraw(); |
| }); |
| |
| fTimeScaleCtrl = new TimeGraphScale(commonComposite, fColorScheme, SWT.BOTTOM); |
| Color backgroundColor = fColorScheme.getColor(TimeGraphColorScheme.TOOL_BACKGROUND); |
| fSwtChart.setBackground(backgroundColor); |
| commonComposite.setBackground(backgroundColor); |
| backgroundColor = fColorScheme.getColor(TimeGraphColorScheme.BACKGROUND); |
| fSwtChart.setBackgroundInPlotArea(backgroundColor); |
| fSwtChart.setForeground(fColorScheme.getColor(TimeGraphColorScheme.TOOL_FOREGROUND)); |
| fTimeScaleCtrl.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false)); |
| fTimeScaleCtrl.setHeight(DEFAULT_SCALE_HEIGHT); |
| fSwtChart.getPlotArea().addMouseListener(new MouseAdapter() { |
| @Override |
| public void mouseDown(MouseEvent e) { |
| fSwtChart.getPlotArea().setFocus(); |
| } |
| }); |
| |
| IAxis xAxis = fSwtChart.getAxisSet().getXAxis(0); |
| IAxis yAxis = fSwtChart.getAxisSet().getYAxis(0); |
| |
| /* Set the title/labels, or hide them if they are not provided */ |
| initTitle(title, fSwtChart.getTitle()); |
| |
| initTitle(null, fSwtChart.getTitle()); |
| |
| xAxis.getTick().setVisible(false); |
| yAxis.getTick().setForeground(fColorScheme.getColor(TimeGraphColorScheme.TOOL_FOREGROUND)); |
| initTitle(yLabel, yAxis.getTitle()); |
| |
| fMouseSelectionProvider = new TmfMouseSelectionProvider(this); |
| fMouseDragZoomProvider = new TmfMouseDragZoomProvider(this); |
| fMouseWheelZoomProvider = new TmfMouseWheelZoomProvider(this); |
| fToolTipProvider = new TmfSimpleTooltipProvider(this); |
| fMouseDragProvider = new TmfMouseDragProvider(this); |
| |
| fSwtChart.addDisposeListener((e) -> { |
| internalDispose(); |
| }); |
| |
| fDataProvider = new TmfXYChartTimeAdapter(this); |
| fTimeScaleCtrl.setTimeProvider(fDataProvider); |
| updateTimeFormat(); |
| } |
| |
| private void initTitle(String label, ITitle titleCtrl) { |
| titleCtrl.setForeground(fColorScheme.getColor(TimeGraphColorScheme.TOOL_FOREGROUND)); |
| if (label == null) { |
| titleCtrl.setVisible(false); |
| } else { |
| titleCtrl.setText(label); |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Getter/Setters |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Sets the SWT Chart reference |
| * |
| * @param chart |
| * The SWT chart to set. |
| */ |
| protected void setSwtChart(Chart chart) { |
| fSwtChart = chart; |
| } |
| |
| /** |
| * Gets the SWT Chart reference |
| * |
| * @return the SWT chart to set. |
| * @since 3.2 |
| */ |
| public Chart getSwtChart() { |
| return fSwtChart; |
| } |
| |
| /** |
| * Sets a mouse selection provider. An existing provider will be disposed. Use |
| * <code>null</code> to disable the mouse selection provider. |
| * |
| * @param provider |
| * The selection provider to set |
| */ |
| public void setSelectionProvider(TmfBaseProvider provider) { |
| if (fMouseSelectionProvider != null) { |
| fMouseSelectionProvider.dispose(); |
| } |
| fMouseSelectionProvider = provider; |
| } |
| |
| /** |
| * Sets a mouse drag zoom provider. An existing provider will be disposed. Use |
| * <code>null</code> to disable the mouse drag zoom provider. |
| * |
| * @param provider |
| * The mouse drag zoom provider to set |
| */ |
| public void setMouseDragZoomProvider(TmfBaseProvider provider) { |
| if (fMouseDragZoomProvider != null) { |
| fMouseDragZoomProvider.dispose(); |
| } |
| fMouseDragZoomProvider = provider; |
| } |
| |
| /** |
| * Sets a mouse wheel zoom provider. An existing provider will be disposed. Use |
| * <code>null</code> to disable the mouse wheel zoom provider. |
| * |
| * @param provider |
| * The mouse wheel zoom provider to set |
| */ |
| public void setMouseWheelZoomProvider(TmfBaseProvider provider) { |
| if (fMouseWheelZoomProvider != null) { |
| fMouseWheelZoomProvider.dispose(); |
| } |
| fMouseWheelZoomProvider = provider; |
| } |
| |
| /** |
| * Sets a tooltip provider. An existing provider will be disposed. Use |
| * <code>null</code> to disable the tooltip provider. |
| * |
| * @param provider |
| * The tooltip provider to set |
| */ |
| public void setTooltipProvider(TmfBaseProvider provider) { |
| if (fToolTipProvider != null) { |
| fToolTipProvider.dispose(); |
| } |
| fToolTipProvider = provider; |
| } |
| |
| /** |
| * Sets a mouse drag provider. An existing provider will be disposed. Use |
| * <code>null</code> to disable the mouse drag provider. |
| * |
| * @param provider |
| * The mouse drag provider to set |
| */ |
| public void setMouseDrageProvider(TmfBaseProvider provider) { |
| if (fMouseDragProvider != null) { |
| fMouseDragProvider.dispose(); |
| } |
| fMouseDragProvider = provider; |
| } |
| |
| // ------------------------------------------------------------------------ |
| // ITmfChartTimeProvider |
| // ------------------------------------------------------------------------ |
| |
| @Override |
| public long getTimeOffset() { |
| return getWindowStartTime() - 1; |
| } |
| |
| // ------------------------------------------------------------------------ |
| // ITmfViewer interface |
| // ------------------------------------------------------------------------ |
| @Override |
| public Control getControl() { |
| return fSwtChart; |
| } |
| |
| @Override |
| public void refresh() { |
| fSwtChart.redraw(); |
| } |
| |
| // ------------------------------------------------------------------------ |
| // TmfComponent |
| // ------------------------------------------------------------------------ |
| |
| @Override |
| public void dispose() { |
| if (!fSwtChart.isDisposed()) { |
| fSwtChart.dispose(); |
| } |
| } |
| |
| private void internalDispose() { |
| super.dispose(); |
| |
| if (fMouseSelectionProvider != null) { |
| fMouseSelectionProvider.dispose(); |
| } |
| |
| if (fMouseDragZoomProvider != null) { |
| fMouseDragZoomProvider.dispose(); |
| } |
| |
| if (fMouseWheelZoomProvider != null) { |
| fMouseWheelZoomProvider.dispose(); |
| } |
| |
| if (fToolTipProvider != null) { |
| fToolTipProvider.dispose(); |
| } |
| |
| if (fMouseDragProvider != null) { |
| fMouseDragProvider.dispose(); |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Operations |
| // ------------------------------------------------------------------------ |
| /** |
| * A Method to load a trace into the viewer. |
| * |
| * @param trace |
| * A trace to apply in the viewer |
| */ |
| @Override |
| public void loadTrace(ITmfTrace trace) { |
| super.loadTrace(trace); |
| clearContent(); |
| updateContent(); |
| } |
| |
| /** |
| * Resets the content of the viewer |
| */ |
| @Override |
| public void reset() { |
| super.reset(); |
| setStartTime(0); |
| setEndTime(0); |
| clearContent(); |
| } |
| |
| /** |
| * Method to implement to update the chart content. |
| */ |
| protected abstract void updateContent(); |
| |
| /** |
| * Returns whether or not this chart viewer is dirty. The viewer is considered |
| * dirty if it has yet to completely update its model. |
| * |
| * This method is meant to be used by tests in order to know when it is safe to |
| * proceed. |
| * |
| * @return true if the time graph view has yet to completely update its model, |
| * false otherwise |
| * @since 2.2 |
| */ |
| @VisibleForTesting |
| public boolean isDirty() { |
| if (getTrace() == null) { |
| return false; |
| } |
| |
| TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext(); |
| long startTime = ctx.getWindowRange().getStartTime().toNanos(); |
| long endTime = ctx.getWindowRange().getEndTime().toNanos(); |
| |
| // If the chart viewer hasn't updated all the way to the end of |
| // the window range then it's dirty. A refresh should happen later. |
| return (getWindowStartTime() != startTime || getWindowEndTime() != endTime); |
| } |
| |
| /** |
| * Draw the grid lines |
| * |
| * @param bounds |
| * The bounds of the control |
| * @param gc |
| * Graphics context |
| * @since 2.0 |
| */ |
| private void drawGridLines(GC gc) { |
| Rectangle bounds = fSwtChart.getPlotArea().getBounds(); |
| Color foreground = fSwtChart.getAxisSet().getXAxis(0).getGrid().getForeground(); |
| gc.setForeground(foreground); |
| gc.setAlpha(foreground.getAlpha()); |
| gc.setLineStyle(SWT.LINE_DOT); |
| for (int x : fTimeScaleCtrl.getTickList()) { |
| gc.drawLine(x, 0, x, bounds.height); |
| } |
| gc.setAlpha(255); |
| } |
| |
| /** |
| * Sets the time format, or null to use the Time Format 'Date and Time |
| * format' preference (default). |
| * |
| * @param timeFormat |
| * the {@link TimeFormat} used to display timestamps |
| * @since 5.0 |
| */ |
| protected void setTimeFormat(TimeFormat timeFormat) { |
| fTimeFormat = timeFormat; |
| if (fSwtChart != null) { |
| updateTimeFormat(); |
| fSwtChart.getAxisSet().adjustRange(); |
| fSwtChart.redraw(); |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Signal Handler |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Signal handler for handling of the time synch signal. |
| * |
| * @param signal |
| * The time synch signal {@link TmfSelectionRangeUpdatedSignal} |
| */ |
| @Override |
| @TmfSignalHandler |
| public void selectionRangeUpdated(TmfSelectionRangeUpdatedSignal signal) { |
| super.selectionRangeUpdated(signal); |
| if (signal != null && (signal.getSource() != this) && (getTrace() != null)) { |
| if (fMouseSelectionProvider != null) { |
| fMouseSelectionProvider.refresh(); |
| } |
| } |
| } |
| |
| /** |
| * Signal handler for handling of the window range signal. |
| * |
| * @param signal |
| * The {@link TmfWindowRangeUpdatedSignal} |
| */ |
| @Override |
| @TmfSignalHandler |
| public void windowRangeUpdated(TmfWindowRangeUpdatedSignal signal) { |
| super.windowRangeUpdated(signal); |
| updateContent(); |
| } |
| |
| /** |
| * Signal handler for handling the signal that notifies about an updated |
| * timestamp format. |
| * |
| * @param signal |
| * The trace updated signal {@link TmfTimestampFormatUpdateSignal} |
| */ |
| @TmfSignalHandler |
| public void timestampFormatUpdated(TmfTimestampFormatUpdateSignal signal) { |
| updateTimeFormat(); |
| fSwtChart.getAxisSet().adjustRange(); |
| fSwtChart.redraw(); |
| } |
| |
| /** |
| * Sets new fixed range for the Y axis. |
| * |
| * @param yRange |
| * new fixed range for the Y axis or {@code null} to |
| * make float again. If not {@code null} then |
| * {@link IAxis#adjustRange} is not called for the Y |
| * axis on updates. |
| * @since 5.2 |
| */ |
| public void setFixedYRange(@Nullable AxisRange yRange) { |
| fFixedYRange = yRange; |
| updateContent(); |
| } |
| |
| /** |
| * Gets current fixed range for the Y axis. |
| * |
| * @return Current fixed range or {@code null} if the range is not fixed. |
| * @since 5.2 |
| */ |
| public @Nullable AxisRange getFixedYRange() { |
| return fFixedYRange; |
| } |
| |
| // ------------------------------------------------------------------------ |
| // IAdaptable Interface |
| // ------------------------------------------------------------------------ |
| /** |
| * @since 5.0 |
| */ |
| @SuppressWarnings("unchecked") |
| @Override |
| public <T> T getAdapter(Class<T> adapter) { |
| if (adapter == ITmfTimeNavigationProvider.class) { |
| return (T) getTimeNavigator(); |
| } |
| if (adapter == ITmfTimeZoomProvider.class) { |
| return (T) getTimeZoomProvider(); |
| } |
| if (adapter == ITmfZoomToSelectionProvider.class ) { |
| return (T) getZoomToSelectionProvider(); |
| } |
| return null; |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Helper Methods |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Clears the view content. |
| */ |
| protected void clearContent() { |
| if (!fSwtChart.isDisposed()) { |
| ISeriesSet set = fSwtChart.getSeriesSet(); |
| ISeries[] series = set.getSeries(); |
| for (int i = 0; i < series.length; i++) { |
| set.deleteSeries(series[i].getId()); |
| } |
| for (IAxis axis : fSwtChart.getAxisSet().getAxes()) { |
| axis.setRange(new Range(0, 1)); |
| } |
| fSwtChart.redraw(); |
| } |
| } |
| |
| /** |
| * Returns the current or default display. |
| * |
| * @return the current or default display |
| */ |
| protected static Display getDisplay() { |
| Display display = Display.getCurrent(); |
| // may be null if outside the UI thread |
| if (display == null) { |
| display = Display.getDefault(); |
| } |
| return display; |
| } |
| |
| /** |
| * Get the offset of the point area, relative to the XY chart viewer control. We |
| * consider the point area to be from where the first point could be drawn to |
| * where the last point could be drawn. |
| * |
| * @return the offset in pixels |
| * |
| * @since 1.0 |
| */ |
| public int getPointAreaOffset() { |
| |
| int pixelCoordinate = 0; |
| IAxis[] xAxes = getSwtChart().getAxisSet().getXAxes(); |
| if (xAxes.length > 0) { |
| IAxis axis = xAxes[0]; |
| pixelCoordinate = axis.getPixelCoordinate(axis.getRange().lower); |
| } |
| return getSwtChart().toControl(getSwtChart().getPlotArea().toDisplay(pixelCoordinate, 0)).x; |
| } |
| |
| /** |
| * Get the width of the point area. We consider the point area to be from where |
| * the first point could be drawn to where the last point could be drawn. The |
| * point area differs from the plot area because there might be a gap between |
| * where the plot area start and where the fist point is drawn. This also |
| * matches the width that the use can select. |
| * |
| * @return the width in pixels |
| * |
| * @since 1.0 |
| */ |
| public int getPointAreaWidth() { |
| IAxis[] xAxes = getSwtChart().getAxisSet().getXAxes(); |
| if (xAxes.length > 0) { |
| IAxis axis = xAxes[0]; |
| int x1 = getPointAreaOffset(); |
| int x2 = axis.getPixelCoordinate(axis.getRange().upper); |
| x2 = getSwtChart().toControl(getSwtChart().getPlotArea().toDisplay(x2, 0)).x; |
| int width = x2 - x1; |
| return width; |
| } |
| |
| return getSwtChart().getPlotArea().getSize().x; |
| } |
| |
| /** |
| * Sets whether or not to send time alignment signals. This should be set to |
| * true for viewers that are part of an aligned view. |
| * |
| * @param sendTimeAlignSignals |
| * whether or not to send time alignment signals |
| * @since 1.0 |
| */ |
| public void setSendTimeAlignSignals(boolean sendTimeAlignSignals) { |
| fSendTimeAlignSignals = sendTimeAlignSignals; |
| } |
| |
| /** |
| * Returns whether or not to send time alignment signals. |
| * |
| * @return whether or not to send time alignment signals. |
| * @since 1.0 |
| */ |
| public boolean isSendTimeAlignSignals() { |
| return fSendTimeAlignSignals; |
| } |
| |
| @Override |
| public void saveImage(String filename, int format) { |
| getSwtChart().save(filename, format); |
| } |
| |
| /** |
| * Set the status bar manager |
| * |
| * @param statusLineManager |
| * Status bar manager |
| * @since 3.3 |
| */ |
| public void setStatusLineManager(IStatusLineManager statusLineManager) { |
| if (fStatusLineManager != null && statusLineManager == null) { |
| fStatusLineManager.setMessage(null); |
| } |
| fStatusLineManager = statusLineManager; |
| } |
| |
| /** |
| * Update the status line to include time selection |
| * |
| * @param startTime |
| * Selection start time |
| * @param endTime |
| * Selection end time |
| * @param cursorTime |
| * Cursor time |
| * @since 3.3 |
| */ |
| public void updateStatusLine(long startTime, long endTime, long cursorTime) { |
| TimeFormat timeFormat = fTimeScaleCtrl.getTimeProvider().getTimeFormat().convert(); |
| boolean isCalendar = timeFormat == TimeFormat.CALENDAR; |
| |
| StringBuilder message = new StringBuilder(); |
| String spaces = " "; //$NON-NLS-1$ |
| if (cursorTime >= 0) { |
| message.append("T: "); //$NON-NLS-1$ |
| if (isCalendar) { |
| message.append(FormatTimeUtils.formatDate(cursorTime + getTimeOffset()) + ' '); |
| } |
| message.append(FormatTimeUtils.formatTime(cursorTime + getTimeOffset(), timeFormat, Resolution.NANOSEC)); |
| message.append(spaces); |
| } |
| |
| if (startTime == endTime) { |
| message.append("T1: "); //$NON-NLS-1$ |
| if (isCalendar) { |
| message.append(FormatTimeUtils.formatDate(startTime + getTimeOffset()) + ' '); |
| } |
| message.append(FormatTimeUtils.formatTime(startTime + getTimeOffset(), timeFormat, Resolution.NANOSEC)); |
| } else { |
| message.append("T1: "); //$NON-NLS-1$ |
| if (isCalendar) { |
| message.append(FormatTimeUtils.formatDate(startTime + getTimeOffset()) + ' '); |
| } |
| message.append(FormatTimeUtils.formatTime(startTime + getTimeOffset(), timeFormat, Resolution.NANOSEC)); |
| message.append(spaces); |
| message.append("T2: "); //$NON-NLS-1$ |
| if (isCalendar) { |
| message.append(FormatTimeUtils.formatDate(endTime + getTimeOffset()) + ' '); |
| } |
| message.append(FormatTimeUtils.formatTime(endTime + getTimeOffset(), timeFormat, Resolution.NANOSEC)); |
| message.append(spaces); |
| message.append("\u0394: " + FormatTimeUtils.formatDelta(endTime - startTime, timeFormat, Resolution.NANOSEC)); //$NON-NLS-1$ |
| } |
| |
| fStatusLineManager.setMessage(message.toString()); |
| } |
| |
| private ITmfTimeZoomProvider getTimeZoomProvider() { |
| return (zoomIn, useMousePosition) -> { |
| Chart chart = getSwtChart(); |
| if (chart == null) { |
| return; |
| } |
| Point cursorDisplayLocation = getDisplay().getCursorLocation(); |
| Point cursorControlLocation = getSwtChart().getPlotArea().toControl(cursorDisplayLocation); |
| Point cursorParentLocation = getSwtChart().getPlotArea().getParent().toControl(cursorDisplayLocation); |
| Rectangle controlBounds = getSwtChart().getPlotArea().getBounds(); |
| // check the X axis only |
| if (!controlBounds.contains(cursorParentLocation.x, controlBounds.y)) { |
| return; |
| } |
| if (useMousePosition) { |
| TmfXyUiUtils.zoom(this, chart, zoomIn, cursorControlLocation.x); |
| } else { |
| TmfXyUiUtils.zoom(this, chart, zoomIn); |
| } |
| }; |
| } |
| |
| private ITmfTimeNavigationProvider getTimeNavigator() { |
| return left -> { |
| Chart chart = getSwtChart(); |
| if (chart != null) { |
| TmfXyUiUtils.horizontalScroll(this, chart, left); |
| } |
| }; |
| } |
| |
| private ITmfZoomToSelectionProvider getZoomToSelectionProvider() { |
| return () -> { |
| long selBegin = getSelectionBeginTime(); |
| long selEnd = getSelectionEndTime(); |
| if (selBegin != selEnd) { |
| updateWindow(selBegin, selEnd); |
| } |
| }; |
| } |
| |
| private void updateTimeFormat() { |
| if (fTimeFormat == null) { |
| String datime = TmfTimePreferences.getPreferenceMap().get(ITmfTimePreferencesConstants.DATIME); |
| if (ITmfTimePreferencesConstants.TIME_ELAPSED_FMT.equals(datime)) { |
| fDataProvider.setTimeFormat(TimeFormat.RELATIVE); |
| } else { |
| fDataProvider.setTimeFormat(TimeFormat.CALENDAR); |
| } |
| } else { |
| fDataProvider.setTimeFormat(fTimeFormat); |
| } |
| } |
| } |