1 /*******************************************************************************
2 * Copyright (c) 2009, 2016 Ericsson
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * William Bourque - Initial API and implementation
11 * Yuriy Vashchuk - GUI reorganisation, simplification and some related code improvements.
12 * Yuriy Vashchuk - Histograms optimisation.
13 * Yuriy Vashchuk - Histogram Canvas Heritage correction
14 * Francois Chouinard - Cleanup and refactoring
15 * Francois Chouinard - Moved from LTTng to TMF
16 * Patrick Tasse - Update for mouse wheel zoom
17 * Xavier Raynaud - Support multi-trace coloring
18 *******************************************************************************/
20 package org
.eclipse
.tracecompass
.tmf
.ui
.views
.histogram
;
22 import java
.util
.Collection
;
24 import org
.eclipse
.jdt
.annotation
.NonNull
;
25 import org
.eclipse
.jface
.action
.Action
;
26 import org
.eclipse
.jface
.action
.IAction
;
27 import org
.eclipse
.jface
.action
.Separator
;
28 import org
.eclipse
.swt
.SWT
;
29 import org
.eclipse
.swt
.custom
.CLabel
;
30 import org
.eclipse
.swt
.custom
.SashForm
;
31 import org
.eclipse
.swt
.custom
.ScrolledComposite
;
32 import org
.eclipse
.swt
.events
.MouseAdapter
;
33 import org
.eclipse
.swt
.events
.MouseEvent
;
34 import org
.eclipse
.swt
.events
.MouseWheelListener
;
35 import org
.eclipse
.swt
.events
.PaintEvent
;
36 import org
.eclipse
.swt
.events
.PaintListener
;
37 import org
.eclipse
.swt
.graphics
.GC
;
38 import org
.eclipse
.swt
.graphics
.Image
;
39 import org
.eclipse
.swt
.graphics
.Point
;
40 import org
.eclipse
.swt
.graphics
.Rectangle
;
41 import org
.eclipse
.swt
.layout
.GridData
;
42 import org
.eclipse
.swt
.layout
.GridLayout
;
43 import org
.eclipse
.swt
.layout
.RowLayout
;
44 import org
.eclipse
.swt
.widgets
.Composite
;
45 import org
.eclipse
.swt
.widgets
.Control
;
46 import org
.eclipse
.swt
.widgets
.Display
;
47 import org
.eclipse
.swt
.widgets
.Event
;
48 import org
.eclipse
.swt
.widgets
.Label
;
49 import org
.eclipse
.swt
.widgets
.Listener
;
50 import org
.eclipse
.swt
.widgets
.Sash
;
51 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.Activator
;
52 import org
.eclipse
.tracecompass
.internal
.tmf
.ui
.ITmfImageConstants
;
53 import org
.eclipse
.tracecompass
.tmf
.core
.request
.ITmfEventRequest
;
54 import org
.eclipse
.tracecompass
.tmf
.core
.request
.ITmfEventRequest
.ExecutionType
;
55 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSelectionRangeUpdatedSignal
;
56 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
57 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalManager
;
58 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalThrottler
;
59 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceClosedSignal
;
60 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceOpenedSignal
;
61 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceRangeUpdatedSignal
;
62 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceSelectedSignal
;
63 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfTraceUpdatedSignal
;
64 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfWindowRangeUpdatedSignal
;
65 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
66 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimeRange
;
67 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestamp
;
68 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTrace
;
69 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceContext
;
70 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTraceManager
;
71 import org
.eclipse
.tracecompass
.tmf
.ui
.signal
.TmfTimeViewAlignmentInfo
;
72 import org
.eclipse
.tracecompass
.tmf
.ui
.signal
.TmfTimeViewAlignmentSignal
;
73 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.ITmfTimeAligned
;
74 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.TmfView
;
75 import org
.eclipse
.ui
.IActionBars
;
78 * The purpose of this view is to provide graphical time distribution statistics about the trace events.
80 * The view is composed of two histograms and two controls:
82 * <li>an event distribution histogram for the whole trace;
83 * <li>an event distribution histogram for current time window (window span);
84 * <li>the timestamp of the currently selected event;
85 * <li>the window span (size of the time window of the smaller histogram).
87 * The histograms x-axis show their respective time range.
90 * @author Francois Chouinard
92 public class HistogramView
extends TmfView
implements ITmfTimeAligned
{
94 // ------------------------------------------------------------------------
96 // ------------------------------------------------------------------------
99 * The view ID as defined in plugin.xml
101 public static final @NonNull String ID
= "org.eclipse.linuxtools.tmf.ui.views.histogram"; //$NON-NLS-1$
103 private static final Image LINK_IMG
= Activator
.getDefault().getImageFromPath(ITmfImageConstants
.IMG_UI_LINK
);
105 private static final int[] DEFAULT_WEIGHTS
= {1, 3};
107 // ------------------------------------------------------------------------
109 // ------------------------------------------------------------------------
112 private ITmfTrace fTrace
;
114 // Current timestamp/time window - everything in the TIME_SCALE
115 private long fTraceStartTime
;
116 private long fTraceEndTime
;
117 private long fWindowStartTime
;
118 private long fWindowEndTime
;
119 private long fWindowSpan
;
120 private long fSelectionBeginTime
;
121 private long fSelectionEndTime
;
124 private SashForm fSashForm
;
125 private ScrolledComposite fScrollComposite
;
126 private Composite fTimeControlsComposite
;
127 private Composite fTimeRangeComposite
;
128 private Listener fSashDragListener
;
131 private HistogramTextControl fSelectionStartControl
;
132 private HistogramTextControl fSelectionEndControl
;
133 private HistogramTextControl fTimeSpanControl
;
136 private Label fLinkButton
;
137 private boolean fLinkState
;
139 // Histogram/request for the full trace range
140 private FullTraceHistogram fFullTraceHistogram
;
141 private HistogramRequest fFullTraceRequest
;
143 // Histogram/request for the selected time range
144 private TimeRangeHistogram fTimeRangeHistogram
;
145 private HistogramRequest fTimeRangeRequest
;
148 private Composite fLegendArea
;
149 private Image
[] fLegendImages
;
151 // Throttlers for the time sync and time-range sync signals
152 private final TmfSignalThrottler fTimeSyncThrottle
;
153 private final TmfSignalThrottler fTimeRangeSyncThrottle
;
155 // Action for toggle showing the lost events
156 private Action hideLostEventsAction
;
157 // Action for toggle showing the traces
158 private Action showTraceAction
;
160 // ------------------------------------------------------------------------
162 // ------------------------------------------------------------------------
165 * Default constructor
167 public HistogramView() {
169 fTimeSyncThrottle
= new TmfSignalThrottler(this, 200);
170 fTimeRangeSyncThrottle
= new TmfSignalThrottler(this, 200);
174 public void dispose() {
175 if ((fTimeRangeRequest
!= null) && !fTimeRangeRequest
.isCompleted()) {
176 fTimeRangeRequest
.cancel();
178 if ((fFullTraceRequest
!= null) && !fFullTraceRequest
.isCompleted()) {
179 fFullTraceRequest
.cancel();
181 fFullTraceHistogram
.dispose();
182 fTimeRangeHistogram
.dispose();
183 fSelectionStartControl
.dispose();
184 fSelectionEndControl
.dispose();
185 fTimeSpanControl
.dispose();
186 disposeLegendImages();
191 private void disposeLegendImages() {
192 if (fLegendImages
!= null) {
193 for (Image i
: fLegendImages
) {
197 fLegendImages
= null;
200 // ------------------------------------------------------------------------
202 // ------------------------------------------------------------------------
205 public void createPartControl(Composite parent
) {
206 super.createPartControl(parent
);
209 final String selectionStartLabel
= Messages
.HistogramView_selectionStartLabel
;
210 final String selectionEndLabel
= Messages
.HistogramView_selectionEndLabel
;
211 final String windowSpanLabel
= Messages
.HistogramView_windowSpanLabel
;
213 // --------------------------------------------------------------------
214 // Set the HistogramView layout
215 // --------------------------------------------------------------------
216 Composite viewComposite
= new Composite(getParentComposite(), SWT
.FILL
);
217 GridLayout gridLayout
= new GridLayout(1, false);
218 gridLayout
.verticalSpacing
= 0;
219 gridLayout
.marginHeight
= 0;
220 gridLayout
.marginWidth
= 0;
221 viewComposite
.setLayout(gridLayout
);
223 // --------------------------------------------------------------------
224 // Add a sash for time controls and time range histogram
225 // --------------------------------------------------------------------
228 * The ScrolledComposite preferred size can be larger than its visible
229 * width. This affects the preferred width of the SashForm. Set the
230 * preferred width to 1 to prevent it from affecting the preferred width
231 * of the view composite.
233 fSashForm
= new SashForm(viewComposite
, SWT
.NONE
) {
235 public Point
computeSize(int wHint
, int hHint
) {
236 Point computedSize
= super.computeSize(wHint
, hHint
);
237 if (wHint
== SWT
.DEFAULT
) {
238 return new Point(1, computedSize
.y
);
243 public Point
computeSize(int wHint
, int hHint
, boolean changed
) {
244 Point computedSize
= super.computeSize(wHint
, hHint
, changed
);
245 if (wHint
== SWT
.DEFAULT
) {
246 return new Point(1, computedSize
.y
);
251 GridData gridData
= new GridData(GridData
.FILL
, GridData
.FILL
, false, true);
252 fSashForm
.setLayoutData(gridData
);
254 // --------------------------------------------------------------------
256 // --------------------------------------------------------------------
257 fScrollComposite
= new PackedScrolledComposite(fSashForm
, SWT
.H_SCROLL
| SWT
.V_SCROLL
);
258 fTimeControlsComposite
= new Composite(fScrollComposite
, SWT
.NONE
);
259 fScrollComposite
.setContent(fTimeControlsComposite
);
260 gridLayout
= new GridLayout(1, false);
261 gridLayout
.marginHeight
= 0;
262 gridLayout
.marginWidth
= 0;
263 fScrollComposite
.setLayout(gridLayout
);
264 fScrollComposite
.setExpandHorizontal(true);
265 fScrollComposite
.setExpandVertical(true);
267 gridLayout
= new GridLayout(1, false);
268 gridLayout
.marginHeight
= 0;
269 gridLayout
.marginWidth
= 0;
270 fTimeControlsComposite
.setLayout(gridLayout
);
271 gridData
= new GridData(GridData
.FILL
, GridData
.CENTER
, false, true);
272 fTimeControlsComposite
.setLayoutData(gridData
);
274 Composite innerComp
= new Composite(fTimeControlsComposite
, SWT
.NONE
);
276 gridLayout
= new GridLayout(2, false);
277 innerComp
.setLayout(gridLayout
);
278 gridLayout
.marginHeight
= 0;
279 gridLayout
.marginWidth
= 0;
280 gridLayout
.horizontalSpacing
= 5;
281 gridLayout
.verticalSpacing
= 1;
282 gridData
= new GridData(GridData
.FILL
, GridData
.CENTER
, false, true);
283 innerComp
.setLayoutData(gridData
);
285 Composite selectionGroup
= new Composite(innerComp
, SWT
.BORDER
);
286 gridLayout
= new GridLayout(1, false);
287 gridLayout
.marginHeight
= 0;
288 gridLayout
.marginWidth
= 0;
289 selectionGroup
.setLayout(gridLayout
);
290 gridData
= new GridData(GridData
.BEGINNING
, GridData
.CENTER
, false, false);
291 selectionGroup
.setLayoutData(gridData
);
293 // Selection start control
294 gridData
= new GridData(GridData
.FILL
, GridData
.CENTER
, false, false);
295 fSelectionStartControl
= new HistogramSelectionStartControl(this, selectionGroup
, selectionStartLabel
, 0L);
296 fSelectionStartControl
.setLayoutData(gridData
);
297 fSelectionStartControl
.setValue(Long
.MIN_VALUE
);
299 // Selection end control
300 gridData
= new GridData(GridData
.FILL
, GridData
.CENTER
, false, false);
301 fSelectionEndControl
= new HistogramSelectionEndControl(this, selectionGroup
, selectionEndLabel
, 0L);
302 fSelectionEndControl
.setLayoutData(gridData
);
303 fSelectionEndControl
.setValue(Long
.MIN_VALUE
);
306 gridData
= new GridData(GridData
.BEGINNING
, GridData
.CENTER
, false, false);
307 fLinkButton
= new Label(innerComp
, SWT
.NONE
);
308 fLinkButton
.setImage(LINK_IMG
);
309 fLinkButton
.setLayoutData(gridData
);
310 addLinkButtonListeners();
312 // Window span time control
313 gridData
= new GridData(GridData
.FILL
, GridData
.CENTER
, false, false);
314 fTimeSpanControl
= new HistogramTimeRangeControl(this, innerComp
, windowSpanLabel
, 0L);
315 fTimeSpanControl
.setLayoutData(gridData
);
316 fTimeSpanControl
.setValue(Long
.MIN_VALUE
);
318 // --------------------------------------------------------------------
319 // Time range histogram
320 // --------------------------------------------------------------------
321 fTimeRangeComposite
= new Composite(fSashForm
, SWT
.NONE
);
322 gridLayout
= new GridLayout(1, true);
323 gridLayout
.marginTop
= 0;
324 gridLayout
.marginWidth
= 0;
325 fTimeRangeComposite
.setLayout(gridLayout
);
327 // Use remaining horizontal space
328 gridData
= new GridData(GridData
.FILL
, GridData
.FILL
, true, true);
329 fTimeRangeComposite
.setLayoutData(gridData
);
332 fTimeRangeHistogram
= new TimeRangeHistogram(this, fTimeRangeComposite
, true);
334 // --------------------------------------------------------------------
335 // Full range histogram
336 // --------------------------------------------------------------------
337 final Composite fullRangeComposite
= new Composite(viewComposite
, SWT
.FILL
);
338 gridLayout
= new GridLayout(1, true);
339 fullRangeComposite
.setLayout(gridLayout
);
341 // Use remaining horizontal space
342 gridData
= new GridData(GridData
.FILL
, GridData
.FILL
, true, true, 2, 1);
343 fullRangeComposite
.setLayoutData(gridData
);
346 fFullTraceHistogram
= new FullTraceHistogram(this, fullRangeComposite
);
348 fLegendArea
= new Composite(viewComposite
, SWT
.FILL
);
349 fLegendArea
.setLayoutData(new GridData(SWT
.BEGINNING
, SWT
.BEGINNING
, true, false, 2, 1));
350 fLegendArea
.setLayout(new RowLayout());
352 // Add mouse wheel listener to time span control
353 MouseWheelListener listener
= fFullTraceHistogram
.getZoom();
354 fTimeSpanControl
.addMouseWheelListener(listener
);
356 // View Action Handling
357 contributeToActionBars();
359 ITmfTrace trace
= TmfTraceManager
.getInstance().getActiveTrace();
361 traceSelected(new TmfTraceSelectedSignal(this, trace
));
364 fSashForm
.setVisible(true);
365 fSashForm
.setWeights(DEFAULT_WEIGHTS
);
367 fTimeControlsComposite
.addPaintListener(new PaintListener() {
369 public void paintControl(PaintEvent e
) {
370 // Sashes in a SashForm are being created on layout so add the
371 // drag listener here
372 if (fSashDragListener
== null) {
373 for (Control control
: fSashForm
.getChildren()) {
374 if (control
instanceof Sash
) {
375 fSashDragListener
= new Listener() {
377 public void handleEvent(Event event
) {
378 TmfSignalManager
.dispatchSignal(new TmfTimeViewAlignmentSignal(fSashForm
, getTimeViewAlignmentInfo()));
381 control
.removePaintListener(this);
382 control
.addListener(SWT
.Selection
, fSashDragListener
);
383 // There should be only one sash
393 public void setFocus() {
394 fFullTraceHistogram
.fCanvas
.setFocus();
398 getParentComposite().layout(true);
405 public TmfTimeViewAlignmentInfo
getTimeViewAlignmentInfo() {
406 if (fSashForm
== null) {
409 return new TmfTimeViewAlignmentInfo(fSashForm
.getShell(), fSashForm
.toDisplay(0, 0), getTimeAxisOffset());
412 private int getTimeAxisOffset() {
413 return fScrollComposite
.getSize().x
+ fSashForm
.getSashWidth() + fTimeRangeHistogram
.getPointAreaOffset();
420 public int getAvailableWidth(int requestedOffset
) {
421 int pointAreaWidth
= fTimeRangeHistogram
.getPointAreaWidth();
422 int curTimeAxisOffset
= getTimeAxisOffset();
423 if (pointAreaWidth
<= 0) {
424 pointAreaWidth
= fSashForm
.getBounds().width
- curTimeAxisOffset
;
426 int endOffset
= curTimeAxisOffset
+ pointAreaWidth
;
427 GridLayout layout
= (GridLayout
) fTimeRangeComposite
.getLayout();
428 int endOffsetWithoutMargin
= endOffset
+ layout
.marginRight
;
429 int availableWidth
= endOffsetWithoutMargin
- requestedOffset
;
430 availableWidth
= Math
.min(fSashForm
.getBounds().width
, Math
.max(0, availableWidth
));
432 return availableWidth
;
439 public void performAlign(int offset
, int width
) {
440 int total
= fSashForm
.getBounds().width
;
441 int plotAreaOffset
= fTimeRangeHistogram
.getPointAreaOffset();
442 int width1
= Math
.max(0, offset
- plotAreaOffset
- fSashForm
.getSashWidth());
443 int width2
= Math
.max(0, total
- width1
- fSashForm
.getSashWidth());
444 if (width1
>= 0 && width2
> 0 || width1
> 0 && width2
>= 0) {
445 fSashForm
.setWeights(new int[] { width1
, width2
});
449 // calculate right margin
450 GridLayout layout
= (GridLayout
) fTimeRangeComposite
.getLayout();
451 int timeBasedControlsWidth
= fTimeRangeComposite
.getSize().x
;
452 int marginSize
= timeBasedControlsWidth
- width
- plotAreaOffset
;
453 layout
.marginRight
= Math
.max(0, marginSize
);
454 fTimeRangeComposite
.layout();
457 // ------------------------------------------------------------------------
459 // ------------------------------------------------------------------------
462 * Returns the current trace handled by the view
464 * @return the current trace
466 public ITmfTrace
getTrace() {
471 * Returns the time range of the current selected window (base on default time scale).
473 * @return the time range of current selected window.
475 public TmfTimeRange
getTimeRange() {
476 return new TmfTimeRange(
477 TmfTimestamp
.fromNanos(fWindowStartTime
),
478 TmfTimestamp
.fromNanos(fWindowEndTime
));
482 * get the show lost events action
484 * @return The action object
486 public Action
getShowLostEventsAction() {
487 if (hideLostEventsAction
== null) {
488 /* show lost events */
489 hideLostEventsAction
= new Action(Messages
.HistogramView_hideLostEvents
, IAction
.AS_CHECK_BOX
) {
492 HistogramScaledData
.hideLostEvents
= hideLostEventsAction
.isChecked();
493 long maxNbEvents
= HistogramScaledData
.hideLostEvents ? fFullTraceHistogram
.fScaledData
.fMaxValue
: fFullTraceHistogram
.fScaledData
.fMaxCombinedValue
;
494 fFullTraceHistogram
.setMaxNbEvents(maxNbEvents
);
495 maxNbEvents
= HistogramScaledData
.hideLostEvents ? fTimeRangeHistogram
.fScaledData
.fMaxValue
: fTimeRangeHistogram
.fScaledData
.fMaxCombinedValue
;
496 fTimeRangeHistogram
.setMaxNbEvents(maxNbEvents
);
499 hideLostEventsAction
.setText(Messages
.HistogramView_hideLostEvents
);
500 hideLostEventsAction
.setToolTipText(Messages
.HistogramView_hideLostEvents
);
501 hideLostEventsAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(ITmfImageConstants
.IMG_UI_SHOW_LOST_EVENTS
));
503 return hideLostEventsAction
;
507 * get the show trace action
509 * @return The action object
511 public Action
getShowTraceAction() {
512 if (showTraceAction
== null) {
513 /* show lost events */
514 showTraceAction
= new Action(Messages
.HistogramView_showTraces
, IAction
.AS_CHECK_BOX
) {
517 Histogram
.showTraces
= showTraceAction
.isChecked();
518 fFullTraceHistogram
.fCanvas
.redraw();
519 fTimeRangeHistogram
.fCanvas
.redraw();
523 showTraceAction
.setChecked(true);
524 showTraceAction
.setText(Messages
.HistogramView_showTraces
);
525 showTraceAction
.setToolTipText(Messages
.HistogramView_showTraces
);
526 showTraceAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(ITmfImageConstants
.IMG_UI_SHOW_HIST_TRACES
));
528 return showTraceAction
;
531 // ------------------------------------------------------------------------
533 // ------------------------------------------------------------------------
536 * Broadcast TmfSignal about new current selection time range.
537 * @param beginTime the begin time of current selection.
538 * @param endTime the end time of current selection.
540 void updateSelectionTime(long beginTime
, long endTime
) {
541 updateDisplayedSelectionTime(beginTime
, endTime
);
542 ITmfTimestamp beginTs
= TmfTimestamp
.fromNanos(beginTime
);
543 ITmfTimestamp endTs
= TmfTimestamp
.fromNanos(endTime
);
544 TmfSelectionRangeUpdatedSignal signal
= new TmfSelectionRangeUpdatedSignal(this, beginTs
, endTs
);
545 fTimeSyncThrottle
.queue(signal
);
549 * Get selection begin time
550 * @return the begin time of current selection
552 long getSelectionBegin() {
553 return fSelectionBeginTime
;
557 * Get selection end time
558 * @return the end time of current selection
560 long getSelectionEnd() {
561 return fSelectionEndTime
;
566 * @return true if begin and end selection time should be linked
568 boolean getLinkState() {
573 * Broadcast TmfSignal about new selection time range.
574 * @param startTime the new start time
575 * @param endTime the new end time
577 void updateTimeRange(long startTime
, long endTime
) {
578 if (fTrace
!= null) {
579 // Build the new time range; keep the current time
580 TmfTimeRange timeRange
= new TmfTimeRange(
581 TmfTimestamp
.fromNanos(startTime
),
582 TmfTimestamp
.fromNanos(endTime
));
583 fTimeSpanControl
.setValue(endTime
- startTime
);
585 updateDisplayedTimeRange(startTime
, endTime
);
587 // Send the FW signal
588 TmfWindowRangeUpdatedSignal signal
= new TmfWindowRangeUpdatedSignal(this, timeRange
);
589 fTimeRangeSyncThrottle
.queue(signal
);
594 * Broadcast TmfSignal about new selected time range.
595 * @param newDuration new duration (relative to current start time)
597 public synchronized void updateTimeRange(long newDuration
) {
598 if (fTrace
!= null) {
599 long delta
= newDuration
- fWindowSpan
;
600 long newStartTime
= fWindowStartTime
- (delta
/ 2);
601 setNewRange(newStartTime
, newDuration
);
605 private void setNewRange(long startTime
, long duration
) {
606 long realStart
= startTime
;
608 if (realStart
< fTraceStartTime
) {
609 realStart
= fTraceStartTime
;
612 long endTime
= realStart
+ duration
;
613 if (endTime
> fTraceEndTime
) {
614 endTime
= fTraceEndTime
;
615 if ((endTime
- duration
) > fTraceStartTime
) {
616 realStart
= endTime
- duration
;
618 realStart
= fTraceStartTime
;
621 updateTimeRange(realStart
, endTime
);
624 // ------------------------------------------------------------------------
626 // ------------------------------------------------------------------------
629 * Handles trace opened signal. Loads histogram if new trace time range is not
630 * equal <code>TmfTimeRange.NULL_RANGE</code>
631 * @param signal the trace opened signal
634 public void traceOpened(TmfTraceOpenedSignal signal
) {
635 assert (signal
!= null);
636 fTrace
= signal
.getTrace();
641 * Handles trace selected signal. Loads histogram if new trace time range is not
642 * equal <code>TmfTimeRange.NULL_RANGE</code>
643 * @param signal the trace selected signal
646 public void traceSelected(TmfTraceSelectedSignal signal
) {
647 assert (signal
!= null);
648 if (fTrace
!= signal
.getTrace()) {
649 fTrace
= signal
.getTrace();
654 private void loadTrace() {
655 initializeHistograms();
656 getParentComposite().redraw();
660 * Handles trace closed signal. Clears the view and data model and cancels requests.
661 * @param signal the trace closed signal
664 public void traceClosed(TmfTraceClosedSignal signal
) {
666 if (signal
.getTrace() != fTrace
) {
670 // Kill any running request
671 if ((fTimeRangeRequest
!= null) && !fTimeRangeRequest
.isCompleted()) {
672 fTimeRangeRequest
.cancel();
674 if ((fFullTraceRequest
!= null) && !fFullTraceRequest
.isCompleted()) {
675 fFullTraceRequest
.cancel();
678 // Initialize the internal data
680 fTraceStartTime
= 0L;
682 fWindowStartTime
= 0L;
685 fSelectionBeginTime
= 0L;
686 fSelectionEndTime
= 0L;
688 // Clear the UI widgets
689 fFullTraceHistogram
.clear();
690 fTimeRangeHistogram
.clear();
691 fSelectionStartControl
.setValue(Long
.MIN_VALUE
);
692 fSelectionEndControl
.setValue(Long
.MIN_VALUE
);
694 fTimeSpanControl
.setValue(Long
.MIN_VALUE
);
696 for (Control c
: fLegendArea
.getChildren()) {
699 disposeLegendImages();
700 fLegendArea
.layout();
701 fLegendArea
.getParent().layout();
705 * Handles trace range updated signal. Extends histogram according to the new time range. If a
706 * HistogramRequest is already ongoing, it will be cancelled and a new request with the new range
709 * @param signal the trace range updated signal
712 public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal
) {
714 if (signal
.getTrace() != fTrace
) {
718 TmfTimeRange fullRange
= signal
.getRange();
720 fTraceStartTime
= fullRange
.getStartTime().toNanos();
721 fTraceEndTime
= fullRange
.getEndTime().toNanos();
723 fFullTraceHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
724 fTimeRangeHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
726 sendFullRangeRequest(fullRange
);
730 * Handles the trace updated signal. Used to update time limits (start and end time)
731 * @param signal the trace updated signal
734 public void traceUpdated(TmfTraceUpdatedSignal signal
) {
735 if (signal
.getTrace() != fTrace
) {
738 TmfTimeRange fullRange
= signal
.getTrace().getTimeRange();
739 fTraceStartTime
= fullRange
.getStartTime().toNanos();
740 fTraceEndTime
= fullRange
.getEndTime().toNanos();
742 fFullTraceHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
743 fTimeRangeHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
745 if ((fFullTraceRequest
!= null) && fFullTraceRequest
.getRange().getEndTime().compareTo(signal
.getRange().getEndTime()) < 0) {
746 sendFullRangeRequest(fullRange
);
751 * Handles the selection range updated signal. Sets the current time
752 * selection in the time range histogram as well as the full histogram.
755 * the signal to process
759 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal
) {
760 if (Display
.getCurrent() == null) {
761 // Make sure the signal is handled in the UI thread
762 Display
.getDefault().asyncExec(new Runnable() {
765 if (getParentComposite().isDisposed()) {
768 selectionRangeUpdated(signal
);
774 // Update the selected time range
775 long beginTime
= signal
.getBeginTime().toNanos();
776 long endTime
= signal
.getEndTime().toNanos();
778 updateDisplayedSelectionTime(beginTime
, endTime
);
782 * Updates the current window time range in the time range histogram and
783 * full range histogram.
786 * the signal to process
790 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal
) {
791 if (Display
.getCurrent() == null) {
792 // Make sure the signal is handled in the UI thread
793 Display
.getDefault().asyncExec(new Runnable() {
796 if (getParentComposite().isDisposed()) {
799 windowRangeUpdated(signal
);
805 if (fTrace
!= null) {
806 // Validate the time range
807 TmfTimeRange range
= signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange());
812 updateDisplayedTimeRange(
813 range
.getStartTime().toNanos(),
814 range
.getEndTime().toNanos());
816 // Send the event request to populate the small histogram
817 sendTimeRangeRequest(fWindowStartTime
, fWindowEndTime
);
819 fTimeSpanControl
.setValue(fWindowSpan
);
823 // ------------------------------------------------------------------------
825 // ------------------------------------------------------------------------
827 private void initializeHistograms() {
828 TmfTimeRange fullRange
= updateTraceTimeRange();
830 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
831 long selectionBeginTime
= ctx
.getSelectionRange().getStartTime().toNanos();
832 long selectionEndTime
= ctx
.getSelectionRange().getEndTime().toNanos();
833 long startTime
= ctx
.getWindowRange().getStartTime().toNanos();
834 long duration
= ctx
.getWindowRange().getEndTime().toNanos() - startTime
;
836 if ((fTimeRangeRequest
!= null) && !fTimeRangeRequest
.isCompleted()) {
837 fTimeRangeRequest
.cancel();
839 fTimeRangeHistogram
.clear();
840 fTimeRangeHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
841 fTimeRangeHistogram
.setTimeRange(startTime
, duration
);
842 fTimeRangeHistogram
.setSelection(selectionBeginTime
, selectionEndTime
);
843 fTimeRangeHistogram
.fDataModel
.setTrace(fTrace
);
845 if ((fFullTraceRequest
!= null) && !fFullTraceRequest
.isCompleted()) {
846 fFullTraceRequest
.cancel();
848 fFullTraceHistogram
.clear();
849 fFullTraceHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
850 fFullTraceHistogram
.setTimeRange(startTime
, duration
);
851 fFullTraceHistogram
.setSelection(selectionBeginTime
, selectionEndTime
);
852 fFullTraceHistogram
.fDataModel
.setTrace(fTrace
);
854 fWindowStartTime
= startTime
;
855 fWindowSpan
= duration
;
856 fWindowEndTime
= startTime
+ duration
;
858 fSelectionBeginTime
= selectionBeginTime
;
859 fSelectionEndTime
= selectionEndTime
;
860 fSelectionStartControl
.setValue(fSelectionBeginTime
);
861 fSelectionEndControl
.setValue(fSelectionEndTime
);
863 // make sure that the scrollbar is setup properly
864 fScrollComposite
.setMinSize(fTimeControlsComposite
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
865 fTimeSpanControl
.setValue(duration
);
867 Collection
<ITmfTrace
> traces
= TmfTraceManager
.getTraceSet(fTrace
);
868 if (!traces
.isEmpty()) {
869 this.showTraceAction
.setEnabled(traces
.size() < fFullTraceHistogram
.getMaxNbTraces());
873 if (!fullRange
.equals(TmfTimeRange
.NULL_RANGE
)) {
874 sendTimeRangeRequest(startTime
, startTime
+ duration
);
875 sendFullRangeRequest(fullRange
);
879 private void updateLegendArea() {
880 for (Control c
: fLegendArea
.getChildren()) {
883 disposeLegendImages();
884 if (fFullTraceHistogram
.showTraces()) {
885 Collection
<ITmfTrace
> traces
= TmfTraceManager
.getTraceSet(fTrace
);
886 fLegendImages
= new Image
[traces
.size()];
888 for (ITmfTrace trace
: traces
) {
889 fLegendImages
[traceIndex
] = new Image(fLegendArea
.getDisplay(), 16, 16);
890 GC gc
= new GC(fLegendImages
[traceIndex
]);
891 gc
.setBackground(fFullTraceHistogram
.getTraceColor(traceIndex
));
892 gc
.fillRectangle(0, 0, 15, 15);
893 gc
.setForeground(fLegendArea
.getDisplay().getSystemColor(SWT
.COLOR_BLACK
));
894 gc
.drawRectangle(0, 0, 15, 15);
897 CLabel label
= new CLabel(fLegendArea
, SWT
.NONE
);
898 label
.setText(trace
.getName());
899 label
.setImage(fLegendImages
[traceIndex
]);
903 fLegendArea
.layout();
904 fLegendArea
.getParent().layout();
907 private void updateDisplayedSelectionTime(long beginTime
, long endTime
) {
908 fSelectionBeginTime
= beginTime
;
909 fSelectionEndTime
= endTime
;
911 fFullTraceHistogram
.setSelection(fSelectionBeginTime
, fSelectionEndTime
);
912 fTimeRangeHistogram
.setSelection(fSelectionBeginTime
, fSelectionEndTime
);
913 fSelectionStartControl
.setValue(fSelectionBeginTime
);
914 fSelectionEndControl
.setValue(fSelectionEndTime
);
917 private void updateDisplayedTimeRange(long start
, long end
) {
918 fWindowStartTime
= start
;
919 fWindowEndTime
= end
;
920 fWindowSpan
= fWindowEndTime
- fWindowStartTime
;
921 fFullTraceHistogram
.setTimeRange(fWindowStartTime
, fWindowSpan
);
924 private TmfTimeRange
updateTraceTimeRange() {
925 fTraceStartTime
= 0L;
928 TmfTimeRange timeRange
= fTrace
.getTimeRange();
929 if (!timeRange
.equals(TmfTimeRange
.NULL_RANGE
)) {
930 fTraceStartTime
= timeRange
.getStartTime().toNanos();
931 fTraceEndTime
= timeRange
.getEndTime().toNanos();
936 private void sendTimeRangeRequest(long startTime
, long endTime
) {
937 if ((fTimeRangeRequest
!= null) && !fTimeRangeRequest
.isCompleted()) {
938 fTimeRangeRequest
.cancel();
940 ITmfTimestamp startTS
= TmfTimestamp
.fromNanos(startTime
);
941 ITmfTimestamp endTS
= TmfTimestamp
.fromNanos(endTime
);
942 TmfTimeRange timeRange
= new TmfTimeRange(startTS
, endTS
);
944 fTimeRangeHistogram
.clear();
945 fTimeRangeHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
946 fTimeRangeHistogram
.setTimeRange(startTime
, endTime
- startTime
);
948 int cacheSize
= fTrace
.getCacheSize();
949 fTimeRangeRequest
= new HistogramRequest(fTimeRangeHistogram
.getDataModel(),
950 timeRange
, 0, ITmfEventRequest
.ALL_DATA
, cacheSize
, ExecutionType
.FOREGROUND
, false);
951 fTrace
.sendRequest(fTimeRangeRequest
);
954 private void sendFullRangeRequest(TmfTimeRange fullRange
) {
955 if ((fFullTraceRequest
!= null) && !fFullTraceRequest
.isCompleted()) {
956 fFullTraceRequest
.cancel();
958 int cacheSize
= fTrace
.getCacheSize();
959 fFullTraceRequest
= new HistogramRequest(fFullTraceHistogram
.getDataModel(),
961 (int) fFullTraceHistogram
.fDataModel
.getNbEvents(),
962 ITmfEventRequest
.ALL_DATA
,
964 ExecutionType
.BACKGROUND
, true);
965 fTrace
.sendRequest(fFullTraceRequest
);
968 private void contributeToActionBars() {
969 IActionBars bars
= getViewSite().getActionBars();
970 bars
.getToolBarManager().add(getShowLostEventsAction());
971 bars
.getToolBarManager().add(getShowTraceAction());
972 bars
.getToolBarManager().add(new Separator());
975 private void addLinkButtonListeners() {
976 fLinkButton
.addMouseListener(new MouseAdapter() {
978 public void mouseDown(MouseEvent e
) {
979 fSelectionEndControl
.setEnabled(fLinkState
);
980 fLinkState
= !fLinkState
;
981 fLinkButton
.redraw();
985 fLinkButton
.addPaintListener(new PaintListener() {
987 public void paintControl(PaintEvent e
) {
989 Rectangle r
= fLinkButton
.getBounds();
992 e
.gc
.setForeground(e
.display
.getSystemColor(SWT
.COLOR_WIDGET_NORMAL_SHADOW
));
993 e
.gc
.drawRectangle(r
);
996 e
.gc
.setForeground(e
.display
.getSystemColor(SWT
.COLOR_DARK_GRAY
));
997 e
.gc
.drawRectangle(r
);
1003 private static class PackedScrolledComposite
extends ScrolledComposite
{
1004 Point fScrollBarSize
; // Size of OS-specific scrollbar
1006 public PackedScrolledComposite(Composite parent
, int style
) {
1007 super(parent
, style
);
1008 Composite composite
= new Composite(parent
, SWT
.H_SCROLL
| SWT
.V_SCROLL
);
1009 composite
.setSize(1, 1);
1010 fScrollBarSize
= composite
.computeSize(0, 0);
1011 composite
.dispose();
1015 public Point
computeSize(int wHint
, int hHint
, boolean changed
) {
1016 Point point
= super.computeSize(wHint
, hHint
, changed
);
1017 // Remove scrollbar size if applicable
1018 point
.x
+= ((getStyle() & SWT
.V_SCROLL
) != 0) ?
-fScrollBarSize
.x
: 0;
1019 point
.y
+= ((getStyle() & SWT
.H_SCROLL
) != 0) ?
-fScrollBarSize
.y
: 0;