tmf: Align the time-axis for the CPU usage view
authorMarc-Andre Laperle <marc-andre.laperle@ericsson.com>
Wed, 29 Apr 2015 18:29:01 +0000 (14:29 -0400)
committerMarc-Andre Laperle <marc-andre.laperle@ericsson.com>
Thu, 7 May 2015 17:49:26 +0000 (13:49 -0400)
Change-Id: I4eef728afc1092ee0fe9b340af97bf4345aa2d2b
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/46811
Reviewed-by: Hudson CI
Reviewed-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
Tested-by: Bernd Hufmann <bernd.hufmann@ericsson.com>
org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/cpuusage/CpuUsageView.java
org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/xycharts/TmfXYChartViewer.java
org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/xycharts/linecharts/TmfCommonXLineChartViewer.java

index eef8c1d3e8686d58a04bee866a2e646866aa0aab..4667ca124aa848b078a2ef56e3a668ed3a155e49 100644 (file)
@@ -18,11 +18,24 @@ import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.SelectionChangedEvent;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.SashForm;
-import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+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.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Sash;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
+import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
+import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentSignal;
+import org.eclipse.tracecompass.tmf.ui.views.ITmfTimeAligned;
 import org.eclipse.tracecompass.tmf.ui.views.TmfView;
 
 /**
@@ -33,7 +46,7 @@ import org.eclipse.tracecompass.tmf.ui.views.TmfView;
  *
  * @author Geneviève Bastien
  */
-public class CpuUsageView extends TmfView {
+public class CpuUsageView extends TmfView implements ITmfTimeAligned {
 
     /** ID string */
     public static final String ID = "org.eclipse.tracecompass.analysis.os.linux.views.cpuusage"; //$NON-NLS-1$
@@ -41,6 +54,11 @@ public class CpuUsageView extends TmfView {
     private CpuUsageComposite fTreeViewer = null;
     private CpuUsageXYViewer fXYViewer = null;
 
+    private SashForm fSashForm;
+    private Listener fSashDragListener;
+    /** A composite that allows us to add margins */
+    private Composite fXYViewerContainer;
+
     /**
      * Constructor
      */
@@ -50,13 +68,21 @@ public class CpuUsageView extends TmfView {
 
     @Override
     public void createPartControl(Composite parent) {
+        super.createPartControl(parent);
+
+        fSashForm = new SashForm(parent, SWT.NONE);
 
-        final SashForm sash = new SashForm(parent, SWT.NONE);
+        fTreeViewer = new CpuUsageComposite(fSashForm);
 
-        fTreeViewer = new CpuUsageComposite(sash);
+        fXYViewerContainer = new Composite(fSashForm, SWT.NONE);
+        GridLayout layout = new GridLayout();
+        layout.marginHeight = 0;
+        layout.marginWidth = 0;
+        fXYViewerContainer.setLayout(layout);
 
         /* Build the XY chart part of the view */
-        fXYViewer = new CpuUsageXYViewer(sash);
+        fXYViewer = new CpuUsageXYViewer(fXYViewerContainer);
+        fXYViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
 
         /* Add selection listener to tree viewer */
         fTreeViewer.addSelectionChangeListener(new ISelectionChangedListener() {
@@ -74,8 +100,6 @@ public class CpuUsageView extends TmfView {
             }
         });
 
-        sash.setLayout(new FillLayout());
-
         /* Initialize the viewers with the currently selected trace */
         ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace();
         if (trace != null) {
@@ -83,7 +107,37 @@ public class CpuUsageView extends TmfView {
             fTreeViewer.traceSelected(signal);
             fXYViewer.traceSelected(signal);
         }
+        fTreeViewer.getControl().addControlListener(new ControlAdapter() {
+            @Override
+            public void controlResized(ControlEvent e) {
+                super.controlResized(e);
+            }
+        });
 
+        fXYViewer.getControl().addPaintListener(new PaintListener() {
+            @Override
+            public void paintControl(PaintEvent e) {
+                // Sashes in a SashForm are being created on layout so add the
+                // drag listener here
+                if (fSashDragListener == null) {
+                    for (Control control : fSashForm.getChildren()) {
+                        if (control instanceof Sash) {
+                            fSashDragListener = new Listener() {
+
+                                @Override
+                                public void handleEvent(Event event) {
+                                    TmfSignalManager.dispatchSignal(new TmfTimeViewAlignmentSignal(fSashForm, getTimeViewAlignmentInfo()));
+                                }
+                            };
+                            control.removePaintListener(this);
+                            control.addListener(SWT.Selection, fSashDragListener);
+                            // There should be only one sash
+                            break;
+                        }
+                    }
+                }
+            }
+        });
     }
 
     @Override
@@ -101,4 +155,62 @@ public class CpuUsageView extends TmfView {
         }
     }
 
+    /**
+     * @since 1.0
+     */
+    @Override
+    public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
+        if (fSashForm == null) {
+            return null;
+        }
+
+        return new TmfTimeViewAlignmentInfo(fSashForm.getShell(), fSashForm.toDisplay(0, 0), getTimeAxisOffset());
+    }
+
+    private int getTimeAxisOffset() {
+        int[] weights = fSashForm.getWeights();
+        int width = (int) (((float) weights[0] / (weights[0] + weights[1])) * fSashForm.getBounds().width);
+        int curTimeAxisOffset = width + fSashForm.getSashWidth() + fXYViewer.getPointAreaOffset();
+        return curTimeAxisOffset;
+    }
+
+    /**
+     * @since 1.0
+     */
+    @Override
+    public int getAvailableWidth(int requestedOffset) {
+        int pointAreaWidth = fXYViewer.getPointAreaWidth();
+        int curTimeAxisOffset = getTimeAxisOffset();
+        if (pointAreaWidth <= 0) {
+            pointAreaWidth = fSashForm.getBounds().width - curTimeAxisOffset;
+        }
+        // TODO this is just an approximation that assumes that the end will be at the same position but that can change for a different data range/scaling
+        int endOffset = curTimeAxisOffset + pointAreaWidth;
+        GridLayout layout = (GridLayout) fXYViewerContainer.getLayout();
+        int endOffsetWithoutMargin = endOffset + layout.marginRight;
+        int availableWidth = endOffsetWithoutMargin - requestedOffset;
+        availableWidth = Math.min(fSashForm.getBounds().width, Math.max(0, availableWidth));
+        return availableWidth;
+    }
+
+    /**
+     * @since 1.0
+     */
+    @Override
+    public void performAlign(int offset, int width) {
+        int plotAreaOffset = fXYViewer.getPointAreaOffset();
+        int sashOffset = Math.max(1, offset - plotAreaOffset);
+        int total = fSashForm.getBounds().width;
+        int width1 = (int) (sashOffset / (float) total * 1000);
+        int width2 = (int) ((total - sashOffset) / (float) total * 1000);
+        fSashForm.setWeights(new int[] { width1, width2 });
+        fSashForm.layout();
+
+        Composite composite = fXYViewerContainer;
+        GridLayout layout = (GridLayout) composite.getLayout();
+        int timeAxisWidth = getAvailableWidth(offset);
+        int marginSize = timeAxisWidth - width;
+        layout.marginRight = Math.max(0, marginSize);
+        composite.layout();
+    }
 }
index 0aec6b89e8ba506deee1a41e85528178e7c57e3a..73aee31787bf9c4c49e8546d354a50620f06ad39 100644 (file)
@@ -16,10 +16,10 @@ 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.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
-import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
 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.trace.ITmfTrace;
 import org.eclipse.tracecompass.tmf.ui.viewers.TmfTimeViewer;
 import org.swtchart.Chart;
@@ -51,6 +51,12 @@ public abstract class TmfXYChartViewer extends TmfTimeViewer implements ITmfChar
     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;
+
 
     // ------------------------------------------------------------------------
     // Constructors
@@ -354,4 +360,72 @@ public abstract class TmfXYChartViewer extends TmfTimeViewer implements ITmfChar
         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];
+            long windowStartTime = getWindowStartTime() - getTimeOffset();
+            pixelCoordinate = axis.getPixelCoordinate(windowStartTime - 1);
+        }
+        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 && fSwtChart.getSeriesSet().getSeries().length > 0) {
+            IAxis axis = xAxes[0];
+            int x1 = getPointAreaOffset();
+            long windowEndTime = getWindowEndTime() - getTimeOffset();
+            int x2 = axis.getPixelCoordinate(windowEndTime - 1);
+            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;
+    }
 }
