X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=org.eclipse.tracecompass.tmf.ui%2Fsrc%2Forg%2Feclipse%2Ftracecompass%2Ftmf%2Fui%2Fwidgets%2Ftimegraph%2FTimeGraphViewer.java;h=7ec110db06ed6cd695b9aa63dbf3b2dea70c1995;hb=3ad34c5d3fbfeee1eeeda5c4fe2afa02d3bc6b2a;hp=857d5071badf16661712dbd6a23f7a83d25dbe3e;hpb=6b11be5292950be9835e2e899403384e03581a9a;p=deliverable%2Ftracecompass.git diff --git a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphViewer.java b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphViewer.java index 857d5071ba..7ec110db06 100644 --- a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphViewer.java +++ b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphViewer.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2007, 2014 Intel Corporation, Ericsson, others + * Copyright (c) 2007, 2015 Intel Corporation, Ericsson, others * 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 @@ -42,11 +42,15 @@ 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.ScrollBar; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Slider; import org.eclipse.tracecompass.internal.tmf.ui.Activator; import org.eclipse.tracecompass.internal.tmf.ui.ITmfImageConstants; import org.eclipse.tracecompass.internal.tmf.ui.Messages; +import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo; +import org.eclipse.tracecompass.tmf.ui.views.ITmfTimeAligned; import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.TimeGraphLegend; import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent; import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent; @@ -63,35 +67,33 @@ import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeForma /** * Generic time graph viewer implementation * - * @version 1.0 * @author Patrick Tasse, and others */ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { - /** Constant indicating that all levels of the time graph should be expanded - * @since 3.1 */ + /** Constant indicating that all levels of the time graph should be expanded */ public static final int ALL_LEVELS = AbstractTreeViewer.ALL_LEVELS; private static final int DEFAULT_NAME_WIDTH = 200; private static final int MIN_NAME_WIDTH = 6; private static final int MAX_NAME_WIDTH = 1000; private static final int DEFAULT_HEIGHT = 22; - private static final long RECENTERING_MARGIN_FACTOR = 50; private static final String HIDE_ARROWS_KEY = "hide.arrows"; //$NON-NLS-1$ private static final long DEFAULT_FREQUENCY = 1000000000L; + private static final int H_SCROLLBAR_MAX = Integer.MAX_VALUE - 1; private long fMinTimeInterval; private ITimeGraphEntry fSelectedEntry; - private long fBeginTime; - private long fEndTime; - private long fTime0; - private long fTime1; - private long fSelectionBegin = 0; - private long fSelectionEnd = 0; - private long fTime0Bound; - private long fTime1Bound; - private long fTime0ExtSynch = 0; - private long fTime1ExtSynch = 0; + private long fBeginTime = SWT.DEFAULT; // The user-specified bounds start time + private long fEndTime = SWT.DEFAULT; // The user-specified bounds end time + private long fTime0 = SWT.DEFAULT; // The current window start time + private long fTime1 = SWT.DEFAULT; // The current window end time + private long fSelectionBegin = SWT.DEFAULT; + private long fSelectionEnd = SWT.DEFAULT; + private long fTime0Bound = SWT.DEFAULT; // The bounds start time + private long fTime1Bound = SWT.DEFAULT; // The bounds end time + private long fTime0ExtSynch = SWT.DEFAULT; + private long fTime1ExtSynch = SWT.DEFAULT; private boolean fTimeRangeFixed; private int fNameWidthPref = DEFAULT_NAME_WIDTH; private int fMinNameWidth = MIN_NAME_WIDTH; @@ -100,6 +102,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { private TimeGraphControl fTimeGraphCtrl; private TimeGraphScale fTimeScaleCtrl; + private Slider fHorizontalScrollBar; private Slider fVerticalScrollBar; private TimeGraphColorScheme fColorScheme; private Object fInputElement; @@ -132,6 +135,78 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { private Action fFollowArrowFwdAction; private Action fFollowArrowBwdAction; + private ListenerNotifier fListenerNotifier; + + private Composite fTimeAlignedComposite; + + private class ListenerNotifier extends Thread { + private static final long DELAY = 400L; + private static final long POLLING_INTERVAL = 10L; + private long fLastUpdateTime = Long.MAX_VALUE; + private boolean fSelectionChanged = false; + private boolean fTimeRangeUpdated = false; + private boolean fTimeSelected = false; + + @Override + public void run() { + while ((System.currentTimeMillis() - fLastUpdateTime) < DELAY) { + try { + Thread.sleep(POLLING_INTERVAL); + } catch (Exception e) { + return; + } + } + Display.getDefault().asyncExec(new Runnable() { + @Override + public void run() { + if (fListenerNotifier != ListenerNotifier.this) { + return; + } + fListenerNotifier = null; + if (ListenerNotifier.this.isInterrupted() || fDataViewer.isDisposed()) { + return; + } + if (fSelectionChanged) { + fireSelectionChanged(fSelectedEntry); + } + if (fTimeRangeUpdated) { + fireTimeRangeUpdated(fTime0, fTime1); + } + if (fTimeSelected) { + fireTimeSelected(fSelectionBegin, fSelectionEnd); + } + } + }); + } + + public void selectionChanged() { + fSelectionChanged = true; + fLastUpdateTime = System.currentTimeMillis(); + } + + public void timeRangeUpdated() { + fTimeRangeUpdated = true; + fLastUpdateTime = System.currentTimeMillis(); + } + + public void timeSelected() { + fTimeSelected = true; + fLastUpdateTime = System.currentTimeMillis(); + } + + public boolean hasSelectionChanged() { + return fSelectionChanged; + } + + public boolean hasTimeRangeUpdated() { + return fTimeRangeUpdated; + } + + public boolean hasTimeSelected() { + return fTimeSelected; + } + } + /** * Standard constructor. *

@@ -144,15 +219,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { */ public TimeGraphViewer(Composite parent, int style) { createDataViewer(parent, style); - fTimeGraphContentProvider = new ITimeGraphContentProvider() { - @Override - public ITimeGraphEntry[] getElements(Object inputElement) { - if (inputElement instanceof ITimeGraphEntry[]) { - return (ITimeGraphEntry[]) inputElement; - } - return new ITimeGraphEntry[0]; - } - }; + fTimeGraphContentProvider = new TimeGraphContentProvider(); } /** @@ -160,8 +227,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * * @param timeGraphContentProvider * the timegraph content provider - * - * @since 3.0 */ public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider) { fTimeGraphContentProvider = timeGraphContentProvider; @@ -171,8 +236,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * Gets the timegraph content provider used by this timegraph viewer. * * @return the timegraph content provider - * - * @since 3.0 */ public ITimeGraphContentProvider getTimeGraphContentProvider() { return fTimeGraphContentProvider; @@ -197,19 +260,16 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * @param inputElement * The input of this time graph viewer, or null if * none - * - * @since 3.0 */ public void setInput(Object inputElement) { fInputElement = inputElement; ITimeGraphEntry[] input = fTimeGraphContentProvider.getElements(inputElement); - + fListenerNotifier = null; if (fTimeGraphCtrl != null) { setTimeRange(input); - fVerticalScrollBar.setEnabled(true); setTopIndex(0); - fSelectionBegin = 0; - fSelectionEnd = 0; + fSelectionBegin = SWT.DEFAULT; + fSelectionEnd = SWT.DEFAULT; fSelectedEntry = null; refreshAllData(input); } @@ -219,8 +279,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * Gets the input for this time graph viewer. * * @return The input of this time graph viewer, or null if none - * - * @since 3.0 */ public Object getInput() { return fInputElement; @@ -231,7 +289,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * * @param links * the links to display in this time graph combo - * @since 2.1 */ public void setLinks(List links) { if (fTimeGraphCtrl != null) { @@ -245,7 +302,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { public void refresh() { ITimeGraphEntry[] input = fTimeGraphContentProvider.getElements(fInputElement); setTimeRange(input); - fVerticalScrollBar.setEnabled(true); refreshAllData(input); } @@ -268,34 +324,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { resizeControls(); } - /** - * Handler for when the model is updated. Called from the display order in - * the API - * - * @param traces - * The traces in the model - * @param start - * The start time - * @param end - * The end time - * @param updateTimeBounds - * Should we updated the time bounds too - */ - public void modelUpdate(ITimeGraphEntry[] traces, long start, - long end, boolean updateTimeBounds) { - if (null != fTimeGraphCtrl) { - updateInternalData(traces, start, end); - if (updateTimeBounds) { - fTimeRangeFixed = true; - // set window to match limits - setStartFinishTime(fTime0Bound, fTime1Bound); - } else { - fTimeGraphCtrl.redraw(); - fTimeScaleCtrl.redraw(); - } - } - } - /** * @return The string representing the view type */ @@ -313,8 +341,8 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { void loadOptions() { fMinTimeInterval = 1; - fSelectionBegin = -1; - fSelectionEnd = -1; + fSelectionBegin = SWT.DEFAULT; + fSelectionEnd = SWT.DEFAULT; fNameWidth = Utils.loadIntOption(getPreferenceString("namewidth"), //$NON-NLS-1$ fNameWidthPref, fMinNameWidth, MAX_NAME_WIDTH); } @@ -350,7 +378,22 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { gl.horizontalSpacing = 0; fDataViewer.setLayout(gl); - fTimeScaleCtrl = new TimeGraphScale(fDataViewer, fColorScheme); + fTimeAlignedComposite = new Composite(fDataViewer, style) { + @Override + public void redraw() { + fDataViewer.redraw(); + super.redraw(); + } + }; + GridLayout gl2 = new GridLayout(1, false); + gl2.marginHeight = fBorderWidth; + gl2.marginWidth = 0; + gl2.verticalSpacing = 0; + gl2.horizontalSpacing = 0; + fTimeAlignedComposite.setLayout(gl2); + fTimeAlignedComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + fTimeScaleCtrl = new TimeGraphScale(fTimeAlignedComposite, fColorScheme); fTimeScaleCtrl.setTimeProvider(fTimeDataProvider); fTimeScaleCtrl.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false)); fTimeScaleCtrl.setHeight(fTimeScaleHeight); @@ -361,22 +404,12 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { } }); - fVerticalScrollBar = new Slider(fDataViewer, SWT.VERTICAL | SWT.NO_FOCUS); - fVerticalScrollBar.setLayoutData(new GridData(SWT.DEFAULT, SWT.FILL, false, true, 1, 2)); - fVerticalScrollBar.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - setTopIndex(fVerticalScrollBar.getSelection()); - } - }); - fVerticalScrollBar.setEnabled(false); - - fTimeGraphCtrl = createTimeGraphControl(fDataViewer, fColorScheme); + fTimeGraphCtrl = createTimeGraphControl(fTimeAlignedComposite, fColorScheme); fTimeGraphCtrl.setTimeProvider(this); fTimeGraphCtrl.setTimeGraphScale(fTimeScaleCtrl); fTimeGraphCtrl.addSelectionListener(this); - fTimeGraphCtrl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 2)); + fTimeGraphCtrl.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); fTimeGraphCtrl.addMouseWheelListener(new MouseWheelListener() { @Override public void mouseScrolled(MouseEvent e) { @@ -395,9 +428,50 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { } }); + fVerticalScrollBar = new Slider(fDataViewer, SWT.VERTICAL | SWT.NO_FOCUS); + fVerticalScrollBar.setLayoutData(new GridData(SWT.DEFAULT, SWT.FILL, false, true, 1, 1)); + fVerticalScrollBar.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + setTopIndex(fVerticalScrollBar.getSelection()); + } + }); + + fHorizontalScrollBar = new Slider(fDataViewer, SWT.HORIZONTAL | SWT.NO_FOCUS); + fHorizontalScrollBar.setLayoutData(new GridData(SWT.FILL, SWT.DEFAULT, true, false)); + fHorizontalScrollBar.addListener(SWT.MouseWheel, new Listener() { + @Override + public void handleEvent(Event event) { + if ((event.stateMask & SWT.MODIFIER_MASK) == SWT.CTRL) { + getTimeGraphControl().zoom(event.count > 0); + } else { + getTimeGraphControl().horizontalScroll(event.count > 0); + } + // don't handle the immediately following SWT.Selection event + event.doit = false; + } + }); + fHorizontalScrollBar.addListener(SWT.Selection, new Listener() { + @Override + public void handleEvent(Event event) { + int start = fHorizontalScrollBar.getSelection(); + long time0 = getTime0(); + long time1 = getTime1(); + long timeMin = getMinTime(); + long timeMax = getMaxTime(); + long delta = timeMax - timeMin; + + long range = time1 - time0; + time0 = timeMin + Math.round(delta * ((double) start / H_SCROLLBAR_MAX)); + time1 = time0 + range; + + setStartFinishTimeNotify(time0, time1); + } + }); + Composite filler = new Composite(fDataViewer, SWT.NONE); GridData gd = new GridData(SWT.DEFAULT, SWT.DEFAULT, false, false); - gd.heightHint = fTimeGraphCtrl.getHorizontalBar().getSize().y; + gd.heightHint = fHorizontalScrollBar.getSize().y; filler.setLayoutData(gd); filler.setLayout(new FillLayout()); @@ -409,6 +483,7 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { }); resizeControls(); fDataViewer.update(); + adjustHorizontalScrollBar(); adjustVerticalScrollBar(); return fDataViewer; } @@ -431,7 +506,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * @param colors * The color scheme * @return The new TimeGraphControl - * @since 2.0 */ protected TimeGraphControl createTimeGraphControl(Composite parent, TimeGraphColorScheme colors) { @@ -454,44 +528,78 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { if (fNameWidth < fMinNameWidth) { fNameWidth = fMinNameWidth; } + adjustHorizontalScrollBar(); adjustVerticalScrollBar(); } /** - * Try to set most convenient time range for display. + * Recalculate the time bounds based on the time graph entries, + * if the user-specified bound is set to SWT.DEFAULT. * - * @param traces - * The traces in the model - */ - public void setTimeRange(ITimeGraphEntry traces[]) { - fEndTime = 0; - fBeginTime = -1; - for (int i = 0; i < traces.length; i++) { - ITimeGraphEntry entry = traces[i]; - if (entry.getEndTime() >= entry.getStartTime() && entry.getEndTime() > 0) { - if (fBeginTime < 0 || entry.getStartTime() < fBeginTime) { - fBeginTime = entry.getStartTime(); - } - if (entry.getEndTime() > fEndTime) { - fEndTime = entry.getEndTime(); - } + * @param entries + * The root time graph entries in the model + */ + public void setTimeRange(ITimeGraphEntry entries[]) { + fTime0Bound = (fBeginTime != SWT.DEFAULT ? fBeginTime : fEndTime); + fTime1Bound = (fEndTime != SWT.DEFAULT ? fEndTime : fBeginTime); + if (fBeginTime != SWT.DEFAULT && fEndTime != SWT.DEFAULT) { + return; + } + if (entries == null || entries.length == 0) { + return; + } + if (fTime0Bound == SWT.DEFAULT) { + fTime0Bound = Long.MAX_VALUE; + } + if (fTime1Bound == SWT.DEFAULT) { + fTime1Bound = Long.MIN_VALUE; + } + for (ITimeGraphEntry entry : entries) { + setTimeRange(entry); + } + } + + private void setTimeRange(ITimeGraphEntry entry) { + if (fBeginTime == SWT.DEFAULT && entry.hasTimeEvents() && entry.getStartTime() != SWT.DEFAULT) { + fTime0Bound = Math.min(entry.getStartTime(), fTime0Bound); + } + if (fEndTime == SWT.DEFAULT && entry.hasTimeEvents() && entry.getEndTime() != SWT.DEFAULT) { + fTime1Bound = Math.max(entry.getEndTime(), fTime1Bound); + } + if (entry.hasChildren()) { + for (ITimeGraphEntry child : entry.getChildren()) { + setTimeRange(child); } } + } - if (fBeginTime < 0) { - fBeginTime = 0; + /** + * Set the time bounds to the provided values. + * + * @param beginTime + * The bounds begin time, or SWT.DEFAULT to use the input bounds + * @param endTime + * The bounds end time, or SWT.DEFAULT to use the input bounds + */ + public void setTimeBounds(long beginTime, long endTime) { + fBeginTime = beginTime; + fEndTime = endTime; + fTime0Bound = (fBeginTime != SWT.DEFAULT ? fBeginTime : fEndTime); + fTime1Bound = (fEndTime != SWT.DEFAULT ? fEndTime : fBeginTime); + if (fTime0Bound > fTime1Bound) { + // only possible if both are not default + fBeginTime = endTime; + fEndTime = beginTime; + fTime0Bound = fBeginTime; + fTime1Bound = fEndTime; } + adjustHorizontalScrollBar(); } /** - * Recalculate the time bounds + * Recalculate the current time window when bounds have changed. */ public void setTimeBounds() { - fTime0Bound = fBeginTime; - if (fTime0Bound < 0) { - fTime0Bound = 0; - } - fTime1Bound = fEndTime; if (!fTimeRangeFixed) { fTime0 = fTime0Bound; fTime1 = fTime1Bound; @@ -503,29 +611,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { } } - /** - * @param traces - * @param start - * @param end - */ - void updateInternalData(ITimeGraphEntry[] traces, long start, long end) { - ITimeGraphEntry[] realTraces = traces; - - if (null == realTraces) { - realTraces = new ITimeGraphEntry[0]; - } - if ((start == 0 && end == 0) || start < 0 || end < 0) { - // Start and end time are unspecified and need to be determined from - // individual processes - setTimeRange(realTraces); - } else { - fBeginTime = start; - fEndTime = end; - } - - refreshAllData(realTraces); - } - /** * @param traces */ @@ -612,7 +697,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { if (fNameWidth < MIN_NAME_WIDTH) { fNameWidth = MIN_NAME_WIDTH; } - fTimeGraphCtrl.adjustScrolls(); fTimeGraphCtrl.redraw(); fTimeScaleCtrl.redraw(); } @@ -643,17 +727,11 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { return fTime0Bound; } - /** - * @since 2.1 - */ @Override public long getSelectionBegin() { return fSelectionBegin; } - /** - * @since 2.1 - */ @Override public long getSelectionEnd() { return fSelectionEnd; @@ -662,16 +740,20 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { @Override public void setStartFinishTimeNotify(long time0, long time1) { setStartFinishTime(time0, time1); - notifyRangeListeners(fTime0, fTime1); + notifyRangeListeners(); } @Override public void notifyStartFinishTime() { - notifyRangeListeners(fTime0, fTime1); + notifyRangeListeners(); } @Override public void setStartFinishTime(long time0, long time1) { + /* if there is a pending time range, ignore this one */ + if (fListenerNotifier != null && fListenerNotifier.hasTimeRangeUpdated()) { + return; + } fTime0 = time0; if (fTime0 < fTime0Bound) { fTime0 = fTime0Bound; @@ -690,34 +772,11 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { fTime1 = Math.min(fTime1Bound, fTime0 + fMinTimeInterval); } fTimeRangeFixed = true; - fTimeGraphCtrl.adjustScrolls(); + adjustHorizontalScrollBar(); fTimeGraphCtrl.redraw(); fTimeScaleCtrl.redraw(); } - /** - * Set the time bounds to the provided values - * - * @param beginTime - * The start time of the window - * @param endTime - * The end time - */ - public void setTimeBounds(long beginTime, long endTime) { - if (endTime >= beginTime) { - fBeginTime = beginTime; - fEndTime = endTime; - fTime0Bound = beginTime; - fTime1Bound = endTime; - } else { - fBeginTime = 0; - fEndTime = 0; - fTime0Bound = 0; - fTime1Bound = 0; - } - fTimeGraphCtrl.adjustScrolls(); - } - @Override public void resetStartFinishTime() { setStartFinishTime(fTime0Bound, fTime1Bound); @@ -731,29 +790,37 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { @Override public void setSelectedTime(long time, boolean ensureVisible) { + /* if there is a pending time selection, ignore this one */ + if (fListenerNotifier != null && fListenerNotifier.hasTimeSelected()) { + return; + } setSelectedTimeInt(time, ensureVisible, false); } - /** - * @since 2.1 - */ @Override public void setSelectionRangeNotify(long beginTime, long endTime) { + long time0 = fTime0; + long time1 = fTime1; boolean changed = (beginTime != fSelectionBegin || endTime != fSelectionEnd); fSelectionBegin = Math.max(fTime0Bound, Math.min(fTime1Bound, beginTime)); fSelectionEnd = Math.max(fTime0Bound, Math.min(fTime1Bound, endTime)); + ensureVisible(fSelectionEnd); fTimeGraphCtrl.redraw(); fTimeScaleCtrl.redraw(); + if ((time0 != fTime0) || (time1 != fTime1)) { + notifyRangeListeners(); + } if (changed) { - notifyTimeListeners(fSelectionBegin, fSelectionEnd); + notifyTimeListeners(); } } - /** - * @since 2.1 - */ @Override public void setSelectionRange(long beginTime, long endTime) { + /* if there is a pending time selection, ignore this one */ + if (fListenerNotifier != null && fListenerNotifier.hasTimeSelected()) { + return; + } fSelectionBegin = Math.max(fTime0Bound, Math.min(fTime1Bound, beginTime)); fSelectionEnd = Math.max(fTime0Bound, Math.min(fTime1Bound, endTime)); fTimeGraphCtrl.redraw(); @@ -764,29 +831,8 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { long time0 = fTime0; long time1 = fTime1; if (ensureVisible) { - long timeSpace = (fTime1 - fTime0) / RECENTERING_MARGIN_FACTOR; - long timeMid = (fTime1 - fTime0) / 2; - if (time < fTime0 + timeSpace) { - long dt = fTime0 - time + timeMid; - fTime0 -= dt; - fTime1 -= dt; - } else if (time > fTime1 - timeSpace) { - long dt = time - fTime1 + timeMid; - fTime0 += dt; - fTime1 += dt; - } - if (fTime0 < fTime0Bound) { - fTime1 = Math.min(fTime1Bound, fTime1 + (fTime0Bound - fTime0)); - fTime0 = fTime0Bound; - } else if (fTime1 > fTime1Bound) { - fTime0 = Math.max(fTime0Bound, fTime0 - (fTime1 - fTime1Bound)); - fTime1 = fTime1Bound; - } + ensureVisible(time); } - if (fTime1 - fTime0 < fMinTimeInterval) { - fTime1 = Math.min(fTime1Bound, fTime0 + fMinTimeInterval); - } - fTimeGraphCtrl.adjustScrolls(); fTimeGraphCtrl.redraw(); fTimeScaleCtrl.redraw(); @@ -795,19 +841,43 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { fSelectionEnd = time; if (doNotify && ((time0 != fTime0) || (time1 != fTime1))) { - notifyRangeListeners(fTime0, fTime1); + notifyRangeListeners(); } if (doNotify && notifySelectedTime) { - notifyTimeListeners(fSelectionBegin, fSelectionEnd); + notifyTimeListeners(); } } + private void ensureVisible(long time) { + long timeMid = (fTime1 - fTime0) / 2; + if (time < fTime0) { + long dt = fTime0 - time + timeMid; + fTime0 -= dt; + fTime1 -= dt; + } else if (time > fTime1) { + long dt = time - fTime1 + timeMid; + fTime0 += dt; + fTime1 += dt; + } + if (fTime0 < fTime0Bound) { + fTime1 = Math.min(fTime1Bound, fTime1 + (fTime0Bound - fTime0)); + fTime0 = fTime0Bound; + } else if (fTime1 > fTime1Bound) { + fTime0 = Math.max(fTime0Bound, fTime0 - (fTime1 - fTime1Bound)); + fTime1 = fTime1Bound; + } + if (fTime1 - fTime0 < fMinTimeInterval) { + fTime1 = Math.min(fTime1Bound, fTime0 + fMinTimeInterval); + } + adjustHorizontalScrollBar(); + } + @Override public void widgetDefaultSelected(SelectionEvent e) { if (fSelectedEntry != getSelection()) { fSelectedEntry = getSelection(); - notifySelectionListeners(fSelectedEntry); + notifySelectionListeners(); } } @@ -815,23 +885,31 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { public void widgetSelected(SelectionEvent e) { if (fSelectedEntry != getSelection()) { fSelectedEntry = getSelection(); - notifySelectionListeners(fSelectedEntry); + notifySelectionListeners(); } } /** * Callback for when the next event is selected + * + * @param extend + * true to extend selection range, false for single selection + * @since 1.0 */ - public void selectNextEvent() { - fTimeGraphCtrl.selectNextEvent(); + public void selectNextEvent(boolean extend) { + fTimeGraphCtrl.selectNextEvent(extend); adjustVerticalScrollBar(); } /** * Callback for when the previous event is selected + * + * @param extend + * true to extend selection range, false for single selection + * @since 1.0 */ - public void selectPrevEvent() { - fTimeGraphCtrl.selectPrevEvent(); + public void selectPrevEvent(boolean extend) { + fTimeGraphCtrl.selectPrevEvent(extend); adjustVerticalScrollBar(); } @@ -900,7 +978,15 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { fSelectionListeners.remove(listener); } - private void notifySelectionListeners(ITimeGraphEntry selection) { + private void notifySelectionListeners() { + if (fListenerNotifier == null) { + fListenerNotifier = new ListenerNotifier(); + fListenerNotifier.start(); + } + fListenerNotifier.selectionChanged(); + } + + private void fireSelectionChanged(ITimeGraphEntry selection) { TimeGraphSelectionEvent event = new TimeGraphSelectionEvent(this, selection); for (ITimeGraphSelectionListener listener : fSelectionListeners) { @@ -928,7 +1014,15 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { fTimeListeners.remove(listener); } - private void notifyTimeListeners(long startTime, long endTime) { + private void notifyTimeListeners() { + if (fListenerNotifier == null) { + fListenerNotifier = new ListenerNotifier(); + fListenerNotifier.start(); + } + fListenerNotifier.timeSelected(); + } + + private void fireTimeSelected(long startTime, long endTime) { TimeGraphTimeEvent event = new TimeGraphTimeEvent(this, startTime, endTime); for (ITimeGraphTimeListener listener : fTimeListeners) { @@ -956,7 +1050,15 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { fRangeListeners.remove(listener); } - private void notifyRangeListeners(long startTime, long endTime) { + private void notifyRangeListeners() { + if (fListenerNotifier == null) { + fListenerNotifier = new ListenerNotifier(); + fListenerNotifier.start(); + } + fListenerNotifier.timeRangeUpdated(); + } + + private void fireTimeRangeUpdated(long startTime, long endTime) { // Check if the time has actually changed from last notification if (startTime != fTime0ExtSynch || endTime != fTime1ExtSynch) { // Notify Time Scale Selection Listeners @@ -1017,6 +1119,10 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * The trace that was selected */ public void setSelection(ITimeGraphEntry trace) { + /* if there is a pending selection, ignore this one */ + if (fListenerNotifier != null && fListenerNotifier.hasSelectionChanged()) { + return; + } fSelectedEntry = trace; fTimeGraphCtrl.selectItem(trace, false); adjustVerticalScrollBar(); @@ -1054,9 +1160,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { fTime1ExtSynch = fTime1; } - /** - * @since 2.0 - */ @Override public TimeFormat getTimeFormat() { return fTimeFormat; @@ -1065,7 +1168,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { /** * @param tf * the {@link TimeFormat} used to display timestamps - * @since 2.0 */ public void setTimeFormat(TimeFormat tf) { this.fTimeFormat = tf; @@ -1085,7 +1187,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * * @param clockFrequency * the clock frequency in Hz - * @since 3.2 */ public void setClockFrequency(long clockFrequency) { fClockFrequency = clockFrequency; @@ -1217,7 +1318,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * Returns the time graph control associated with this viewer. * * @return the time graph control - * @since 2.0 */ public TimeGraphControl getTimeGraphControl() { return fTimeGraphCtrl; @@ -1227,20 +1327,28 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * Returns the time graph scale associated with this viewer. * * @return the time graph scale - * @since 2.0 */ public TimeGraphScale getTimeGraphScale() { return fTimeScaleCtrl; } + /** + * Returns the composite containing all the controls that are time aligned, + * i.e. TimeGraphScale, TimeGraphControl. + * + * @return the time based composite + * @since 1.0 + */ + public Composite getTimeAlignedComposite() { + return fTimeAlignedComposite; + } + /** * Return the x coordinate corresponding to a time * * @param time * the time * @return the x coordinate corresponding to the time - * - * @since 2.0 */ public int getXForTime(long time) { return fTimeGraphCtrl.getXForTime(time); @@ -1252,8 +1360,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * @param x * the x coordinate * @return the time corresponding to the x coordinate - * - * @since 2.0 */ public long getTimeAtX(int x) { return fTimeGraphCtrl.getTimeAtX(x); @@ -1283,8 +1389,8 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * * @return The scroll bar */ - public ScrollBar getHorizontalBar() { - return fTimeGraphCtrl.getHorizontalBar(); + public Slider getHorizontalBar() { + return fHorizontalScrollBar; } /** @@ -1328,7 +1434,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * @param level * non-negative level, or ALL_LEVELS to expand all * levels of the tree - * @since 3.1 */ public void setAutoExpandLevel(int level) { fTimeGraphCtrl.setAutoExpandLevel(level); @@ -1340,7 +1445,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * @return non-negative level, or ALL_LEVELS if all levels of * the tree are expanded automatically * @see #setAutoExpandLevel - * @since 3.1 */ public int getAutoExpandLevel() { return fTimeGraphCtrl.getAutoExpandLevel(); @@ -1361,8 +1465,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { /** * Collapses all nodes of the viewer's tree, starting with the root. - * - * @since 2.0 */ public void collapseAll() { fTimeGraphCtrl.collapseAll(); @@ -1371,8 +1473,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { /** * Expands all nodes of the viewer's tree, starting with the root. - * - * @since 2.0 */ public void expandAll() { fTimeGraphCtrl.expandAll(); @@ -1470,8 +1570,9 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { if (fNextEventAction == null) { fNextEventAction = new Action() { @Override - public void run() { - selectNextEvent(); + public void runWithEvent(Event event) { + boolean extend = (event.stateMask & SWT.SHIFT) != 0; + selectNextEvent(extend); } }; @@ -1492,8 +1593,9 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { if (fPrevEventAction == null) { fPrevEventAction = new Action() { @Override - public void run() { - selectPrevEvent(); + public void runWithEvent(Event event) { + boolean extend = (event.stateMask & SWT.SHIFT) != 0; + selectPrevEvent(extend); } }; @@ -1595,8 +1697,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * or null * * @return The Action object - * - * @since 2.1 */ public Action getHideArrowsAction(final IDialogSettings dialogSettings) { if (fHideArrowsAction == null) { @@ -1638,15 +1738,14 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * Get the follow arrow forward action. * * @return The Action object - * - * @since 2.1 */ public Action getFollowArrowFwdAction() { if (fFollowArrowFwdAction == null) { fFollowArrowFwdAction = new Action() { @Override - public void run() { - fTimeGraphCtrl.followArrowFwd(); + public void runWithEvent(Event event) { + boolean extend = (event.stateMask & SWT.SHIFT) != 0; + fTimeGraphCtrl.followArrowFwd(extend); adjustVerticalScrollBar(); } }; @@ -1664,15 +1763,14 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * Get the follow arrow backward action. * * @return The Action object - * - * @since 2.1 */ public Action getFollowArrowBwdAction() { if (fFollowArrowBwdAction == null) { fFollowArrowBwdAction = new Action() { @Override - public void run() { - fTimeGraphCtrl.followArrowBwd(); + public void runWithEvent(Event event) { + boolean extend = (event.stateMask & SWT.SHIFT) != 0; + fTimeGraphCtrl.followArrowBwd(extend); adjustVerticalScrollBar(); } }; @@ -1686,6 +1784,23 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { return fFollowArrowBwdAction; } + private void adjustHorizontalScrollBar() { + long time0 = getTime0(); + long time1 = getTime1(); + long timeMin = getMinTime(); + long timeMax = getMaxTime(); + long delta = timeMax - timeMin; + int timePos = 0; + int thumb = H_SCROLLBAR_MAX; + if (delta != 0) { + // Thumb size (page size) + thumb = Math.max(1, (int) (H_SCROLLBAR_MAX * ((double) (time1 - time0) / delta))); + // At the beginning of visible window + timePos = (int) (H_SCROLLBAR_MAX * ((double) (time0 - timeMin) / delta)); + } + fHorizontalScrollBar.setValues(timePos, 0, H_SCROLLBAR_MAX, thumb, Math.max(1, thumb / 2), Math.max(2, thumb)); + } + private void adjustVerticalScrollBar() { int topIndex = fTimeGraphCtrl.getTopIndex(); int countPerPage = fTimeGraphCtrl.countPerPage(); @@ -1707,7 +1822,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * @param listener * a {@link MenuDetectListener} * @see org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl#addTimeGraphEntryMenuListener(org.eclipse.swt.events.MenuDetectListener) - * @since 1.2 */ public void addTimeGraphEntryMenuListener(MenuDetectListener listener) { fTimeGraphCtrl.addTimeGraphEntryMenuListener(listener); @@ -1717,7 +1831,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * @param listener * a {@link MenuDetectListener} * @see org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl#removeTimeGraphEntryMenuListener(org.eclipse.swt.events.MenuDetectListener) - * @since 1.2 */ public void removeTimeGraphEntryMenuListener(MenuDetectListener listener) { fTimeGraphCtrl.removeTimeGraphEntryMenuListener(listener); @@ -1727,7 +1840,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * @param listener * a {@link MenuDetectListener} * @see org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl#addTimeEventMenuListener(org.eclipse.swt.events.MenuDetectListener) - * @since 1.2 */ public void addTimeEventMenuListener(MenuDetectListener listener) { fTimeGraphCtrl.addTimeEventMenuListener(listener); @@ -1737,7 +1849,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { * @param listener * a {@link MenuDetectListener} * @see org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl#removeTimeEventMenuListener(org.eclipse.swt.events.MenuDetectListener) - * @since 1.2 */ public void removeTimeEventMenuListener(MenuDetectListener listener) { fTimeGraphCtrl.removeTimeEventMenuListener(listener); @@ -1746,7 +1857,6 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { /** * @param filter * The filter object to be attached to the view - * @since 2.0 */ public void addFilter(ViewerFilter filter) { fTimeGraphCtrl.addFilter(filter); @@ -1756,11 +1866,61 @@ public class TimeGraphViewer implements ITimeDataProvider, SelectionListener { /** * @param filter * The filter object to be attached to the view - * @since 2.0 */ public void removeFilter(ViewerFilter filter) { fTimeGraphCtrl.removeFilter(filter); refresh(); } + /** + * Return the time alignment information + * + * @return the time alignment information + * + * @see ITmfTimeAligned + * + * @since 1.0 + */ + public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() { + return fTimeGraphCtrl.getTimeViewAlignmentInfo(); + } + + /** + * Return the available width for the time-axis. + * + * @see ITmfTimeAligned + * + * @param requestedOffset + * the requested offset + * @return the available width for the time-axis + * + * @since 1.0 + */ + public int getAvailableWidth(int requestedOffset) { + int totalWidth = fTimeAlignedComposite.getSize().x; + return Math.min(totalWidth, Math.max(0, totalWidth - requestedOffset)); + } + + /** + * Perform the alignment operation. + * + * @param offset + * the alignment offset + * @param width + * the alignment width + * + * @see ITmfTimeAligned + * + * @since 1.0 + */ + public void performAlign(int offset, int width) { + fTimeGraphCtrl.performAlign(offset); + int alignmentWidth = width; + int size = fTimeAlignedComposite.getSize().x; + GridLayout layout = (GridLayout) fTimeAlignedComposite.getLayout(); + int marginSize = size - alignmentWidth - offset; + layout.marginRight = Math.max(0, marginSize); + fTimeAlignedComposite.layout(); + } + }