tmf: Align the time-axis for time range histogram
authorBernd Hufmann <Bernd.Hufmann@ericsson.com>
Mon, 4 May 2015 15:24:56 +0000 (11:24 -0400)
committerBernd Hufmann <bernd.hufmann@ericsson.com>
Mon, 11 May 2015 20:18:59 +0000 (16:18 -0400)
Change-Id: Ie1dfb34e9ffdbe881bb477622398dce44546529d
Signed-off-by: Bernd Hufmann <Bernd.Hufmann@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/47077
Reviewed-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Tested-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewed-by: Hudson CI
org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/Histogram.java
org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/HistogramView.java
org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/TimeRangeHistogram.java

index 16e92267a3abc252ee59f11f7b2173b1ba21848d..aa5adf40d29ec2e9c96e5f5bf51aec37015a4e61 100644 (file)
@@ -36,6 +36,7 @@ import org.eclipse.swt.graphics.Font;
 import org.eclipse.swt.graphics.FontData;
 import org.eclipse.swt.graphics.GC;
 import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
@@ -50,6 +51,8 @@ import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampDelta;
 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat;
+import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentSignal;
+import org.eclipse.tracecompass.tmf.ui.views.ITmfTimeAligned;
 import org.eclipse.tracecompass.tmf.ui.views.TmfView;
 
 /**
@@ -169,6 +172,8 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
      */
     protected Canvas fCanvas;
 
+    private Composite canvasComposite;
+
     /**
      * The histogram data model.
      */
@@ -219,12 +224,15 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
      */
     static boolean showTraces = true;
 
+
+    private boolean fSendTimeAlignSignals = false;
+
     // ------------------------------------------------------------------------
     // Construction
     // ------------------------------------------------------------------------
 
     /**
-     * Full constructor.
+     * Constructor.
      *
      * @param view
      *            A reference to the parent TMF view.
@@ -232,8 +240,23 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
      *            A parent composite
      */
     public Histogram(final TmfView view, final Composite parent) {
-        fParentView = view;
+        this(view, parent, false);
+    }
 
+    /**
+     * Full constructor.
+     *
+     * @param view
+     *            A reference to the parent TMF view.
+     * @param parent
+     *            A parent composite
+     * @param sendTimeAlignSignals
+     *            Flag to send time alignment signals or not
+     * @since 1.0
+     */
+    public Histogram(final TmfView view, final Composite parent, final boolean sendTimeAlignSignals) {
+        fParentView = view;
+        fSendTimeAlignSignals = sendTimeAlignSignals;
         fComposite = createWidget(parent);
         fDataModel = new HistogramDataModel();
         fDataModel.addHistogramListener(this);
@@ -304,7 +327,7 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
         fMaxNbEventsLabel.setLayoutData(gridData);
 
         // Histogram itself
-        Composite canvasComposite = new Composite(composite, SWT.BORDER);
+        canvasComposite = new Composite(composite, SWT.BORDER);
         gridData = new GridData();
         gridData.horizontalSpan = 2;
         gridData.verticalSpan = 2;
@@ -625,11 +648,17 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
                                 // Display histogram and update X-,Y-axis labels
                                 updateRangeTextControls();
                                 long maxNbEvents = HistogramScaledData.hideLostEvents ? fScaledData.fMaxValue : fScaledData.fMaxCombinedValue;
+                                String old = fMaxNbEventsLabel.getText();
                                 fMaxNbEventsLabel.setText(Long.toString(maxNbEvents));
                                 // The Y-axis area might need to be re-sized
                                 GridData gd = (GridData) fMaxNbEventsLabel.getLayoutData();
                                 gd.widthHint = Math.max(gd.widthHint, fMaxNbEventsLabel.computeSize(SWT.DEFAULT, SWT.DEFAULT).x);
                                 fMaxNbEventsLabel.getParent().layout();
+                                if (old.length() < fMaxNbEventsLabel.getText().length()) {
+                                    if ((fSendTimeAlignSignals) && (fParentView instanceof ITmfTimeAligned)) {
+                                        TmfSignalManager.dispatchSignal(new TmfTimeViewAlignmentSignal(this, ((ITmfTimeAligned) fParentView).getTimeViewAlignmentInfo(), true));
+                                    }
+                                }
                             }
                         }
                     }