index e766dc9ea293df066eadeaeee49cac5a629d0289..96cc78286f7d948901316dccb81ef2165bbba9ac 100644 (file)
@@ -19,10 +19,14 @@ import java.util.Map.Entry;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Display;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import org.eclipse.tracecompass.tmf.ui.TmfUiRefreshHandler;
+import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
+import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentSignal;
 import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.TmfChartTimeStampFormat;
 import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.TmfXYChartViewer;
 import org.swtchart.IAxisTick;
@@ -352,6 +356,16 @@ public abstract class TmfCommonXLineChartViewer extends TmfXYChartViewer {
                         getSwtChart().getAxisSet().getYAxis(0).setRange(new Range(miny, maxy));
                     }
                     getSwtChart().redraw();
+
+                    if (isSendTimeAlignSignals()) {
+                        // The width of the chart might have changed and its time
+                        // axis might be misaligned with the other views
+                        Point viewPos = TmfCommonXLineChartViewer.this.getParent().getParent().toDisplay(0, 0);
+                        int axisPos = getSwtChart().toDisplay(0, 0).x + getPointAreaOffset();
+                        int timeAxisOffset = axisPos - viewPos.x;
+                        TmfTimeViewAlignmentInfo timeAlignmentInfo = new TmfTimeViewAlignmentInfo(getControl().getShell(), viewPos, timeAxisOffset);
+                        TmfSignalManager.dispatchSignal(new TmfTimeViewAlignmentSignal(TmfCommonXLineChartViewer.this, timeAlignmentInfo, true));
+                    }
                 }
             }
         });
This page took 0.03111 seconds and 5 git commands to generate.