From: Bernd Hufmann Date: Mon, 4 May 2015 15:24:56 +0000 (-0400) Subject: tmf: Align the time-axis for time range histogram X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=e8c79054ccf8073df417cbdae865251ad5512933;p=deliverable%2Ftracecompass.git tmf: Align the time-axis for time range histogram Change-Id: Ie1dfb34e9ffdbe881bb477622398dce44546529d Signed-off-by: Bernd Hufmann Reviewed-on: https://git.eclipse.org/r/47077 Reviewed-by: Marc-Andre Laperle Tested-by: Marc-Andre Laperle Reviewed-by: Hudson CI --- diff --git a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/Histogram.java b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/Histogram.java index 16e92267a3..aa5adf40d2 100644 --- a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/Histogram.java +++ b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/Histogram.java @@ -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 // ------------------------------------------------------------------------ diff --git a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/HistogramView.java b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/HistogramView.java index fe35c90d06..799b2c5a1b 100644 --- a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/HistogramView.java +++ b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/HistogramView.java @@ -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); diff --git a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/TimeRangeHistogram.java b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/TimeRangeHistogram.java index 3d9563094d..c4ea220425 100644 --- a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/TimeRangeHistogram.java +++ b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/histogram/TimeRangeHistogram.java @@ -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()); }