@@ -878,6 +907,40 @@ public abstract class Histogram implements ControlListener, PaintListener, KeyLi
         imageGC.drawLine(center, (height / 2) - chHalfWidth, center, (height / 2) + chHalfWidth);
     }
 
+    /**
+     * Get the offset of the point area, relative to the histogram canvas
+     * 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() {
+        Point absCanvas = fCanvas.toDisplay(0, 0);
+        Point viewPoint = fComposite.getParent().toDisplay(0, 0);
+        return absCanvas.x - viewPoint.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() {
+        if (!fCanvas.isDisposed()) {
+            // Retrieve and normalize the data
+            return fComposite.getBounds().width;
+        }
+        return 0;
+    }
+
     // ------------------------------------------------------------------------
     // KeyListener
     // ------------------------------------------------------------------------
index fe35c90d06c9064387fda7e9e2c86ac784820371..799b2c5a1b411bd518154a40c7d32ab70f1e0657 100644 (file)
@@ -44,26 +44,33 @@ import org.eclipse.swt.layout.RowLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Sash;
 import org.eclipse.tracecompass.internal.tmf.ui.Activator;
 import org.eclipse.tracecompass.internal.tmf.ui.ITmfImageConstants;
 import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
 import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest.ExecutionType;
-import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalThrottler;
-import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceRangeUpdatedSignal;
 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
 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.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;
 import org.eclipse.ui.IActionBars;
 
@@ -82,7 +89,7 @@ import org.eclipse.ui.IActionBars;
  * @version 2.0
  * @author Francois Chouinard
  */
