/******************************************************************************* * Copyright (c) 2009, 2013 Ericsson * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * William Bourque - Initial API and implementation * Yuriy Vashchuk - GUI reorganisation, simplification and some related code improvements. * Yuriy Vashchuk - Histograms optimisation. * Yuriy Vashchuk - Histogram Canvas Heritage correction * Francois Chouinard - Cleanup and refactoring * Francois Chouinard - Moved from LTTng to TMF * Patrick Tasse - Update for mouse wheel zoom * Xavier Raynaud - Support multi-trace coloring *******************************************************************************/ package fr.inria.linuxtools.tmf.ui.views.histogram; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.Separator; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CLabel; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseWheelListener; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; 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.Label; import org.eclipse.ui.IActionBars; import fr.inria.linuxtools.internal.tmf.ui.Activator; import fr.inria.linuxtools.internal.tmf.ui.ITmfImageConstants; import fr.inria.linuxtools.tmf.core.request.ITmfEventRequest; import fr.inria.linuxtools.tmf.core.request.ITmfEventRequest.ExecutionType; import fr.inria.linuxtools.tmf.core.signal.TmfRangeSynchSignal; import fr.inria.linuxtools.tmf.core.signal.TmfSignalHandler; import fr.inria.linuxtools.tmf.core.signal.TmfSignalThrottler; import fr.inria.linuxtools.tmf.core.signal.TmfTimeSynchSignal; import fr.inria.linuxtools.tmf.core.signal.TmfTraceClosedSignal; import fr.inria.linuxtools.tmf.core.signal.TmfTraceOpenedSignal; import fr.inria.linuxtools.tmf.core.signal.TmfTraceRangeUpdatedSignal; import fr.inria.linuxtools.tmf.core.signal.TmfTraceSelectedSignal; import fr.inria.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal; import fr.inria.linuxtools.tmf.core.timestamp.ITmfTimestamp; import fr.inria.linuxtools.tmf.core.timestamp.TmfTimeRange; import fr.inria.linuxtools.tmf.core.timestamp.TmfTimestamp; import fr.inria.linuxtools.tmf.core.trace.ITmfTrace; import fr.inria.linuxtools.tmf.core.trace.TmfTraceManager; import fr.inria.linuxtools.tmf.ui.views.TmfView; /** * The purpose of this view is to provide graphical time distribution statistics about the trace events. * <p> * The view is composed of two histograms and two controls: * <ul> * <li>an event distribution histogram for the whole trace; * <li>an event distribution histogram for current time window (window span); * <li>the timestamp of the currently selected event; * <li>the window span (size of the time window of the smaller histogram). * </ul> * The histograms x-axis show their respective time range. * * @version 2.0 * @author Francois Chouinard */ public class HistogramView extends TmfView { // ------------------------------------------------------------------------ // Constants // ------------------------------------------------------------------------ /** * The view ID as defined in plugin.xml */ public static final String ID = "fr.inria.linuxtools.tmf.ui.views.histogram"; //$NON-NLS-1$ private static final Image LINK_IMG = Activator.getDefault().getImageFromPath("/icons/etool16/link.gif"); //$NON-NLS-1$ // ------------------------------------------------------------------------ // Attributes // ------------------------------------------------------------------------ // Parent widget private Composite fParent; // The current trace private ITmfTrace fTrace; // Current timestamp/time window - everything in the TIME_SCALE private long fTraceStartTime; private long fTraceEndTime; private long fWindowStartTime; private long fWindowEndTime; private long fWindowSpan; private long fSelectionBeginTime; private long fSelectionEndTime; // Time controls private HistogramTextControl fSelectionStartControl; private HistogramTextControl fSelectionEndControl; private HistogramTextControl fTimeSpanControl; // Link private Label fLinkButton; private boolean fLinkState; // Histogram/request for the full trace range private static FullTraceHistogram fFullTraceHistogram; private HistogramRequest fFullTraceRequest; // Histogram/request for the selected time range private static TimeRangeHistogram fTimeRangeHistogram; private HistogramRequest fTimeRangeRequest; // Legend area private Composite fLegendArea; private Image[] fLegendImages; // Throttlers for the time sync and time-range sync signals private final TmfSignalThrottler fTimeSyncThrottle; private final TmfSignalThrottler fTimeRangeSyncThrottle; // Action for toggle showing the lost events private Action hideLostEventsAction; // Action for toggle showing the traces private Action showTraceAction; // ------------------------------------------------------------------------ // Constructor // ------------------------------------------------------------------------ /** * Default constructor */ public HistogramView() { super(ID); fTimeSyncThrottle = new TmfSignalThrottler(this, 200); fTimeRangeSyncThrottle = new TmfSignalThrottler(this, 200); } @Override public void dispose() { if ((fTimeRangeRequest != null) && !fTimeRangeRequest.isCompleted()) { fTimeRangeRequest.cancel(); } if ((fFullTraceRequest != null) && !fFullTraceRequest.isCompleted()) { fFullTraceRequest.cancel(); } fFullTraceHistogram.dispose(); fTimeRangeHistogram.dispose(); fSelectionStartControl.dispose(); fSelectionEndControl.dispose(); fTimeSpanControl.dispose(); super.dispose(); } // ------------------------------------------------------------------------ // TmfView // ------------------------------------------------------------------------ @Override public void createPartControl(Composite parent) { fParent = parent; // Control labels final String selectionStartLabel = Messages.HistogramView_selectionStartLabel; final String selectionEndLabel = Messages.HistogramView_selectionEndLabel; final String windowSpanLabel = Messages.HistogramView_windowSpanLabel; // -------------------------------------------------------------------- // Set the HistogramView layout // -------------------------------------------------------------------- Composite viewComposite = new Composite(fParent, SWT.FILL); GridLayout gridLayout = new GridLayout(); gridLayout.numColumns = 2; gridLayout.horizontalSpacing = 5; gridLayout.verticalSpacing = 0; gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; viewComposite.setLayout(gridLayout); // -------------------------------------------------------------------- // Time controls // -------------------------------------------------------------------- Composite controlsComposite = new Composite(viewComposite, SWT.NONE); gridLayout = new GridLayout(); gridLayout.numColumns = 2; gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; gridLayout.horizontalSpacing = 5; gridLayout.verticalSpacing = 1; gridLayout.makeColumnsEqualWidth = false; controlsComposite.setLayout(gridLayout); GridData gridData = new GridData(SWT.FILL, SWT.CENTER, false, false); controlsComposite.setLayoutData(gridData); Composite selectionGroup = new Composite(controlsComposite, SWT.BORDER); gridLayout = new GridLayout(); gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; gridLayout.horizontalSpacing = 0; gridLayout.verticalSpacing = 0; selectionGroup.setLayout(gridLayout); // Selection start control gridData = new GridData(); gridData.horizontalAlignment = SWT.FILL; gridData.verticalAlignment = SWT.CENTER; fSelectionStartControl = new HistogramSelectionStartControl(this, selectionGroup, selectionStartLabel, 0L); fSelectionStartControl.setLayoutData(gridData); fSelectionStartControl.setValue(Long.MIN_VALUE); // Selection end control gridData = new GridData(); gridData.horizontalAlignment = SWT.FILL; gridData.verticalAlignment = SWT.CENTER; fSelectionEndControl = new HistogramSelectionEndControl(this, selectionGroup, selectionEndLabel, 0L); fSelectionEndControl.setLayoutData(gridData); fSelectionEndControl.setValue(Long.MIN_VALUE); // Link button gridData = new GridData(); fLinkButton = new Label(controlsComposite, SWT.NONE); fLinkButton.setImage(LINK_IMG); fLinkButton.setLayoutData(gridData); addLinkButtonListeners(); // Window span time control gridData = new GridData(); gridData.horizontalAlignment = SWT.FILL; gridData.verticalAlignment = SWT.CENTER; fTimeSpanControl = new HistogramTimeRangeControl(this, controlsComposite, windowSpanLabel, 0L); fTimeSpanControl.setLayoutData(gridData); fTimeSpanControl.setValue(Long.MIN_VALUE); // -------------------------------------------------------------------- // Time range histogram // -------------------------------------------------------------------- Composite timeRangeComposite = new Composite(viewComposite, SWT.NONE); gridLayout = new GridLayout(); gridLayout.numColumns = 1; gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; gridLayout.marginTop = 5; gridLayout.horizontalSpacing = 0; gridLayout.verticalSpacing = 0; gridLayout.marginLeft = 5; gridLayout.marginRight = 5; timeRangeComposite.setLayout(gridLayout); // Use remaining horizontal space gridData = new GridData(); gridData.horizontalAlignment = SWT.FILL; gridData.verticalAlignment = SWT.FILL; gridData.grabExcessHorizontalSpace = true; gridData.grabExcessVerticalSpace = true; timeRangeComposite.setLayoutData(gridData); // Histogram fTimeRangeHistogram = new TimeRangeHistogram(this, timeRangeComposite); // -------------------------------------------------------------------- // Full range histogram // -------------------------------------------------------------------- Composite fullRangeComposite = new Composite(viewComposite, SWT.FILL); gridLayout = new GridLayout(); gridLayout.numColumns = 1; gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; gridLayout.marginTop = 5; gridLayout.horizontalSpacing = 0; gridLayout.verticalSpacing = 0; gridLayout.marginLeft = 5; gridLayout.marginRight = 5; fullRangeComposite.setLayout(gridLayout); // Use remaining horizontal space gridData = new GridData(); gridData.horizontalAlignment = SWT.FILL; gridData.verticalAlignment = SWT.FILL; gridData.horizontalSpan = 2; gridData.grabExcessHorizontalSpace = true; gridData.grabExcessVerticalSpace = true; fullRangeComposite.setLayoutData(gridData); // Histogram fFullTraceHistogram = new FullTraceHistogram(this, fullRangeComposite); fLegendArea = new Composite(viewComposite, SWT.FILL); fLegendArea.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, true, false, 2, 1)); fLegendArea.setLayout(new RowLayout()); // Add mouse wheel listener to time span control MouseWheelListener listener = fFullTraceHistogram.getZoom(); fTimeSpanControl.addMouseWheelListener(listener); // View Action Handling contributeToActionBars(); ITmfTrace trace = getActiveTrace(); if (trace != null) { traceSelected(new TmfTraceSelectedSignal(this, trace)); } } @Override public void setFocus() { fFullTraceHistogram.fCanvas.setFocus(); } void refresh() { fParent.layout(true); } // ------------------------------------------------------------------------ // Accessors // ------------------------------------------------------------------------ /** * Returns the current trace handled by the view * * @return the current trace * @since 2.0 */ public ITmfTrace getTrace() { return fTrace; } /** * Returns the time range of the current selected window (base on default time scale). * * @return the time range of current selected window. * @since 2.0 */ public TmfTimeRange getTimeRange() { return new TmfTimeRange( new TmfTimestamp(fWindowStartTime, ITmfTimestamp.NANOSECOND_SCALE), new TmfTimestamp(fWindowEndTime, ITmfTimestamp.NANOSECOND_SCALE)); } /** * get the show lost events action * * @return The action object * @since 2.2 */ public Action getShowLostEventsAction() { if (hideLostEventsAction == null) { /* show lost events */ hideLostEventsAction = new Action(Messages.HistogramView_hideLostEvents, IAction.AS_CHECK_BOX) { @Override public void run() { HistogramScaledData.hideLostEvents = hideLostEventsAction.isChecked(); long maxNbEvents = HistogramScaledData.hideLostEvents ? fFullTraceHistogram.fScaledData.fMaxValue : fFullTraceHistogram.fScaledData.fMaxCombinedValue; fFullTraceHistogram.setMaxNbEvents(maxNbEvents); maxNbEvents = HistogramScaledData.hideLostEvents ? fTimeRangeHistogram.fScaledData.fMaxValue : fTimeRangeHistogram.fScaledData.fMaxCombinedValue; fTimeRangeHistogram.setMaxNbEvents(maxNbEvents); } }; hideLostEventsAction.setText(Messages.HistogramView_hideLostEvents); hideLostEventsAction.setToolTipText(Messages.HistogramView_hideLostEvents); hideLostEventsAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_SHOW_LOST_EVENTS)); } return hideLostEventsAction; } /** * get the show trace action * * @return The action object * @since 3.0 */ public Action getShowTraceAction() { if (showTraceAction == null) { /* show lost events */ showTraceAction = new Action(Messages.HistogramView_showTraces, IAction.AS_CHECK_BOX) { @Override public void run() { Histogram.showTraces = showTraceAction.isChecked(); fFullTraceHistogram.fCanvas.redraw(); fTimeRangeHistogram.fCanvas.redraw(); updateLegendArea(); } }; showTraceAction.setChecked(true); showTraceAction.setText(Messages.HistogramView_showTraces); showTraceAction.setToolTipText(Messages.HistogramView_showTraces); showTraceAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_SHOW_HIST_TRACES)); } return showTraceAction; } // ------------------------------------------------------------------------ // Operations // ------------------------------------------------------------------------ /** * Broadcast TmfSignal about new current selection time range. * @param beginTime the begin time of current selection. * @param endTime the end time of current selection. */ void updateSelectionTime(long beginTime, long endTime) { updateDisplayedSelectionTime(beginTime, endTime); TmfTimestamp beginTs = new TmfTimestamp(beginTime, ITmfTimestamp.NANOSECOND_SCALE); TmfTimestamp endTs = new TmfTimestamp(endTime, ITmfTimestamp.NANOSECOND_SCALE); TmfTimeSynchSignal signal = new TmfTimeSynchSignal(this, beginTs, endTs); fTimeSyncThrottle.queue(signal); } /** * Get selection begin time * @return the begin time of current selection */ long getSelectionBegin() { return fSelectionBeginTime; } /** * Get selection end time * @return the end time of current selection */ long getSelectionEnd() { return fSelectionEndTime; } /** * Get the link state * @return true if begin and end selection time should be linked */ boolean getLinkState() { return fLinkState; } /** * Broadcast TmfSignal about new selection time range. * @param startTime the new start time * @param endTime the new end time */ void updateTimeRange(long startTime, long endTime) { if (fTrace != null) { // Build the new time range; keep the current time TmfTimeRange timeRange = new TmfTimeRange( new TmfTimestamp(startTime, ITmfTimestamp.NANOSECOND_SCALE), new TmfTimestamp(endTime, ITmfTimestamp.NANOSECOND_SCALE)); fTimeSpanControl.setValue(endTime - startTime); updateDisplayedTimeRange(startTime, endTime); // Send the FW signal TmfRangeSynchSignal signal = new TmfRangeSynchSignal(this, timeRange); fTimeRangeSyncThrottle.queue(signal); } } /** * Broadcast TmfSignal about new selected time range. * @param newDuration new duration (relative to current start time) */ public synchronized void updateTimeRange(long newDuration) { if (fTrace != null) { long delta = newDuration - fWindowSpan; long newStartTime = fWindowStartTime - (delta / 2); setNewRange(newStartTime, newDuration); } } private void setNewRange(long startTime, long duration) { long realStart = startTime; if (realStart < fTraceStartTime) { realStart = fTraceStartTime; } long endTime = realStart + duration; if (endTime > fTraceEndTime) { endTime = fTraceEndTime; if ((endTime - duration) > fTraceStartTime) { realStart = endTime - duration; } else { realStart = fTraceStartTime; } } updateTimeRange(realStart, endTime); } // ------------------------------------------------------------------------ // Signal handlers // ------------------------------------------------------------------------ /** * Handles trace opened signal. Loads histogram if new trace time range is not * equal <code>TmfTimeRange.NULL_RANGE</code> * @param signal the trace opened signal * @since 2.0 */ @TmfSignalHandler public void traceOpened(TmfTraceOpenedSignal signal) { assert (signal != null); fTrace = signal.getTrace(); loadTrace(); } /** * Handles trace selected signal. Loads histogram if new trace time range is not * equal <code>TmfTimeRange.NULL_RANGE</code> * @param signal the trace selected signal * @since 2.0 */ @TmfSignalHandler public void traceSelected(TmfTraceSelectedSignal signal) { assert (signal != null); if (fTrace != signal.getTrace()) { fTrace = signal.getTrace(); loadTrace(); } } private void loadTrace() { initializeHistograms(); fParent.redraw(); } /** * Handles trace closed signal. Clears the view and data model and cancels requests. * @param signal the trace closed signal * @since 2.0 */ @TmfSignalHandler public void traceClosed(TmfTraceClosedSignal signal) { if (signal.getTrace() != fTrace) { return; } // Kill any running request if ((fTimeRangeRequest != null) && !fTimeRangeRequest.isCompleted()) { fTimeRangeRequest.cancel(); } if ((fFullTraceRequest != null) && !fFullTraceRequest.isCompleted()) { fFullTraceRequest.cancel(); } // Initialize the internal data fTrace = null; fTraceStartTime = 0L; fTraceEndTime = 0L; fWindowStartTime = 0L; fWindowEndTime = 0L; fWindowSpan = 0L; fSelectionBeginTime = 0L; fSelectionEndTime = 0L; // Clear the UI widgets fFullTraceHistogram.clear(); fTimeRangeHistogram.clear(); fSelectionStartControl.setValue(Long.MIN_VALUE); fSelectionEndControl.setValue(Long.MIN_VALUE); fTimeSpanControl.setValue(Long.MIN_VALUE); for (Control c: fLegendArea.getChildren()) { c.dispose(); } if (fLegendImages != null) { for (Image i: fLegendImages) { i.dispose(); } } fLegendImages = null; fLegendArea.layout(); fLegendArea.getParent().layout(); } /** * Handles trace range updated signal. Extends histogram according to the new time range. If a * HistogramRequest is already ongoing, it will be cancelled and a new request with the new range * will be issued. * * @param signal the trace range updated signal * @since 2.0 */ @TmfSignalHandler public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal) { if (signal.getTrace() != fTrace) { return; } TmfTimeRange fullRange = signal.getRange(); fTraceStartTime = fullRange.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); fTraceEndTime = fullRange.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); fFullTraceHistogram.setFullRange(fTraceStartTime, fTraceEndTime); fTimeRangeHistogram.setFullRange(fTraceStartTime, fTraceEndTime); sendFullRangeRequest(fullRange); } /** * Handles the trace updated signal. Used to update time limits (start and end time) * @param signal the trace updated signal * @since 2.0 */ @TmfSignalHandler public void traceUpdated(TmfTraceUpdatedSignal signal) { if (signal.getTrace() != fTrace) { return; } TmfTimeRange fullRange = signal.getTrace().getTimeRange(); fTraceStartTime = fullRange.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); fTraceEndTime = fullRange.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); fFullTraceHistogram.setFullRange(fTraceStartTime, fTraceEndTime); fTimeRangeHistogram.setFullRange(fTraceStartTime, fTraceEndTime); if ((fFullTraceRequest != null) && fFullTraceRequest.getRange().getEndTime().compareTo(signal.getRange().getEndTime()) < 0) { sendFullRangeRequest(fullRange); } } /** * Handles the current time updated signal. Sets the current time in the time range * histogram as well as the full histogram. * * @param signal the signal to process */ @TmfSignalHandler public void currentTimeUpdated(final TmfTimeSynchSignal signal) { if (Display.getCurrent() == null) { // Make sure the signal is handled in the UI thread Display.getDefault().asyncExec(new Runnable() { @Override public void run() { if (fParent.isDisposed()) { return; } currentTimeUpdated(signal); } }); return; } // Update the selected time range ITmfTimestamp beginTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE); ITmfTimestamp endTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE); updateDisplayedSelectionTime(beginTime.getValue(), endTime.getValue()); } /** * Updates the current time range in the time range histogram and full range histogram. * @param signal the signal to process */ @TmfSignalHandler public void timeRangeUpdated(final TmfRangeSynchSignal signal) { if (Display.getCurrent() == null) { // Make sure the signal is handled in the UI thread Display.getDefault().asyncExec(new Runnable() { @Override public void run() { if (fParent.isDisposed()) { return; } timeRangeUpdated(signal); } }); return; } if (fTrace != null) { // Validate the time range TmfTimeRange range = signal.getCurrentRange().getIntersection(fTrace.getTimeRange()); if (range == null) { return; } updateDisplayedTimeRange( range.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(), range.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue()); // Send the event request to populate the small histogram sendTimeRangeRequest(fWindowStartTime, fWindowEndTime); fTimeSpanControl.setValue(fWindowSpan); } } // ------------------------------------------------------------------------ // Helper functions // ------------------------------------------------------------------------ private void initializeHistograms() { TmfTimeRange fullRange = updateTraceTimeRange(); long selectionBeginTime = fTraceManager.getSelectionBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); long selectionEndTime = fTraceManager.getSelectionEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); long startTime = fTraceManager.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); long duration = fTraceManager.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue() - startTime; if ((fTimeRangeRequest != null) && !fTimeRangeRequest.isCompleted()) { fTimeRangeRequest.cancel(); } fTimeRangeHistogram.clear(); fTimeRangeHistogram.setFullRange(fTraceStartTime, fTraceEndTime); fTimeRangeHistogram.setTimeRange(startTime, duration); fTimeRangeHistogram.setSelection(selectionBeginTime, selectionEndTime); fTimeRangeHistogram.fDataModel.setTrace(fTrace); if ((fFullTraceRequest != null) && !fFullTraceRequest.isCompleted()) { fFullTraceRequest.cancel(); } fFullTraceHistogram.clear(); fFullTraceHistogram.setFullRange(fTraceStartTime, fTraceEndTime); fFullTraceHistogram.setTimeRange(startTime, duration); fFullTraceHistogram.setSelection(selectionBeginTime, selectionEndTime); fFullTraceHistogram.fDataModel.setTrace(fTrace); fWindowStartTime = startTime; fWindowSpan = duration; fWindowEndTime = startTime + duration; fSelectionBeginTime = selectionBeginTime; fSelectionEndTime = selectionEndTime; fSelectionStartControl.setValue(fSelectionBeginTime); fSelectionEndControl.setValue(fSelectionEndTime); fTimeSpanControl.setValue(duration); ITmfTrace[] traces = TmfTraceManager.getTraceSet(fTrace); if (traces != null) { this.showTraceAction.setEnabled(traces.length < fFullTraceHistogram.getMaxNbTraces()); } updateLegendArea(); if (!fullRange.equals(TmfTimeRange.NULL_RANGE)) { sendTimeRangeRequest(startTime, startTime + duration); sendFullRangeRequest(fullRange); } } private void updateLegendArea() { for (Control c: fLegendArea.getChildren()) { c.dispose(); } if (fLegendImages != null) { for (Image i: fLegendImages) { i.dispose(); } } fLegendImages = null; if (fFullTraceHistogram.showTraces()) { ITmfTrace[] traces = TmfTraceManager.getTraceSet(fTrace); fLegendImages = new Image[traces.length]; int traceIndex = 0; for (ITmfTrace trace : traces) { fLegendImages[traceIndex] = new Image(fLegendArea.getDisplay(), 16, 16); GC gc = new GC(fLegendImages[traceIndex]); gc.setBackground(fFullTraceHistogram.getTraceColor(traceIndex)); gc.fillRectangle(0, 0, 15, 15); gc.setForeground(fLegendArea.getDisplay().getSystemColor(SWT.COLOR_BLACK)); gc.drawRectangle(0, 0, 15, 15); gc.dispose(); CLabel label = new CLabel(fLegendArea, SWT.NONE); label.setText(trace.getName()); label.setImage(fLegendImages[traceIndex]); traceIndex++; } } fLegendArea.layout(); fLegendArea.getParent().layout(); } private void updateDisplayedSelectionTime(long beginTime, long endTime) { fSelectionBeginTime = beginTime; fSelectionEndTime = endTime; fFullTraceHistogram.setSelection(fSelectionBeginTime, fSelectionEndTime); fTimeRangeHistogram.setSelection(fSelectionBeginTime, fSelectionEndTime); fSelectionStartControl.setValue(fSelectionBeginTime); fSelectionEndControl.setValue(fSelectionEndTime); } private void updateDisplayedTimeRange(long start, long end) { fWindowStartTime = start; fWindowEndTime = end; fWindowSpan = fWindowEndTime - fWindowStartTime; fFullTraceHistogram.setTimeRange(fWindowStartTime, fWindowSpan); } private TmfTimeRange updateTraceTimeRange() { fTraceStartTime = 0L; fTraceEndTime = 0L; TmfTimeRange timeRange = fTrace.getTimeRange(); if (!timeRange.equals(TmfTimeRange.NULL_RANGE)) { fTraceStartTime = timeRange.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); fTraceEndTime = timeRange.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue(); } return timeRange; } private void sendTimeRangeRequest(long startTime, long endTime) { if ((fTimeRangeRequest != null) && !fTimeRangeRequest.isCompleted()) { fTimeRangeRequest.cancel(); } TmfTimestamp startTS = new TmfTimestamp(startTime, ITmfTimestamp.NANOSECOND_SCALE); TmfTimestamp endTS = new TmfTimestamp(endTime, ITmfTimestamp.NANOSECOND_SCALE); TmfTimeRange timeRange = new TmfTimeRange(startTS, endTS); fTimeRangeHistogram.clear(); fTimeRangeHistogram.setFullRange(fTraceStartTime, fTraceEndTime); fTimeRangeHistogram.setTimeRange(startTime, endTime - startTime); int cacheSize = fTrace.getCacheSize(); fTimeRangeRequest = new HistogramRequest(fTimeRangeHistogram.getDataModel(), timeRange, 0, ITmfEventRequest.ALL_DATA, cacheSize, ExecutionType.FOREGROUND, false); fTrace.sendRequest(fTimeRangeRequest); } private void sendFullRangeRequest(TmfTimeRange fullRange) { if ((fFullTraceRequest != null) && !fFullTraceRequest.isCompleted()) { fFullTraceRequest.cancel(); } int cacheSize = fTrace.getCacheSize(); fFullTraceRequest = new HistogramRequest(fFullTraceHistogram.getDataModel(), fullRange, (int) fFullTraceHistogram.fDataModel.getNbEvents(), ITmfEventRequest.ALL_DATA, cacheSize, ExecutionType.BACKGROUND, true); fTrace.sendRequest(fFullTraceRequest); } private void contributeToActionBars() { IActionBars bars = getViewSite().getActionBars(); bars.getToolBarManager().add(getShowLostEventsAction()); bars.getToolBarManager().add(getShowTraceAction()); bars.getToolBarManager().add(new Separator()); } private void addLinkButtonListeners() { fLinkButton.addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { fSelectionEndControl.setEnabled(fLinkState); fLinkState = !fLinkState; fLinkButton.redraw(); } }); fLinkButton.addPaintListener(new PaintListener() { @Override public void paintControl(PaintEvent e) { if (fLinkState) { Rectangle r = fLinkButton.getBounds(); r.x = -1; r.y = -1; e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW)); e.gc.drawRectangle(r); r.x = 0; r.y = 0; e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_DARK_GRAY)); e.gc.drawRectangle(r); } } }); } }