From: Bernd Hufmann Date: Thu, 19 Dec 2013 12:10:54 +0000 (-0500) Subject: tmf: add abstract view and viewer classes for generation of SWT charts X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=d7d40e67c981cd09897cfe021217391625304043;p=deliverable%2Ftracecompass.git tmf: add abstract view and viewer classes for generation of SWT charts Change-Id: I2d83280a63574727ceaf567db501119a7e0b2909 Signed-off-by: Bernd Hufmann Reviewed-on: https://git.eclipse.org/r/20080 Tested-by: Hudson CI Reviewed-by: Genevieve Bastien IP-Clean: Genevieve Bastien Tested-by: Genevieve Bastien Reviewed-by: Bernd Hufmann --- diff --git a/org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF b/org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF index f87297d72a..c1e2ec0441 100644 --- a/org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.linuxtools.tmf.ui/META-INF/MANIFEST.MF @@ -15,7 +15,8 @@ Require-Bundle: org.eclipse.core.expressions, org.eclipse.ui, org.eclipse.ui.ide, org.eclipse.ui.navigator, - org.eclipse.ui.navigator.resources + org.eclipse.ui.navigator.resources, + org.swtchart Export-Package: org.eclipse.linuxtools.internal.tmf.ui;x-friends:="org.eclipse.linuxtools.tmf.ui.tests", org.eclipse.linuxtools.internal.tmf.ui.commands;x-internal:=true, org.eclipse.linuxtools.internal.tmf.ui.dialogs;x-internal:=true, @@ -38,6 +39,7 @@ Export-Package: org.eclipse.linuxtools.internal.tmf.ui;x-friends:="org.eclipse.l org.eclipse.linuxtools.tmf.ui.viewers.events, org.eclipse.linuxtools.tmf.ui.viewers.statistics, org.eclipse.linuxtools.tmf.ui.viewers.statistics.model, + org.eclipse.linuxtools.tmf.ui.viewers.xycharts;x-internal:=true, org.eclipse.linuxtools.tmf.ui.views, org.eclipse.linuxtools.tmf.ui.views.callstack, org.eclipse.linuxtools.tmf.ui.views.colors, diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/ITmfChartTimeProvider.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/ITmfChartTimeProvider.java new file mode 100644 index 0000000000..b7ebb6266b --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/ITmfChartTimeProvider.java @@ -0,0 +1,103 @@ +/********************************************************************** + * Copyright (c) 2013 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: + * Bernd Hufmann - Initial API and implementation + **********************************************************************/ +package org.eclipse.linuxtools.tmf.ui.viewers.xycharts; + +import org.eclipse.linuxtools.tmf.ui.viewers.ITmfViewer; + +/** + * Interface for providing and updating time information. This is typically + * implemented by a chart viewer that is displaying trace data over time where + * the time is shown on the x-axis. + * + * @author Bernd Hufmann + * @since 3.0 + */ +public interface ITmfChartTimeProvider extends ITmfViewer { + /** + * Gets the start time of trace + * + * @return start time of trace + */ + long getStartTime(); + + /** + * Gets the end time of trace + * + * @return End time of trace + */ + long getEndTime(); + + /** + * Gets the start time of current time range displayed + * + * @return start time of current time range + */ + long getWindowStartTime(); + + /** + * Gets the end time of current time range displayed + * + * @return End time of current time range + */ + long getWindowEndTime(); + + /** + * Gets the duration of the current time range displayed + * + * @return duration of current time range + */ + long getWindowDuration(); + + /** + * Gets the begin time of the selected range + * + * @return the begin time of the selected range + */ + long getSelectionBeginTime(); + + /** + * Gets the end time of the selected range + * + * @return end time of the selected range + */ + long getSelectionEndTime(); + + /** + * Returns a constant time offset that is used to normalize the time values + * to a range of 0..53 bits to avoid loss of precision when converting + * long <-> double. + * + * Time values are stored in TMF as long values. The SWT chart library + * uses values of type double (on x and y axis). To avoid loss of + * precision when converting long <-> double the values need to fit + * within 53 bits. + * + * Subtract the offset when using time values provided externally for + * internal usage in SWT chart. Add the offset when using time values + * provided by SWT chart (e.g. for display purposes) and when broadcasting + * them externally (e.g. time synchronization signals). + * + * For example the offset can be calculated as the time of the first + * time value in the current time range to be displayed in the chart. + * Add +1 to avoid 0 when using logarithmic scale. + * + * t0=10000, t2=20000, tn=N -> timeOffset=t0-1 + * -> t0'=1, t1'=10001, tn'=N-timeOffset + * + * where t0 ... tn are times used externally and t0' ... tn' are times + * used internally by the SWT chart. + * + * @return the time offset + */ + long getTimeOffset(); + +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfXYChartViewer.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfXYChartViewer.java new file mode 100644 index 0000000000..c97f75ff24 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/viewers/xycharts/TmfXYChartViewer.java @@ -0,0 +1,532 @@ +/********************************************************************** + * Copyright (c) 2013 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: + * Bernd Hufmann - Initial API and implementation + **********************************************************************/ +package org.eclipse.linuxtools.tmf.ui.viewers.xycharts; + +import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal; +import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler; +import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal; +import org.eclipse.linuxtools.tmf.core.signal.TmfTimestampFormatUpdateSignal; +import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal; +import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal; +import org.eclipse.linuxtools.tmf.core.signal.TmfTraceRangeUpdatedSignal; +import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal; +import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal; +import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp; +import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange; +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager; +import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.swtchart.Chart; +import org.swtchart.IAxis; +import org.swtchart.ISeries; +import org.swtchart.ISeriesSet; + +/** + * 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 + * @since 3.0 + */ +public abstract class TmfXYChartViewer extends TmfViewer implements ITmfChartTimeProvider { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + /** + * The offset to apply to any x position. This offset ensures better + * precision when converting long to double and back. + */ + private long fTimeOffset; + /** Start time of trace */ + private long fStartTime; + /** End time of trace */ + private long fEndTime; + /** Start time of current time range */ + private long fWindowStartTime; + /** End time of current time range */ + private long fWindowEndTime; + /** Duration of current time range */ + private long fWindowDuration; + /** Current begin time of selection range */ + private long fSelectionBeginTime; + /** Current end of selection range */ + private long fSelectionEndTime; + /** The trace that is displayed by this viewer */ + private ITmfTrace fTrace; + /** The SWT Chart reference */ + private Chart fSwtChart; + + // ------------------------------------------------------------------------ + // 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) { + super(parent, title); + fSwtChart = new Chart(parent, SWT.NONE); + + IAxis xAxis = fSwtChart.getAxisSet().getXAxis(0); + IAxis yAxis = fSwtChart.getAxisSet().getYAxis(0); + + /* Set the title/labels, or hide them if they are not provided */ + if (title == null) { + fSwtChart.getTitle().setVisible(false); + } else { + fSwtChart.getTitle().setText(title); + } + if (xLabel == null) { + xAxis.getTitle().setVisible(false); + } else { + xAxis.getTitle().setText(xLabel); + } + if (yLabel == null) { + yAxis.getTitle().setVisible(false); + } else { + yAxis.getTitle().setText(yLabel); + } + } + + // ------------------------------------------------------------------------ + // Getter/Setters + // ------------------------------------------------------------------------ + /** + * Sets the time offset to apply. + * @see ITmfChartTimeProvider#getTimeOffset() + * + * @param timeOffset + * The time offset to apply + */ + protected void setTimeOffset(long timeOffset) { + fTimeOffset = timeOffset; + } + + /** + * Sets the start time of the trace + * + * @param startTime + * The start time to set + */ + protected void setStartTime(long startTime) { + fStartTime = startTime; + } + + /** + * Sets the end time of the trace + * + * @param endTime + * The start time to set + */ + protected void setEndTime(long endTime) { + fEndTime = endTime; + } + + /** + * Sets the start time of the current time range window + * + * @param windowStartTime + * The start time to set + */ + protected void setWindowStartTime(long windowStartTime) { + fWindowStartTime = windowStartTime; + } + + /** + * Sets the end time of the current time range window + * + * @param windowEndTime + * The start time to set + */ + protected void setWindowEndTime(long windowEndTime) { + fWindowEndTime = windowEndTime; + } + + /** + * Sets the start time of the current time range window + * + * @param windowDuration + * The start time to set + */ + protected void setWindowDuration(long windowDuration) { + fWindowDuration = windowDuration; + } + + /** + * Sets the begin time of the selection range. + * + * @param selectionBeginTime + * The begin time to set + */ + protected void setSelectionBeginTime(long selectionBeginTime) { + fSelectionBeginTime = selectionBeginTime; + } + + /** + * Sets the end time of the selection range. + * + * @param selectionEndTime + * The end time to set + */ + protected void setSelectionEndTime(long selectionEndTime) { + fSelectionEndTime = selectionEndTime; + } + + /** + * Sets the trace that is displayed by this viewer. + * + * @param trace + * The trace to set + */ + protected void setTrace(ITmfTrace trace) { + fTrace = trace; + } + + /** + * Gets the trace that is displayed by this viewer. + * + * @return the trace + */ + protected ITmfTrace getTrace() { + return fTrace; + } + + /** + * 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. + */ + protected Chart getSwtChart() { + return fSwtChart; + } + + // ------------------------------------------------------------------------ + // ITmfChartTimeProvider + // ------------------------------------------------------------------------ + @Override + public long getStartTime() { + return fStartTime; + } + + @Override + public long getEndTime() { + return fEndTime; + } + + @Override + public long getWindowStartTime() { + return fWindowStartTime; + } + + @Override + public long getWindowEndTime() { + return fWindowEndTime; + } + + @Override + public long getWindowDuration() { + return fWindowDuration; + } + + @Override + public long getSelectionBeginTime() { + return fSelectionBeginTime; + } + + @Override + public long getSelectionEndTime() { + return fSelectionEndTime; + } + + @Override + public long getTimeOffset() { + return fTimeOffset; + } + + // ------------------------------------------------------------------------ + // ITmfViewer interface + // ------------------------------------------------------------------------ + @Override + public Control getControl() { + return fSwtChart; + } + + @Override + public void refresh() { + fSwtChart.redraw(); + } + + // ------------------------------------------------------------------------ + // TmfComponent + // ------------------------------------------------------------------------ + @Override + public void dispose() { + super.dispose(); + fSwtChart.dispose(); + } + + // ------------------------------------------------------------------------ + // Operations + // ------------------------------------------------------------------------ + /** + * A Method to load a trace into the viewer. + * + * @param trace + * A trace to apply in the viewer + */ + public void loadTrace(ITmfTrace trace) { + fTrace = trace; + + long timestamp = TmfTraceManager.getInstance().getSelectionBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); + long windowStartTime = TmfTraceManager.getInstance().getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); + long startTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); + long endTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); + + setSelectionBeginTime(timestamp); + setSelectionEndTime(timestamp); + setStartTime(startTime); + setWindowStartTime(windowStartTime); + setWindowDuration(fTrace.getInitialRangeOffset().getValue()); + setEndTime(endTime); + setWindowEndTime(windowStartTime + getWindowDuration()); + clearContent(); + updateContent(); + } + + /** + * Resets the content of the viewer + */ + public void reset() { + // Reset the internal data + setSelectionBeginTime(0); + setSelectionEndTime(0); + setStartTime(0); + setWindowStartTime(0); + setWindowDuration(0); + setEndTime(0); + setWindowEndTime(0); + setTrace(null); + clearContent(); + } + + /** + * Method to implement to update the chart content. + */ + protected abstract void updateContent(); + + // ------------------------------------------------------------------------ + // Signal Handler + // ------------------------------------------------------------------------ + + /** + * Signal handler for handling of the trace opened signal. + * + * @param signal + * The trace opened signal {@link TmfTraceOpenedSignal} + */ + @TmfSignalHandler + public void traceOpened(TmfTraceOpenedSignal signal) { + fTrace = signal.getTrace(); + loadTrace(getTrace()); + } + + /** + * Signal handler for handling of the trace selected signal. + * + * @param signal + * The trace selected signal {@link TmfTraceSelectedSignal} + */ + @TmfSignalHandler + public void traceSelected(TmfTraceSelectedSignal signal) { + if (fTrace != signal.getTrace()) { + fTrace = signal.getTrace(); + loadTrace(getTrace()); + } + } + + /** + * Signal handler for handling of the trace closed signal. + * + * @param signal + * The trace closed signal {@link TmfTraceClosedSignal} + */ + @TmfSignalHandler + public void traceClosed(TmfTraceClosedSignal signal) { + + if (signal.getTrace() != fTrace) { + return; + } + + // Reset the internal data + fTrace = null; + reset(); + } + + /** + * Signal handler for handling of the time synch signal. + * + * @param signal + * The time synch signal {@link TmfTimeSynchSignal} + */ + @TmfSignalHandler + public void selectionRangeUpdated(TmfTimeSynchSignal signal) { + if ((signal.getSource() != this) && (fTrace != null)) { + ITmfTimestamp selectedTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE); + ITmfTimestamp selectedEndTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE); + setSelectionBeginTime(selectedTime.getValue()); + setSelectionEndTime(selectedEndTime.getValue()); + } + } + + /** + * Signal handler for handling of the time range synch signal. + * + * @param signal + * The time range synch signal {@link TmfRangeSynchSignal} + */ + @TmfSignalHandler + public void timeRangeUpdated(TmfRangeSynchSignal signal) { + + if (fTrace != null) { + // Validate the time range + TmfTimeRange range = signal.getCurrentRange().getIntersection(fTrace.getTimeRange()); + if (range == null) { + return; + } + + if (signal.getSource() != this) { + // Update the time range + long windowStartTime = range.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); + long windowEndTime = range.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); + long windowDuration = windowEndTime - windowStartTime; + + setWindowStartTime(windowStartTime); + setWindowEndTime(windowEndTime); + setWindowDuration(windowDuration); + } + } + updateContent(); + } + + /** + * Signal handler for handling of the trace range updated signal. + * + * @param signal + * The trace range signal {@link TmfTraceRangeUpdatedSignal} + */ + @TmfSignalHandler + public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal) { + + if (signal.getTrace() != fTrace) { + return; + } + + TmfTimeRange fullRange = signal.getRange(); + + long traceStartTime = fullRange.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); + long traceEndTime = fullRange.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); + + setStartTime(traceStartTime); + setEndTime(traceEndTime); + } + + /** + * Signal handler for handling of the trace updated signal. + * + * @param signal + * The trace updated signal {@link TmfTraceUpdatedSignal} + */ + @TmfSignalHandler + public void traceUpdated(TmfTraceUpdatedSignal signal) { + if (signal.getTrace() != fTrace) { + return; + } + TmfTimeRange fullRange = signal.getTrace().getTimeRange(); + long traceStartTime = fullRange.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); + long traceEndTime = fullRange.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); + + setStartTime(traceStartTime); + setEndTime(traceEndTime); + } + + /** + * 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) { + fSwtChart.getAxisSet().adjustRange(); + fSwtChart.redraw(); + } + + // ------------------------------------------------------------------------ + // 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()); + } + 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; + } + +} diff --git a/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/TmfChartView.java b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/TmfChartView.java new file mode 100644 index 0000000000..ba27d57923 --- /dev/null +++ b/org.eclipse.linuxtools.tmf.ui/src/org/eclipse/linuxtools/tmf/ui/views/TmfChartView.java @@ -0,0 +1,118 @@ +/********************************************************************** + * Copyright (c) 2013 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: + * Bernd Hufmann - Initial API and implementation + **********************************************************************/ +package org.eclipse.linuxtools.tmf.ui.views; + +import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; +import org.eclipse.linuxtools.tmf.ui.viewers.xycharts.TmfXYChartViewer; +import org.eclipse.swt.widgets.Composite; + +/** + * Base class to be used with a chart viewer {@link TmfXYChartViewer}. + * It is responsible to instantiate the viewer class and load the trace + * into the viewer when the view is created. + * + * @author Bernd Hufmann + * @since 3.0 + */ +abstract public class TmfChartView extends TmfView { + + // ------------------------------------------------------------------------ + // Attributes + // ------------------------------------------------------------------------ + /** The TMF XY Chart reference */ + private TmfXYChartViewer fChartViewer; + /** The Trace reference */ + private ITmfTrace fTrace; + + // ------------------------------------------------------------------------ + // Constructors + // ------------------------------------------------------------------------ + /** + * Standard Constructor + * + * @param viewName + * The view name + */ + public TmfChartView(String viewName) { + super(viewName); + } + + // ------------------------------------------------------------------------ + // Accessors + // ------------------------------------------------------------------------ + /** + * Returns the TMF XY chart viewer implementation. + * + * @return the TMF XY chart viewer {@link TmfXYChartViewer} + */ + protected TmfXYChartViewer getChartViewer() { + return fChartViewer; + } + + /** + * Sets the TMF XY chart viewer implementation. + * + * @param chartViewer + * The TMF XY chart viewer {@link TmfXYChartViewer} + */ + protected void setChartViewer(TmfXYChartViewer chartViewer) { + fChartViewer = chartViewer; + } + + /** + * Returns the ITmfTrace implementation + * + * @return the ITmfTrace implementation {@link ITmfTrace} + */ + protected ITmfTrace getTrace() { + return fTrace; + } + + /** + * Sets the ITmfTrace implementation + * + * @param trace + * The ITmfTrace implementation {@link ITmfTrace} + */ + protected void setTrace(ITmfTrace trace) { + fTrace = trace; + } + + // ------------------------------------------------------------------------ + // Operations + // ------------------------------------------------------------------------ + @Override + public void createPartControl(Composite parent) { + ITmfTrace trace = getActiveTrace(); + if (trace != null) { + setTrace(trace); + loadTrace(); + } + } + + @Override + public void dispose() { + if (fChartViewer != null) { + fChartViewer.dispose(); + } + } + + /** + * Load the trace into view. + */ + protected void loadTrace() { + if (fChartViewer != null) { + fChartViewer.loadTrace(fTrace); + } + } + +}