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 // TODO this is just an approximation that assumes that the end will be at the same position but that can change for a different data range/scaling
427 int endOffset
= curTimeAxisOffset
+ pointAreaWidth
;
428 GridLayout layout
= (GridLayout
) fTimeRangeComposite
.getLayout();
429 int endOffsetWithoutMargin
= endOffset
+ layout
.marginRight
;
430 int availableWidth
= endOffsetWithoutMargin
- requestedOffset
;
431 availableWidth
= Math
.min(fSashForm
.getBounds().width
, Math
.max(0, availableWidth
));
433 return availableWidth
;
440 public void performAlign(int offset
, int width
) {
441 int total
= fSashForm
.getBounds().width
;
442 int plotAreaOffset
= fTimeRangeHistogram
.getPointAreaOffset();
443 int width1
= Math
.max(0, offset
- plotAreaOffset
- fSashForm
.getSashWidth());
444 int width2
= Math
.max(0, total
- width1
- fSashForm
.getSashWidth());
445 fSashForm
.setWeights(new int[] { width1
, width2
});
448 // calculate right margin
449 GridLayout layout
= (GridLayout
) fTimeRangeComposite
.getLayout();
450 int timeBasedControlsWidth
= fTimeRangeComposite
.getSize().x
;
451 int marginSize
= timeBasedControlsWidth
- width
- plotAreaOffset
;
452 layout
.marginRight
= Math
.max(0, marginSize
);
453 fTimeRangeComposite
.layout();
456 // ------------------------------------------------------------------------
458 // ------------------------------------------------------------------------
461 * Returns the current trace handled by the view
463 * @return the current trace
465 public ITmfTrace
getTrace() {
470 * Returns the time range of the current selected window (base on default time scale).
472 * @return the time range of current selected window.
474 public TmfTimeRange
getTimeRange() {
475 return new TmfTimeRange(
476 new TmfTimestamp(fWindowStartTime
, ITmfTimestamp
.NANOSECOND_SCALE
),
477 new TmfTimestamp(fWindowEndTime
, ITmfTimestamp
.NANOSECOND_SCALE
));
481 * get the show lost events action
483 * @return The action object
485 public Action
getShowLostEventsAction() {
486 if (hideLostEventsAction
== null) {
487 /* show lost events */
488 hideLostEventsAction
= new Action(Messages
.HistogramView_hideLostEvents
, IAction
.AS_CHECK_BOX
) {
491 HistogramScaledData
.hideLostEvents
= hideLostEventsAction
.isChecked();
492 long maxNbEvents
= HistogramScaledData
.hideLostEvents ? fFullTraceHistogram
.fScaledData
.fMaxValue
: fFullTraceHistogram
.fScaledData
.fMaxCombinedValue
;
493 fFullTraceHistogram
.setMaxNbEvents(maxNbEvents
);
494 maxNbEvents
= HistogramScaledData
.hideLostEvents ? fTimeRangeHistogram
.fScaledData
.fMaxValue
: fTimeRangeHistogram
.fScaledData
.fMaxCombinedValue
;
495 fTimeRangeHistogram
.setMaxNbEvents(maxNbEvents
);
498 hideLostEventsAction
.setText(Messages
.HistogramView_hideLostEvents
);
499 hideLostEventsAction
.setToolTipText(Messages
.HistogramView_hideLostEvents
);
500 hideLostEventsAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(ITmfImageConstants
.IMG_UI_SHOW_LOST_EVENTS
));
502 return hideLostEventsAction
;
506 * get the show trace action
508 * @return The action object
510 public Action
getShowTraceAction() {
511 if (showTraceAction
== null) {
512 /* show lost events */
513 showTraceAction
= new Action(Messages
.HistogramView_showTraces
, IAction
.AS_CHECK_BOX
) {
516 Histogram
.showTraces
= showTraceAction
.isChecked();
517 fFullTraceHistogram
.fCanvas
.redraw();
518 fTimeRangeHistogram
.fCanvas
.redraw();
522 showTraceAction
.setChecked(true);
523 showTraceAction
.setText(Messages
.HistogramView_showTraces
);
524 showTraceAction
.setToolTipText(Messages
.HistogramView_showTraces
);
525 showTraceAction
.setImageDescriptor(Activator
.getDefault().getImageDescripterFromPath(ITmfImageConstants
.IMG_UI_SHOW_HIST_TRACES
));
527 return showTraceAction
;
530 // ------------------------------------------------------------------------
532 // ------------------------------------------------------------------------
535 * Broadcast TmfSignal about new current selection time range.
536 * @param beginTime the begin time of current selection.
537 * @param endTime the end time of current selection.
539 void updateSelectionTime(long beginTime
, long endTime
) {
540 updateDisplayedSelectionTime(beginTime
, endTime
);
541 TmfTimestamp beginTs
= new TmfTimestamp(beginTime
, ITmfTimestamp
.NANOSECOND_SCALE
);
542 TmfTimestamp endTs
= new TmfTimestamp(endTime
, ITmfTimestamp
.NANOSECOND_SCALE
);
543 TmfSelectionRangeUpdatedSignal signal
= new TmfSelectionRangeUpdatedSignal(this, beginTs
, endTs
);
544 fTimeSyncThrottle
.queue(signal
);
548 * Get selection begin time
549 * @return the begin time of current selection
551 long getSelectionBegin() {
552 return fSelectionBeginTime
;
556 * Get selection end time
557 * @return the end time of current selection
559 long getSelectionEnd() {
560 return fSelectionEndTime
;
565 * @return true if begin and end selection time should be linked
567 boolean getLinkState() {
572 * Broadcast TmfSignal about new selection time range.
573 * @param startTime the new start time
574 * @param endTime the new end time
576 void updateTimeRange(long startTime
, long endTime
) {
577 if (fTrace
!= null) {
578 // Build the new time range; keep the current time
579 TmfTimeRange timeRange
= new TmfTimeRange(
580 new TmfTimestamp(startTime
, ITmfTimestamp
.NANOSECOND_SCALE
),
581 new TmfTimestamp(endTime
, ITmfTimestamp
.NANOSECOND_SCALE
));
582 fTimeSpanControl
.setValue(endTime
- startTime
);
584 updateDisplayedTimeRange(startTime
, endTime
);
586 // Send the FW signal
587 TmfWindowRangeUpdatedSignal signal
= new TmfWindowRangeUpdatedSignal(this, timeRange
);
588 fTimeRangeSyncThrottle
.queue(signal
);
593 * Broadcast TmfSignal about new selected time range.
594 * @param newDuration new duration (relative to current start time)
596 public synchronized void updateTimeRange(long newDuration
) {
597 if (fTrace
!= null) {
598 long delta
= newDuration
- fWindowSpan
;
599 long newStartTime
= fWindowStartTime
- (delta
/ 2);
600 setNewRange(newStartTime
, newDuration
);
604 private void setNewRange(long startTime
, long duration
) {
605 long realStart
= startTime
;
607 if (realStart
< fTraceStartTime
) {
608 realStart
= fTraceStartTime
;
611 long endTime
= realStart
+ duration
;
612 if (endTime
> fTraceEndTime
) {
613 endTime
= fTraceEndTime
;
614 if ((endTime
- duration
) > fTraceStartTime
) {
615 realStart
= endTime
- duration
;
617 realStart
= fTraceStartTime
;
620 updateTimeRange(realStart
, endTime
);
623 // ------------------------------------------------------------------------
625 // ------------------------------------------------------------------------
628 * Handles trace opened signal. Loads histogram if new trace time range is not
629 * equal <code>TmfTimeRange.NULL_RANGE</code>
630 * @param signal the trace opened signal
633 public void traceOpened(TmfTraceOpenedSignal signal
) {
634 assert (signal
!= null);
635 fTrace
= signal
.getTrace();
640 * Handles trace selected signal. Loads histogram if new trace time range is not
641 * equal <code>TmfTimeRange.NULL_RANGE</code>
642 * @param signal the trace selected signal
645 public void traceSelected(TmfTraceSelectedSignal signal
) {
646 assert (signal
!= null);
647 if (fTrace
!= signal
.getTrace()) {
648 fTrace
= signal
.getTrace();
653 private void loadTrace() {
654 initializeHistograms();
655 getParentComposite().redraw();
659 * Handles trace closed signal. Clears the view and data model and cancels requests.
660 * @param signal the trace closed signal
663 public void traceClosed(TmfTraceClosedSignal signal
) {
665 if (signal
.getTrace() != fTrace
) {
669 // Kill any running request
670 if ((fTimeRangeRequest
!= null) && !fTimeRangeRequest
.isCompleted()) {
671 fTimeRangeRequest
.cancel();
673 if ((fFullTraceRequest
!= null) && !fFullTraceRequest
.isCompleted()) {
674 fFullTraceRequest
.cancel();
677 // Initialize the internal data
679 fTraceStartTime
= 0L;
681 fWindowStartTime
= 0L;
684 fSelectionBeginTime
= 0L;
685 fSelectionEndTime
= 0L;
687 // Clear the UI widgets
688 fFullTraceHistogram
.clear();
689 fTimeRangeHistogram
.clear();
690 fSelectionStartControl
.setValue(Long
.MIN_VALUE
);
691 fSelectionEndControl
.setValue(Long
.MIN_VALUE
);
693 fTimeSpanControl
.setValue(Long
.MIN_VALUE
);
695 for (Control c
: fLegendArea
.getChildren()) {
698 disposeLegendImages();
699 fLegendArea
.layout();
700 fLegendArea
.getParent().layout();
704 * Handles trace range updated signal. Extends histogram according to the new time range. If a
705 * HistogramRequest is already ongoing, it will be cancelled and a new request with the new range
708 * @param signal the trace range updated signal
711 public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal
) {
713 if (signal
.getTrace() != fTrace
) {
717 TmfTimeRange fullRange
= signal
.getRange();
719 fTraceStartTime
= fullRange
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
720 fTraceEndTime
= fullRange
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
722 fFullTraceHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
723 fTimeRangeHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
725 sendFullRangeRequest(fullRange
);
729 * Handles the trace updated signal. Used to update time limits (start and end time)
730 * @param signal the trace updated signal
733 public void traceUpdated(TmfTraceUpdatedSignal signal
) {
734 if (signal
.getTrace() != fTrace
) {
737 TmfTimeRange fullRange
= signal
.getTrace().getTimeRange();
738 fTraceStartTime
= fullRange
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
739 fTraceEndTime
= fullRange
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
741 fFullTraceHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
742 fTimeRangeHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
744 if ((fFullTraceRequest
!= null) && fFullTraceRequest
.getRange().getEndTime().compareTo(signal
.getRange().getEndTime()) < 0) {
745 sendFullRangeRequest(fullRange
);
750 * Handles the selection range updated signal. Sets the current time
751 * selection in the time range histogram as well as the full histogram.
754 * the signal to process
758 public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal
) {
759 if (Display
.getCurrent() == null) {
760 // Make sure the signal is handled in the UI thread
761 Display
.getDefault().asyncExec(new Runnable() {
764 if (getParentComposite().isDisposed()) {
767 selectionRangeUpdated(signal
);
773 // Update the selected time range
774 ITmfTimestamp beginTime
= signal
.getBeginTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
);
775 ITmfTimestamp endTime
= signal
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
);
776 updateDisplayedSelectionTime(beginTime
.getValue(), endTime
.getValue());
780 * Updates the current window time range in the time range histogram and
781 * full range histogram.
784 * the signal to process
788 public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal
) {
789 if (Display
.getCurrent() == null) {
790 // Make sure the signal is handled in the UI thread
791 Display
.getDefault().asyncExec(new Runnable() {
794 if (getParentComposite().isDisposed()) {
797 windowRangeUpdated(signal
);
803 if (fTrace
!= null) {
804 // Validate the time range
805 TmfTimeRange range
= signal
.getCurrentRange().getIntersection(fTrace
.getTimeRange());
810 updateDisplayedTimeRange(
811 range
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue(),
812 range
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue());
814 // Send the event request to populate the small histogram
815 sendTimeRangeRequest(fWindowStartTime
, fWindowEndTime
);
817 fTimeSpanControl
.setValue(fWindowSpan
);
821 // ------------------------------------------------------------------------
823 // ------------------------------------------------------------------------
825 private void initializeHistograms() {
826 TmfTimeRange fullRange
= updateTraceTimeRange();
828 TmfTraceContext ctx
= TmfTraceManager
.getInstance().getCurrentTraceContext();
829 long selectionBeginTime
= ctx
.getSelectionRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
830 long selectionEndTime
= ctx
.getSelectionRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
831 long startTime
= ctx
.getWindowRange().getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
832 long duration
= ctx
.getWindowRange().getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue() - startTime
;
834 if ((fTimeRangeRequest
!= null) && !fTimeRangeRequest
.isCompleted()) {
835 fTimeRangeRequest
.cancel();
837 fTimeRangeHistogram
.clear();
838 fTimeRangeHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
839 fTimeRangeHistogram
.setTimeRange(startTime
, duration
);
840 fTimeRangeHistogram
.setSelection(selectionBeginTime
, selectionEndTime
);
841 fTimeRangeHistogram
.fDataModel
.setTrace(fTrace
);
843 if ((fFullTraceRequest
!= null) && !fFullTraceRequest
.isCompleted()) {
844 fFullTraceRequest
.cancel();
846 fFullTraceHistogram
.clear();
847 fFullTraceHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
848 fFullTraceHistogram
.setTimeRange(startTime
, duration
);
849 fFullTraceHistogram
.setSelection(selectionBeginTime
, selectionEndTime
);
850 fFullTraceHistogram
.fDataModel
.setTrace(fTrace
);
852 fWindowStartTime
= startTime
;
853 fWindowSpan
= duration
;
854 fWindowEndTime
= startTime
+ duration
;
856 fSelectionBeginTime
= selectionBeginTime
;
857 fSelectionEndTime
= selectionEndTime
;
858 fSelectionStartControl
.setValue(fSelectionBeginTime
);
859 fSelectionEndControl
.setValue(fSelectionEndTime
);
861 // make sure that the scrollbar is setup properly
862 fScrollComposite
.setMinSize(fTimeControlsComposite
.computeSize(SWT
.DEFAULT
, SWT
.DEFAULT
));
863 fTimeSpanControl
.setValue(duration
);
865 Collection
<ITmfTrace
> traces
= TmfTraceManager
.getTraceSet(fTrace
);
866 if (!traces
.isEmpty()) {
867 this.showTraceAction
.setEnabled(traces
.size() < fFullTraceHistogram
.getMaxNbTraces());
871 if (!fullRange
.equals(TmfTimeRange
.NULL_RANGE
)) {
872 sendTimeRangeRequest(startTime
, startTime
+ duration
);
873 sendFullRangeRequest(fullRange
);
877 private void updateLegendArea() {
878 for (Control c
: fLegendArea
.getChildren()) {
881 disposeLegendImages();
882 if (fFullTraceHistogram
.showTraces()) {
883 Collection
<ITmfTrace
> traces
= TmfTraceManager
.getTraceSet(fTrace
);
884 fLegendImages
= new Image
[traces
.size()];
886 for (ITmfTrace trace
: traces
) {
887 fLegendImages
[traceIndex
] = new Image(fLegendArea
.getDisplay(), 16, 16);
888 GC gc
= new GC(fLegendImages
[traceIndex
]);
889 gc
.setBackground(fFullTraceHistogram
.getTraceColor(traceIndex
));
890 gc
.fillRectangle(0, 0, 15, 15);
891 gc
.setForeground(fLegendArea
.getDisplay().getSystemColor(SWT
.COLOR_BLACK
));
892 gc
.drawRectangle(0, 0, 15, 15);
895 CLabel label
= new CLabel(fLegendArea
, SWT
.NONE
);
896 label
.setText(trace
.getName());
897 label
.setImage(fLegendImages
[traceIndex
]);
901 fLegendArea
.layout();
902 fLegendArea
.getParent().layout();
905 private void updateDisplayedSelectionTime(long beginTime
, long endTime
) {
906 fSelectionBeginTime
= beginTime
;
907 fSelectionEndTime
= endTime
;
909 fFullTraceHistogram
.setSelection(fSelectionBeginTime
, fSelectionEndTime
);
910 fTimeRangeHistogram
.setSelection(fSelectionBeginTime
, fSelectionEndTime
);
911 fSelectionStartControl
.setValue(fSelectionBeginTime
);
912 fSelectionEndControl
.setValue(fSelectionEndTime
);
915 private void updateDisplayedTimeRange(long start
, long end
) {
916 fWindowStartTime
= start
;
917 fWindowEndTime
= end
;
918 fWindowSpan
= fWindowEndTime
- fWindowStartTime
;
919 fFullTraceHistogram
.setTimeRange(fWindowStartTime
, fWindowSpan
);
922 private TmfTimeRange
updateTraceTimeRange() {
923 fTraceStartTime
= 0L;
926 TmfTimeRange timeRange
= fTrace
.getTimeRange();
927 if (!timeRange
.equals(TmfTimeRange
.NULL_RANGE
)) {
928 fTraceStartTime
= timeRange
.getStartTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
929 fTraceEndTime
= timeRange
.getEndTime().normalize(0, ITmfTimestamp
.NANOSECOND_SCALE
).getValue();
934 private void sendTimeRangeRequest(long startTime
, long endTime
) {
935 if ((fTimeRangeRequest
!= null) && !fTimeRangeRequest
.isCompleted()) {
936 fTimeRangeRequest
.cancel();
938 TmfTimestamp startTS
= new TmfTimestamp(startTime
, ITmfTimestamp
.NANOSECOND_SCALE
);
939 TmfTimestamp endTS
= new TmfTimestamp(endTime
, ITmfTimestamp
.NANOSECOND_SCALE
);
940 TmfTimeRange timeRange
= new TmfTimeRange(startTS
, endTS
);
942 fTimeRangeHistogram
.clear();
943 fTimeRangeHistogram
.setFullRange(fTraceStartTime
, fTraceEndTime
);
944 fTimeRangeHistogram
.setTimeRange(startTime
, endTime
- startTime
);
946 int cacheSize
= fTrace
.getCacheSize();
947 fTimeRangeRequest
= new HistogramRequest(fTimeRangeHistogram
.getDataModel(),
948 timeRange
, 0, ITmfEventRequest
.ALL_DATA
, cacheSize
, ExecutionType
.FOREGROUND
, false);
949 fTrace
.sendRequest(fTimeRangeRequest
);
952 private void sendFullRangeRequest(TmfTimeRange fullRange
) {
953 if ((fFullTraceRequest
!= null) && !fFullTraceRequest
.isCompleted()) {
954 fFullTraceRequest
.cancel();
956 int cacheSize
= fTrace
.getCacheSize();
957 fFullTraceRequest
= new HistogramRequest(fFullTraceHistogram
.getDataModel(),
959 (int) fFullTraceHistogram
.fDataModel
.getNbEvents(),
960 ITmfEventRequest
.ALL_DATA
,
962 ExecutionType
.BACKGROUND
, true);
963 fTrace
.sendRequest(fFullTraceRequest
);
966 private void contributeToActionBars() {
967 IActionBars bars
= getViewSite().getActionBars();
968 bars
.getToolBarManager().add(getShowLostEventsAction());
969 bars
.getToolBarManager().add(getShowTraceAction());
970 bars
.getToolBarManager().add(new Separator());
973 private void addLinkButtonListeners() {
974 fLinkButton
.addMouseListener(new MouseAdapter() {
976 public void mouseDown(MouseEvent e
) {
977 fSelectionEndControl
.setEnabled(fLinkState
);
978 fLinkState
= !fLinkState
;
979 fLinkButton
.redraw();
983 fLinkButton
.addPaintListener(new PaintListener() {
985 public void paintControl(PaintEvent e
) {
987 Rectangle r
= fLinkButton
.getBounds();
990 e
.gc
.setForeground(e
.display
.getSystemColor(SWT
.COLOR_WIDGET_NORMAL_SHADOW
));
991 e
.gc
.drawRectangle(r
);
994 e
.gc
.setForeground(e
.display
.getSystemColor(SWT
.COLOR_DARK_GRAY
));
995 e
.gc
.drawRectangle(r
);
1001 private static class PackedScrolledComposite
extends ScrolledComposite
{
1002 Point fScrollBarSize
; // Size of OS-specific scrollbar
1004 public PackedScrolledComposite(Composite parent
, int style
) {
1005 super(parent
, style
);
1006 Composite composite
= new Composite(parent
, SWT
.H_SCROLL
| SWT
.V_SCROLL
);
1007 composite
.setSize(1, 1);
1008 fScrollBarSize
= composite
.computeSize(0, 0);
1009 composite
.dispose();
1013 public Point
computeSize(int wHint
, int hHint
, boolean changed
) {
1014 Point point
= super.computeSize(wHint
, hHint
, changed
);
1015 // Remove scrollbar size if applicable
1016 point
.x
+= ((getStyle() & SWT
.V_SCROLL
) != 0) ?
-fScrollBarSize
.x
: 0;
1017 point
.y
+= ((getStyle() & SWT
.H_SCROLL
) != 0) ?
-fScrollBarSize
.y
: 0;