-public class HistogramView extends TmfView {
+public class HistogramView extends TmfView implements ITmfTimeAligned {
 
     // ------------------------------------------------------------------------
     // Constants
@@ -95,19 +102,12 @@ public class HistogramView extends TmfView {
 
     private static final Image LINK_IMG = Activator.getDefault().getImageFromPath(ITmfImageConstants.IMG_UI_LINK);
 
-    private static final int HISTOGRAM_MARGIN_TOP = 5;
-    private static final int HISTOGRAM_MARGIN_LEFT = 5;
-    private static final int HISTOGRAM_MARGIN_RIGHT = 5;
-
     private static final int[] DEFAULT_WEIGHTS = {1, 3};
 
     // ------------------------------------------------------------------------
     // Attributes
     // ------------------------------------------------------------------------
 
-    // Parent widget
-    private Composite fParent;
-
     // The current trace
     private ITmfTrace fTrace;
 
@@ -120,8 +120,12 @@ public class HistogramView extends TmfView {
     private long fSelectionBeginTime;
     private long fSelectionEndTime;
 
+    // SashForm
+    private SashForm fSashForm;
     private ScrolledComposite fScrollComposite;
     private Composite fTimeControlsComposite;
+    private Composite fTimeRangeComposite;
+    private Listener fSashDragListener;
 
     // Time controls
     private HistogramTextControl fSelectionStartControl;
@@ -199,8 +203,7 @@ public class HistogramView extends TmfView {
 
     @Override
     public void createPartControl(Composite parent) {
-
-        fParent = parent;
+        super.createPartControl(parent);
 
         // Control labels
         final String selectionStartLabel = Messages.HistogramView_selectionStartLabel;
@@ -210,7 +213,7 @@ public class HistogramView extends TmfView {
         // --------------------------------------------------------------------
         // Set the HistogramView layout
         // --------------------------------------------------------------------
-        Composite viewComposite = new Composite(fParent, SWT.FILL);
+        Composite viewComposite = new Composite(getParentComposite(), SWT.FILL);
         GridLayout gridLayout = new GridLayout(1, false);
         gridLayout.verticalSpacing = 0;
         gridLayout.marginHeight = 0;
@@ -220,14 +223,38 @@ public class HistogramView extends TmfView {
         // --------------------------------------------------------------------
         // Add a sash for time controls and time range histogram
         // --------------------------------------------------------------------
-        SashForm sashForm = new SashForm(viewComposite, SWT.NONE);
+
+        /*
+         * The ScrolledComposite preferred size can be larger than its visible
+         * width. This affects the preferred width of the SashForm. Set the
+         * preferred width to 1 to prevent it from affecting the preferred width
+         * of the view composite.
+         */
+        fSashForm = new SashForm(viewComposite, SWT.NONE) {
+            @Override
+            public Point computeSize(int wHint, int hHint) {
+                Point computedSize = super.computeSize(wHint, hHint);
+                if (wHint == SWT.DEFAULT) {
+                    return new Point(1, computedSize.y);
+                }
+                return computedSize;
+            }
+            @Override
+            public Point computeSize(int wHint, int hHint, boolean changed) {
+                Point computedSize = super.computeSize(wHint, hHint, changed);
+                if (wHint == SWT.DEFAULT) {
+                    return new Point(1, computedSize.y);
+                }
+                return computedSize;
+            }
+        };
         GridData gridData = new GridData(GridData.FILL, GridData.FILL, false, true);
-        sashForm.setLayoutData(gridData);
+        fSashForm.setLayoutData(gridData);
 
         // --------------------------------------------------------------------
         // Time controls
         // --------------------------------------------------------------------
-        fScrollComposite = new PackedScrolledComposite(sashForm, SWT.H_SCROLL | SWT.V_SCROLL);
+        fScrollComposite = new PackedScrolledComposite(fSashForm, SWT.H_SCROLL | SWT.V_SCROLL);
         fTimeControlsComposite = new Composite(fScrollComposite, SWT.NONE);
         fScrollComposite.setContent(fTimeControlsComposite);
         gridLayout = new GridLayout(1, false);
@@ -291,30 +318,24 @@ public class HistogramView extends TmfView {
         // --------------------------------------------------------------------
         // Time range histogram
         // --------------------------------------------------------------------
-        Composite timeRangeComposite = new Composite(sashForm, SWT.NONE);
+        fTimeRangeComposite = new Composite(fSashForm, SWT.NONE);
         gridLayout = new GridLayout(1, true);
         gridLayout.marginTop = 0;
-        gridLayout.marginLeft = HISTOGRAM_MARGIN_LEFT;
-        gridLayout.marginRight = HISTOGRAM_MARGIN_RIGHT;
-        timeRangeComposite.setLayout(gridLayout);
+        gridLayout.marginWidth = 0;
+        fTimeRangeComposite.setLayout(gridLayout);
 
         // Use remaining horizontal space
         gridData = new GridData(GridData.FILL, GridData.FILL, true, true);
-        timeRangeComposite.setLayoutData(gridData);
+        fTimeRangeComposite.setLayoutData(gridData);
 
         // Histogram
-        fTimeRangeHistogram = new TimeRangeHistogram(this, timeRangeComposite);
+        fTimeRangeHistogram = new TimeRangeHistogram(this, fTimeRangeComposite, true);
 
         // --------------------------------------------------------------------
         // Full range histogram
         // --------------------------------------------------------------------
         final Composite fullRangeComposite = new Composite(viewComposite, SWT.FILL);
         gridLayout = new GridLayout(1, true);
-        gridLayout.marginTop = HISTOGRAM_MARGIN_TOP;
-        gridLayout.marginLeft = HISTOGRAM_MARGIN_LEFT;
-        gridLayout.marginRight = HISTOGRAM_MARGIN_RIGHT;
-        gridLayout.marginHeight = 0;
-        gridLayout.marginWidth = 0;
         fullRangeComposite.setLayout(gridLayout);
 
         // Use remaining horizontal space
@@ -340,8 +361,32 @@ public class HistogramView extends TmfView {
             traceSelected(new TmfTraceSelectedSignal(this, trace));
         }
 
-        sashForm.setVisible(true);
-        sashForm.setWeights(DEFAULT_WEIGHTS);
+        fSashForm.setVisible(true);
+        fSashForm.setWeights(DEFAULT_WEIGHTS);
+
+        fTimeControlsComposite.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
@@ -350,7 +395,66 @@ public class HistogramView extends TmfView {
     }
 
     void refresh() {
-        fParent.layout(true);
+       getParentComposite().layout(true);
+    }
+
+    /**
+     * @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() + fTimeRangeHistogram.getPointAreaOffset();
+        return curTimeAxisOffset;
+    }
+
+    /**
+     * @since 1.0
+     */
+    @Override
+    public int getAvailableWidth(int requestedOffset) {
+        int pointAreaWidth = fTimeRangeHistogram.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) fTimeRangeComposite.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 = fTimeRangeHistogram.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();
+
+        // calculate right margin
+        GridLayout layout = (GridLayout) fTimeRangeComposite.getLayout();
+        int timeBasedControlsWidth = fTimeRangeComposite.getSize().x;
+        int marginSize = timeBasedControlsWidth - width - plotAreaOffset;
+        layout.marginRight = Math.max(0, marginSize);
+        fTimeRangeComposite.layout();
     }
 
     // ------------------------------------------------------------------------
@@ -552,7 +656,7 @@ public class HistogramView extends TmfView {
 
     private void loadTrace() {
         initializeHistograms();
-        fParent.redraw();
+        getParentComposite().redraw();
     }
 
     /**
@@ -661,7 +765,7 @@ public class HistogramView extends TmfView {
             Display.getDefault().asyncExec(new Runnable() {
                 @Override
                 public void run() {
-                    if (fParent.isDisposed()) {
+                    if (getParentComposite().isDisposed()) {
                         return;
                     }
                     selectionRangeUpdated(signal);
@@ -691,7 +795,7 @@ public class HistogramView extends TmfView {
             Display.getDefault().asyncExec(new Runnable() {
                 @Override
                 public void run() {
-                    if (fParent.isDisposed()) {
+                    if (getParentComposite().isDisposed()) {
                         return;
                     }
                     windowRangeUpdated(signal);
index 3d9563094d6aef7ffb05e1734e1bed7228fe0c15..c4ea220425884ad444a5be0f4e17648fb494cca9 100644 (file)
@@ -50,15 +50,30 @@ public class TimeRangeHistogram extends Histogram {
     // Constructor
     // ------------------------------------------------------------------------
     /**
-     * Constructor
+     * Constructor.
+     *
+     * @param view
+     *            A reference to the parent TMF view.
+     * @param parent
+     *            A parent composite
+     */
+    public TimeRangeHistogram(HistogramView view, Composite parent) {
+        this(view, parent, false);
+    }
+
+    /**
+     * Full Constructor
      *
      * @param view
      *            The parent histogram view
      * @param parent
      *            The parent composite
+     * @param sendTimeAlignSignals
+     *            Flag to send time alignment signals or not
+     * @since 1.0
      */
-    public TimeRangeHistogram(HistogramView view, Composite parent) {
-        super(view, parent);
+    public TimeRangeHistogram(HistogramView view, Composite parent, boolean sendTimeAlignSignals) {
+        super(view, parent, sendTimeAlignSignals);
         fZoom = new HistogramZoom(this, getStartTime(), getTimeLimit());
     }
 
This page took 0.033626 seconds and 5 git commands to generate.