1 /*******************************************************************************
2 * Copyright (c) 2009, 2015 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 static FullTraceHistogram fFullTraceHistogram
;
141 private HistogramRequest fFullTraceRequest
;
143 // Histogram/request for the selected time range
144 private static 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 fSashForm
.setWeights(new int[] { width1
, width2
});
447 // calculate right margin
448 GridLayout layout
= (GridLayout
) fTimeRangeComposite
.getLayout();
449 int timeBasedControlsWidth
= fTimeRangeComposite
.getSize().x
;
450 int marginSize
= timeBasedControlsWidth
- width
- plotAreaOffset
;
451 layout
.marginRight
= Math
.max(0, marginSize
);
452 fTimeRangeComposite
.layout();
455 // ------------------------------------------------------------------------
457 // ------------------------------------------------------------------------
460 * Returns the current trace handled by the view
462 * @return the current trace
464 public ITmfTrace
getTrace() {
469 * Returns the time range of the current selected window (base on default time scale).
471 * @return the time range of current selected window.
473 public TmfTimeRange
getTimeRange() {
474 return new TmfTimeRange(
475 new TmfTimestamp(fWindowStartTime
, ITmfTimestamp
.NANOSECOND_SCALE
),
476 new TmfTimestamp(fWindowEndTime
, ITmfTimestamp
.NANOSECOND_SCALE
));
480 * get the show lost events action
482 * @return The action object
484 public Action
getShowLostEventsAction() {
485 if (hideLostEventsAction
== null) {
486 /* show lost events */
487 hideLostEventsAction
= new Action(Messages
.HistogramView_hideLostEvents
, IAction
.AS_CHECK_BOX
) {
490 HistogramScaledData
.hideLostEvents
= hideLostEventsAction
.isChecked();
491 long maxNbEvents
= HistogramScaledData
.hideLostEvents ? fFullTraceHistogram
.fScaledData
.fMaxValue
: fFullTraceHistogram
.fScaledData
.fMaxCombinedValue
;
492 fFullTraceHistogram
.setMaxNbEvents(maxNbEvents
);
493 maxNbEvents
= HistogramScaledData
.hideLostEvents ? fTimeRangeHistogram
.fScaledData
.fMaxValue
: fTimeRangeHistogram
.fScaledData
.fMaxCombinedValue
;
494 fTimeRangeHistogram
.setMaxNbEvents(maxNbEvents
);
497 hideLostEventsAction
.setText(Messages
.HistogramView_hideLostEvents
);
498 hideLostEventsAction
.setToolTipText(Messages
.HistogramView_hideLostEvents
);
499 hideLostEventsAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(ITmfImageConstants
.IMG_UI_SHOW_LOST_EVENTS
));
501 return hideLostEventsAction
;
505 * get the show trace action
507 * @return The action object
509 public Action
getShowTraceAction() {
510 if (showTraceAction
== null) {
511 /* show lost events */
512 showTraceAction
= new Action(Messages
.HistogramView_showTraces
, IAction
.AS_CHECK_BOX
) {
515 Histogram
.showTraces
= showTraceAction
.isChecked();
516 fFullTraceHistogram
.fCanvas
.redraw();
517 fTimeRangeHistogram
.fCanvas
.redraw();
521 showTraceAction
.setChecked(true);
522 showTraceAction
.setText(Messages
.HistogramView_showTraces
);
523 showTraceAction
.setToolTipText(Messages
.HistogramView_showTraces
);
524 showTraceAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(ITmfImageConstants
.IMG_UI_SHOW_HIST_TRACES
));
526 return showTraceAction
;
529 // ------------------------------------------------------------------------
531 // ------------------------------------------------------------------------
534 * Broadcast TmfSignal about new current selection time range.
535 * @param beginTime the begin time of current selection.
536 * @param endTime the end time of current selection.
538 void updateSelectionTime(long beginTime
, long endTime
) {
539 updateDisplayedSelectionTime(beginTime
, endTime
);
540 TmfTimestamp beginTs
= new TmfTimestamp(beginTime
, ITmfTimestamp
.NANOSECOND_SCALE
);
541 TmfTimestamp endTs
= new TmfTimestamp(endTime
, ITmfTimestamp
.NANOSECOND_SCALE
);
542 TmfSelectionRangeUpdatedSignal signal
= new TmfSelectionRangeUpdatedSignal(this, beginTs
, endTs
);
543 fTimeSyncThrottle
.queue(signal
);
547 * Get selection begin time
548 * @return the begin time of current selection
550 long getSelectionBegin() {
551 return fSelectionBeginTime
;
555 * Get selection end time
556 * @return the end time of current selection
558 long getSelectionEnd() {
559 return fSelectionEndTime
;
564 * @return true if begin and end selection time should be linked
566 boolean getLinkState() {
571 * Broadcast TmfSignal about new selection time range.
572 * @param startTime the new start time
573 * @param endTime the new end time
575 void updateTimeRange(long startTime
, long endTime
) {
576 if (fTrace
!= null) {
577 // Build the new time range; keep the current time
578 TmfTimeRange timeRange
= new TmfTimeRange(
579 new TmfTimestamp(startTime
, ITmfTimestamp
.NANOSECOND_SCALE
),
580 new TmfTimestamp(endTime
, ITmfTimestamp
.NANOSECOND_SCALE
));
581 fTimeSpanControl
.setValue(endTime
- startTime
);
583 updateDisplayedTimeRange(startTime
, endTime
);
585 // Send the FW signal
586 TmfWindowRangeUpdatedSignal signal
= new TmfWindowRangeUpdatedSignal(this, timeRange
);
587 fTimeRangeSyncThrottle
.queue(signal
);
592 * Broadcast TmfSignal about new selected time range.
593 * @param newDuration new duration (relative to current start time)
595 public synchronized void updateTimeRange(long newDuration
) {
596 if (fTrace
!= null) {
597 long delta
= newDuration
- fWindowSpan
;
598 long newStartTime
= fWindowStartTime
- (delta
/ 2);
599 setNewRange(newStartTime
, newDuration
);
603 private void setNewRange(long startTime
, long duration
) {
604 long realStart
= startTime
;
606 if (realStart
< fTraceStartTime
) {
607 realStart
= fTraceStartTime
;
610 long endTime
= realStart
+ duration
;
611 if (endTime
> fTraceEndTime
) {
612 endTime
= fTraceEndTime
;
613 if ((endTime
- duration
) > fTraceStartTime
) {
614 realStart
= endTime
- duration
;
616 realStart
= fTraceStartTime
;
619 updateTimeRange(realStart
, endTime
);
622 // ------------------------------------------------------------------------
624 // ------------------------------------------------------------------------
627 * Handles trace opened signal. Loads histogram if new trace time range is not
628 * equal <code>TmfTimeRange.NULL_RANGE</code>
629 * @param signal the trace opened signal
632 public void traceOpened(TmfTraceOpenedSignal signal
) {
633 assert (signal
!= null);
634 fTrace
= signal
.getTrace();
639 * Handles trace selected signal. Loads histogram if new trace time range is not
640 * equal <code>TmfTimeRange.NULL_RANGE</code>
641 * @param signal the trace selected signal
644 public void traceSelected(TmfTraceSelectedSignal signal
) {
645 assert (signal
!= null);
646 if (fTrace
!= signal
.getTrace()) {
647 fTrace
= signal
.getTrace();
652 private void loadTrace() {
653 initializeHistograms();
654 getParentComposite().redraw();
658 * Handles trace closed signal. Clears the view and data model and cancels requests.
659 * @param signal the trace closed signal
662 public void traceClosed(TmfTraceClosedSignal signal
) {
664 if (signal
.getTrace() != fTrace
) {
668 // Kill any running request
669 if ((fTimeRangeRequest
!= null) && !fTimeRangeRequest
.isCompleted()) {
670 fTimeRangeRequest
.cancel();
672 if ((fFullTraceRequest
!= null) && !fFullTraceRequest
.isCompleted()) {
673 fFullTraceRequest
.cancel();
676 // Initialize the internal data
678 fTraceStartTime
= 0L;
680 fWindowStartTime
= 0L;
683 fSelectionBeginTime
= 0L;
684 fSelectionEndTime
= 0L;
686 // Clear the UI widgets
687 fFullTraceHistogram
.clear();
688 fTimeRangeHistogram
.clear();
689 fSelectionStartControl
.setValue(Long
.MIN_VALUE
);
690 fSelectionEndControl
.setValue(Long
.MIN_VALUE
);
692 fTimeSpanControl
.setValue(Long
.MIN_VALUE
);
694 for (Control c
: fLegendArea
.getChildren()) {
697 disposeLegendImages();
698 fLegendArea
.layout();
699 fLegendArea
.getParent().layout();
703 * Handles trace range updated signal. Extends histogram according to the new time range. If a
704 * HistogramRequest is already ongoing, it will be cancelled and a new request with the new range
707 * @param signal the trace range updated signal
710 public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal
) {
712 if (signal
.getTrace() != fTrace
) {
716 TmfTimeRange fullRange
= signal
.getRange();
718 fTraceStartTime
= fullRange
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
719 fTraceEndTime
= fullRange
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
721 fFullTraceHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
722 fTimeRangeHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
724 sendFullRangeRequest(fullRange
);
728 * Handles the trace updated signal. Used to update time limits (start and end time)
729 * @param signal the trace updated signal
732 public void traceUpdated(TmfTraceUpdatedSignal signal
) {
733 if (signal
.getTrace() != fTrace
) {
736 TmfTimeRange fullRange
= signal
.getTrace().getTimeRange();
737 fTraceStartTime
= fullRange
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
738 fTraceEndTime
= fullRange
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
740 fFullTraceHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
741 fTimeRangeHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
743 if ((fFullTraceRequest
!= null) && fFullTraceRequest
.getRange().getEndTime().compareTo(signal
.getRange().getEndTime()) < 0) {
744 sendFullRangeRequest(fullRange
);
749 * Handles the selection range updated signal. Sets the current time
750 * selection in the time range histogram as well as the full histogram.
753 * the signal to process
757 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal
) {
758 if (Display
.getCurrent() == null) {
759 // Make sure the signal is handled in the UI thread
760 Display
.getDefault().asyncExec(new Runnable() {
763 if (getParentComposite().isDisposed()) {
766 selectionRangeUpdated(signal
);
772 // Update the selected time range
773 ITmfTimestamp beginTime
= signal
.getBeginTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
);
774 ITmfTimestamp endTime
= signal
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
);
775 updateDisplayedSelectionTime(beginTime
.getValue(), endTime
.getValue());
779 * Updates the current window time range in the time range histogram and
780 * full range histogram.
783 * the signal to process
787 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal
) {
788 if (Display
.getCurrent() == null) {
789 // Make sure the signal is handled in the UI thread
790 Display
.getDefault().asyncExec(new Runnable() {
793 if (getParentComposite().isDisposed()) {
796 windowRangeUpdated(signal
);
802 if (fTrace
!= null) {
803 // Validate the time range
804 TmfTimeRange range
= signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange());
809 updateDisplayedTimeRange(
810 range
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue(),
811 range
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue());
813 // Send the event request to populate the small histogram
814 sendTimeRangeRequest(fWindowStartTime
, fWindowEndTime
);
816 fTimeSpanControl
.setValue(fWindowSpan
);
820 // ------------------------------------------------------------------------
822 // ------------------------------------------------------------------------
824 private void initializeHistograms() {
825 TmfTimeRange fullRange
= updateTraceTimeRange();
827 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
828 long selectionBeginTime
= ctx
.getSelectionRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
829 long selectionEndTime
= ctx
.getSelectionRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
830 long startTime
= ctx
.getWindowRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
831 long duration
= ctx
.getWindowRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue() - startTime
;
833 if ((fTimeRangeRequest
!= null) && !fTimeRangeRequest
.isCompleted()) {
834 fTimeRangeRequest
.cancel();
836 fTimeRangeHistogram
.clear();
837 fTimeRangeHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
838 fTimeRangeHistogram
.setTimeRange(startTime
, duration
);
839 fTimeRangeHistogram
.setSelection(selectionBeginTime
, selectionEndTime
);
840 fTimeRangeHistogram
.fDataModel
.setTrace(fTrace
);
842 if ((fFullTraceRequest
!= null) && !fFullTraceRequest
.isCompleted()) {
843 fFullTraceRequest
.cancel();
845 fFullTraceHistogram
.clear();
846 fFullTraceHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
847 fFullTraceHistogram
.setTimeRange(startTime
, duration
);
848 fFullTraceHistogram
.setSelection(selectionBeginTime
, selectionEndTime
);
849 fFullTraceHistogram
.fDataModel
.setTrace(fTrace
);
851 fWindowStartTime
= startTime
;
852 fWindowSpan
= duration
;
853 fWindowEndTime
= startTime
+ duration
;
855 fSelectionBeginTime
= selectionBeginTime
;
856 fSelectionEndTime
= selectionEndTime
;
857 fSelectionStartControl
.setValue(fSelectionBeginTime
);
858 fSelectionEndControl
.setValue(fSelectionEndTime
);
860 // make sure that the scrollbar is setup properly
861 fScrollComposite
.setMinSize(fTimeControlsComposite
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
862 fTimeSpanControl
.setValue(duration
);
864 Collection
<ITmfTrace
> traces
= TmfTraceManager
.getTraceSet(fTrace
);
865 if (!traces
.isEmpty()) {
866 this.showTraceAction
.setEnabled(traces
.size() < fFullTraceHistogram
.getMaxNbTraces());
870 if (!fullRange
.equals(TmfTimeRange
.NULL_RANGE
)) {
871 sendTimeRangeRequest(startTime
, startTime
+ duration
);
872 sendFullRangeRequest(fullRange
);
876 private void updateLegendArea() {
877 for (Control c
: fLegendArea
.getChildren()) {
880 disposeLegendImages();
881 if (fFullTraceHistogram
.showTraces()) {
882 Collection
<ITmfTrace
> traces
= TmfTraceManager
.getTraceSet(fTrace
);
883 fLegendImages
= new Image
[traces
.size()];
885 for (ITmfTrace trace
: traces
) {
886 fLegendImages
[traceIndex
] = new Image(fLegendArea
.getDisplay(), 16, 16);
887 GC gc
= new GC(fLegendImages
[traceIndex
]);
888 gc
.setBackground(fFullTraceHistogram
.getTraceColor(traceIndex
));
889 gc
.fillRectangle(0, 0, 15, 15);
890 gc
.setForeground(fLegendArea
.getDisplay().getSystemColor(SWT
.COLOR_BLACK
));
891 gc
.drawRectangle(0, 0, 15, 15);
894 CLabel label
= new CLabel(fLegendArea
, SWT
.NONE
);
895 label
.setText(trace
.getName());
896 label
.setImage(fLegendImages
[traceIndex
]);
900 fLegendArea
.layout();
901 fLegendArea
.getParent().layout();
904 private void updateDisplayedSelectionTime(long beginTime
, long endTime
) {
905 fSelectionBeginTime
= beginTime
;
906 fSelectionEndTime
= endTime
;
908 fFullTraceHistogram
.setSelection(fSelectionBeginTime
, fSelectionEndTime
);
909 fTimeRangeHistogram
.setSelection(fSelectionBeginTime
, fSelectionEndTime
);
910 fSelectionStartControl
.setValue(fSelectionBeginTime
);
911 fSelectionEndControl
.setValue(fSelectionEndTime
);
914 private void updateDisplayedTimeRange(long start
, long end
) {
915 fWindowStartTime
= start
;
916 fWindowEndTime
= end
;
917 fWindowSpan
= fWindowEndTime
- fWindowStartTime
;
918 fFullTraceHistogram
.setTimeRange(fWindowStartTime
, fWindowSpan
);
921 private TmfTimeRange
updateTraceTimeRange() {
922 fTraceStartTime
= 0L;
925 TmfTimeRange timeRange
= fTrace
.getTimeRange();
926 if (!timeRange
.equals(TmfTimeRange
.NULL_RANGE
)) {
927 fTraceStartTime
= timeRange
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
928 fTraceEndTime
= timeRange
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
933 private void sendTimeRangeRequest(long startTime
, long endTime
) {
934 if ((fTimeRangeRequest
!= null) && !fTimeRangeRequest
.isCompleted()) {
935 fTimeRangeRequest
.cancel();
937 TmfTimestamp startTS
= new TmfTimestamp(startTime
, ITmfTimestamp
.NANOSECOND_SCALE
);
938 TmfTimestamp endTS
= new TmfTimestamp(endTime
, ITmfTimestamp
.NANOSECOND_SCALE
);
939 TmfTimeRange timeRange
= new TmfTimeRange(startTS
, endTS
);
941 fTimeRangeHistogram
.clear();
942 fTimeRangeHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
943 fTimeRangeHistogram
.setTimeRange(startTime
, endTime
- startTime
);
945 int cacheSize
= fTrace
.getCacheSize();
946 fTimeRangeRequest
= new HistogramRequest(fTimeRangeHistogram
.getDataModel(),
947 timeRange
, 0, ITmfEventRequest
.ALL_DATA
, cacheSize
, ExecutionType
.FOREGROUND
, false);
948 fTrace
.sendRequest(fTimeRangeRequest
);
951 private void sendFullRangeRequest(TmfTimeRange fullRange
) {
952 if ((fFullTraceRequest
!= null) && !fFullTraceRequest
.isCompleted()) {
953 fFullTraceRequest
.cancel();
955 int cacheSize
= fTrace
.getCacheSize();
956 fFullTraceRequest
= new HistogramRequest(fFullTraceHistogram
.getDataModel(),
958 (int) fFullTraceHistogram
.fDataModel
.getNbEvents(),
959 ITmfEventRequest
.ALL_DATA
,
961 ExecutionType
.BACKGROUND
, true);
962 fTrace
.sendRequest(fFullTraceRequest
);
965 private void contributeToActionBars() {
966 IActionBars bars
= getViewSite().getActionBars();
967 bars
.getToolBarManager().add(getShowLostEventsAction());
968 bars
.getToolBarManager().add(getShowTraceAction());
969 bars
.getToolBarManager().add(new Separator());
972 private void addLinkButtonListeners() {
973 fLinkButton
.addMouseListener(new MouseAdapter() {
975 public void mouseDown(MouseEvent e
) {
976 fSelectionEndControl
.setEnabled(fLinkState
);
977 fLinkState
= !fLinkState
;
978 fLinkButton
.redraw();
982 fLinkButton
.addPaintListener(new PaintListener() {
984 public void paintControl(PaintEvent e
) {
986 Rectangle r
= fLinkButton
.getBounds();
989 e
.gc
.setForeground(e
.display
.getSystemColor(SWT
.COLOR_WIDGET_NORMAL_SHADOW
));
990 e
.gc
.drawRectangle(r
);
993 e
.gc
.setForeground(e
.display
.getSystemColor(SWT
.COLOR_DARK_GRAY
));
994 e
.gc
.drawRectangle(r
);
1000 private static class PackedScrolledComposite
extends ScrolledComposite
{
1001 Point fScrollBarSize
; // Size of OS-specific scrollbar
1003 public PackedScrolledComposite(Composite parent
, int style
) {
1004 super(parent
, style
);
1005 Composite composite
= new Composite(parent
, SWT
.H_SCROLL
| SWT
.V_SCROLL
);
1006 composite
.setSize(1, 1);
1007 fScrollBarSize
= composite
.computeSize(0, 0);
1008 composite
.dispose();
1012 public Point
computeSize(int wHint
, int hHint
, boolean changed
) {
1013 Point point
= super.computeSize(wHint
, hHint
, changed
);
1014 // Remove scrollbar size if applicable
1015 point
.x
+= ((getStyle() & SWT
.V_SCROLL
) != 0) ?
-fScrollBarSize
.x
: 0;
1016 point
.y
+= ((getStyle() & SWT
.H_SCROLL
) != 0) ?
-fScrollBarSize
.y
: 0;