1 /*******************************************************************************
2 * Copyright (c) 2009, 2010, 2011 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 *******************************************************************************/
17 package org
.eclipse
.linuxtools
.lttng
.ui
.views
.histogram
;
19 import org
.eclipse
.linuxtools
.lttng
.event
.LttngEvent
;
20 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimeRange
;
21 import org
.eclipse
.linuxtools
.tmf
.event
.TmfTimestamp
;
22 import org
.eclipse
.linuxtools
.tmf
.experiment
.TmfExperiment
;
23 import org
.eclipse
.linuxtools
.tmf
.request
.ITmfDataRequest
.ExecutionType
;
24 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfExperimentRangeUpdatedSignal
;
25 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfExperimentSelectedSignal
;
26 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfRangeSynchSignal
;
27 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfSignalHandler
;
28 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfSignalManager
;
29 import org
.eclipse
.linuxtools
.tmf
.signal
.TmfTimeSynchSignal
;
30 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.TmfView
;
31 import org
.eclipse
.swt
.SWT
;
32 import org
.eclipse
.swt
.layout
.GridData
;
33 import org
.eclipse
.swt
.layout
.GridLayout
;
34 import org
.eclipse
.swt
.widgets
.Composite
;
37 * <b><u>HistogramView</u></b>
39 * The purpose of this view is to provide graphical time distribution statistics about the experiment/trace events.
41 * The view is composed of two histograms and two controls:
43 * <li>an event distribution histogram for the whole experiment;
44 * <li>an event distribution histogram for current time window (window span);
45 * <li>the timestamp of the currently selected event;
46 * <li>the window span (size of the time window of the smaller histogram).
48 * The histograms x-axis show their respective time range.
50 public class HistogramView
extends TmfView
{
52 // ------------------------------------------------------------------------
54 // ------------------------------------------------------------------------
56 // The view ID as defined in plugin.xml
57 public static final String ID
= "org.eclipse.linuxtools.lttng.ui.views.histogram"; //$NON-NLS-1$
59 // The initial window span (in nanoseconds)
60 public static long INITIAL_WINDOW_SPAN
= (1L * 100 * 1000 * 1000); // .1sec
63 private final byte TIME_SCALE
= Histogram
.TIME_SCALE
;
65 // ------------------------------------------------------------------------
67 // ------------------------------------------------------------------------
70 private Composite fParent
;
72 // The current experiment
73 private TmfExperiment
<LttngEvent
> fCurrentExperiment
;
75 // Current timestamp/time window
76 private long fExperimentStartTime
;
77 private long fExperimentEndTime
;
78 private long fWindowStartTime
;
79 private long fWindowEndTime
;
80 private long fWindowSpan
= INITIAL_WINDOW_SPAN
;
81 private long fCurrentTimestamp
;
84 private HistogramTextControl fCurrentEventTimeControl
;
85 private HistogramTextControl fTimeSpanControl
;
87 // Histogram/request for the full trace range
88 private static FullTraceHistogram fFullTraceHistogram
;
89 private HistogramRequest fFullTraceRequest
;
91 // Histogram/request for the selected time range
92 private static TimeRangeHistogram fTimeRangeHistogram
;
93 private HistogramRequest fTimeRangeRequest
;
95 // ------------------------------------------------------------------------
97 // ------------------------------------------------------------------------
99 public HistogramView() {
104 public void dispose() {
105 if (fTimeRangeRequest
!= null && !fTimeRangeRequest
.isCompleted()) {
106 fTimeRangeRequest
.cancel();
108 if (fFullTraceRequest
!= null && !fFullTraceRequest
.isCompleted()) {
109 fFullTraceRequest
.cancel();
111 fFullTraceHistogram
.dispose();
112 fTimeRangeHistogram
.dispose();
116 // ------------------------------------------------------------------------
118 // ------------------------------------------------------------------------
121 @SuppressWarnings("unchecked")
122 public void createPartControl(Composite parent
) {
127 final String currentEventLabel
= Messages
.HistogramView_currentEventLabel
;
128 final String windowSpanLabel
= Messages
.HistogramView_windowSpanLabel
;
130 // --------------------------------------------------------------------
131 // Set the HistogramView layout
132 // --------------------------------------------------------------------
134 Composite viewComposite
= new Composite(fParent
, SWT
.FILL
);
135 GridLayout gridLayout
= new GridLayout();
136 gridLayout
.numColumns
= 2;
137 gridLayout
.horizontalSpacing
= 5;
138 gridLayout
.verticalSpacing
= 0;
139 gridLayout
.marginHeight
= 0;
140 gridLayout
.marginWidth
= 0;
141 viewComposite
.setLayout(gridLayout
);
143 // Use all available space
144 GridData gridData
= new GridData();
145 gridData
.horizontalAlignment
= SWT
.FILL
;
146 gridData
.verticalAlignment
= SWT
.FILL
;
147 gridData
.grabExcessHorizontalSpace
= true;
148 viewComposite
.setLayoutData(gridData
);
150 // --------------------------------------------------------------------
152 // --------------------------------------------------------------------
154 Composite controlsComposite
= new Composite(viewComposite
, SWT
.FILL
);
155 gridLayout
= new GridLayout();
156 gridLayout
.numColumns
= 2;
157 gridLayout
.marginHeight
= 0;
158 gridLayout
.marginWidth
= 0;
159 gridLayout
.horizontalSpacing
= 5;
160 gridLayout
.verticalSpacing
= 0;
161 gridLayout
.makeColumnsEqualWidth
= true;
162 gridLayout
.marginLeft
= 5;
163 gridLayout
.marginRight
= 5;
164 controlsComposite
.setLayout(gridLayout
);
166 // Current event time control
167 gridData
= new GridData();
168 gridData
.horizontalAlignment
= SWT
.CENTER
;
169 gridData
.verticalAlignment
= SWT
.CENTER
;
170 fCurrentEventTimeControl
= new HistogramCurrentTimeControl(this, controlsComposite
, SWT
.BORDER
, SWT
.BORDER
,
171 currentEventLabel
, HistogramUtils
.nanosecondsToString(0L));
172 fCurrentEventTimeControl
.setLayoutData(gridData
);
174 // Window span time control
175 gridData
= new GridData();
176 gridData
.horizontalAlignment
= SWT
.CENTER
;
177 gridData
.verticalAlignment
= SWT
.CENTER
;
178 fTimeSpanControl
= new HistogramTimeRangeControl(this, controlsComposite
, SWT
.BORDER
, SWT
.BORDER
,
179 windowSpanLabel
, HistogramUtils
.nanosecondsToString(0L));
180 fTimeSpanControl
.setLayoutData(gridData
);
182 // --------------------------------------------------------------------
183 // Time range histogram
184 // --------------------------------------------------------------------
186 Composite timeRangeComposite
= new Composite(viewComposite
, SWT
.FILL
);
187 gridLayout
= new GridLayout();
188 gridLayout
.numColumns
= 1;
189 gridLayout
.marginHeight
= 0;
190 gridLayout
.marginWidth
= 0;
191 gridLayout
.marginTop
= 5;
192 gridLayout
.horizontalSpacing
= 0;
193 gridLayout
.verticalSpacing
= 0;
194 gridLayout
.marginLeft
= 5;
195 gridLayout
.marginRight
= 5;
196 timeRangeComposite
.setLayout(gridLayout
);
198 // Use remaining horizontal space
199 gridData
= new GridData();
200 gridData
.horizontalAlignment
= SWT
.FILL
;
201 gridData
.verticalAlignment
= SWT
.FILL
;
202 gridData
.grabExcessHorizontalSpace
= true;
203 timeRangeComposite
.setLayoutData(gridData
);
206 fTimeRangeHistogram
= new TimeRangeHistogram(this, timeRangeComposite
);
208 // --------------------------------------------------------------------
209 // Full range histogram
210 // --------------------------------------------------------------------
212 Composite fullRangeComposite
= new Composite(viewComposite
, SWT
.FILL
);
213 gridLayout
= new GridLayout();
214 gridLayout
.numColumns
= 1;
215 gridLayout
.marginHeight
= 0;
216 gridLayout
.marginWidth
= 0;
217 gridLayout
.marginTop
= 5;
218 gridLayout
.horizontalSpacing
= 0;
219 gridLayout
.verticalSpacing
= 0;
220 gridLayout
.marginLeft
= 5;
221 gridLayout
.marginRight
= 5;
222 fullRangeComposite
.setLayout(gridLayout
);
224 // Use remaining horizontal space
225 gridData
= new GridData();
226 gridData
.horizontalAlignment
= SWT
.FILL
;
227 gridData
.verticalAlignment
= SWT
.FILL
;
228 gridData
.horizontalSpan
= 2;
229 gridData
.grabExcessHorizontalSpace
= true;
230 fullRangeComposite
.setLayoutData(gridData
);
233 fFullTraceHistogram
= new FullTraceHistogram(this, fullRangeComposite
);
235 // Load the experiment if present
236 fCurrentExperiment
= (TmfExperiment
<LttngEvent
>) TmfExperiment
.getCurrentExperiment();
237 if (fCurrentExperiment
!= null)
242 @SuppressWarnings("unchecked")
243 public void setFocus() {
244 TmfExperiment
<LttngEvent
> experiment
= (TmfExperiment
<LttngEvent
>) TmfExperiment
.getCurrentExperiment();
245 if ((experiment
!= null) && (experiment
!= fCurrentExperiment
)) {
246 fCurrentExperiment
= experiment
;
247 initializeHistograms();
252 // ------------------------------------------------------------------------
254 // ------------------------------------------------------------------------
256 public TmfTimeRange
getTimeRange() {
257 return new TmfTimeRange(new TmfTimestamp(fWindowStartTime
, TIME_SCALE
), new TmfTimestamp(fWindowEndTime
,
261 // ------------------------------------------------------------------------
263 // ------------------------------------------------------------------------
265 public void updateCurrentEventTime(long newTime
) {
266 if (fCurrentExperiment
!= null) {
267 TmfTimeRange timeRange
= new TmfTimeRange(new TmfTimestamp(newTime
, TIME_SCALE
), TmfTimestamp
.BigCrunch
);
268 HistogramRequest request
= new HistogramRequest(fTimeRangeHistogram
, timeRange
, 0, 1,
269 ExecutionType
.FOREGROUND
) {
271 public void handleData(LttngEvent event
) {
273 TmfTimeSynchSignal signal
= new TmfTimeSynchSignal(this, event
.getTimestamp());
274 TmfSignalManager
.dispatchSignal(signal
);
278 fCurrentExperiment
.sendRequest(request
);
282 public void updateTimeRange(long startTime
, long endTime
) {
283 if (fCurrentExperiment
!= null) {
284 // Build the new time range; keep the current time
285 TmfTimeRange timeRange
= new TmfTimeRange(new TmfTimestamp(startTime
, TIME_SCALE
), new TmfTimestamp(
286 endTime
, TIME_SCALE
));
287 TmfTimestamp currentTime
= new TmfTimestamp(fCurrentTimestamp
, TIME_SCALE
);
289 fTimeSpanControl
.setValue(endTime
- startTime
);
291 // Send the FW signal
292 TmfRangeSynchSignal signal
= new TmfRangeSynchSignal(this, timeRange
, currentTime
);
293 TmfSignalManager
.dispatchSignal(signal
);
297 public synchronized void updateTimeRange(long newDuration
) {
298 if (fCurrentExperiment
!= null) {
299 long delta
= newDuration
- fWindowSpan
;
300 long newStartTime
= fWindowStartTime
+ delta
/ 2;
301 setNewRange(newStartTime
, newDuration
);
305 private void setNewRange(long startTime
, long duration
) {
306 if (startTime
< fExperimentStartTime
)
307 startTime
= fExperimentStartTime
;
309 long endTime
= startTime
+ duration
;
310 if (endTime
> fExperimentEndTime
) {
311 endTime
= fExperimentEndTime
;
312 if (endTime
- duration
> fExperimentStartTime
)
313 startTime
= endTime
- duration
;
315 startTime
= fExperimentStartTime
;
318 updateTimeRange(startTime
, endTime
);
321 // ------------------------------------------------------------------------
323 // ------------------------------------------------------------------------
326 @SuppressWarnings("unchecked")
327 public void experimentSelected(TmfExperimentSelectedSignal
<LttngEvent
> signal
) {
328 assert (signal
!= null);
329 fCurrentExperiment
= (TmfExperiment
<LttngEvent
>) signal
.getExperiment();
333 private void loadExperiment() {
334 initializeHistograms();
339 @SuppressWarnings("unchecked")
340 public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal
) {
342 fCurrentExperiment
= (TmfExperiment
<LttngEvent
>) signal
.getExperiment();
343 boolean drawTimeRangeHistogram
= fExperimentStartTime
== 0;
344 TmfTimeRange fullRange
= signal
.getRange();
346 fExperimentStartTime
= fullRange
.getStartTime().getValue();
347 fExperimentEndTime
= fullRange
.getEndTime().getValue();
349 fFullTraceHistogram
.setFullRange(fExperimentStartTime
, fExperimentEndTime
);
350 fTimeRangeHistogram
.setFullRange(fExperimentStartTime
, fExperimentEndTime
);
352 if (drawTimeRangeHistogram
) {
353 fCurrentTimestamp
= fExperimentStartTime
;
354 fCurrentEventTimeControl
.setValue(fCurrentTimestamp
);
355 fFullTraceHistogram
.setTimeRange(fExperimentStartTime
, INITIAL_WINDOW_SPAN
);
356 fTimeRangeHistogram
.setTimeRange(fExperimentStartTime
, INITIAL_WINDOW_SPAN
);
357 sendTimeRangeRequest(fExperimentStartTime
, fExperimentStartTime
+ INITIAL_WINDOW_SPAN
);
360 sendFullRangeRequest(fullRange
);
364 public void currentTimeUpdated(TmfTimeSynchSignal signal
) {
365 // Because this can't happen :-)
366 assert (signal
!= null);
368 // Update the selected event time
369 TmfTimestamp currentTime
= signal
.getCurrentTime();
370 fCurrentTimestamp
= currentTime
.getValue();
372 // Notify the relevant widgets
373 fFullTraceHistogram
.setCurrentEvent(fCurrentTimestamp
);
374 fTimeRangeHistogram
.setCurrentEvent(fCurrentTimestamp
);
375 fCurrentEventTimeControl
.setValue(fCurrentTimestamp
);
379 public void timeRangeUpdated(TmfRangeSynchSignal signal
) {
380 // Because this can't happen :-)
381 assert (signal
!= null);
383 if (fCurrentExperiment
!= null) {
384 // Update the time range
385 fWindowStartTime
= signal
.getCurrentRange().getStartTime().getValue();
386 fWindowEndTime
= signal
.getCurrentRange().getEndTime().getValue();
387 fWindowSpan
= fWindowEndTime
- fWindowStartTime
;
389 // Notify the relevant widgets
390 sendTimeRangeRequest(fWindowStartTime
, fWindowEndTime
);
391 fFullTraceHistogram
.setTimeRange(fWindowStartTime
, fWindowSpan
);
392 fTimeSpanControl
.setValue(fWindowSpan
);
396 // ------------------------------------------------------------------------
398 // ------------------------------------------------------------------------
400 private void initializeHistograms() {
401 TmfTimeRange fullRange
= updateExperimentTimeRange(fCurrentExperiment
);
403 fTimeRangeHistogram
.clear();
404 fTimeRangeHistogram
.setFullRange(fExperimentStartTime
, fExperimentEndTime
);
405 fTimeRangeHistogram
.setTimeRange(fExperimentStartTime
, INITIAL_WINDOW_SPAN
);
406 fTimeRangeHistogram
.setCurrentEvent(fExperimentStartTime
);
408 fFullTraceHistogram
.clear();
409 fFullTraceHistogram
.setFullRange(fExperimentStartTime
, fExperimentEndTime
);
410 fFullTraceHistogram
.setTimeRange(fExperimentStartTime
, INITIAL_WINDOW_SPAN
);
411 fFullTraceHistogram
.setCurrentEvent(fExperimentStartTime
);
413 fWindowStartTime
= fExperimentStartTime
;
414 fWindowSpan
= INITIAL_WINDOW_SPAN
;
415 fWindowEndTime
= fWindowStartTime
+ fWindowSpan
;
417 fCurrentEventTimeControl
.setValue(fExperimentStartTime
);
418 fTimeSpanControl
.setValue(fWindowSpan
);
420 sendTimeRangeRequest(fExperimentStartTime
, fExperimentStartTime
+ fWindowSpan
);
421 sendFullRangeRequest(fullRange
);
424 private TmfTimeRange
updateExperimentTimeRange(TmfExperiment
<LttngEvent
> experiment
) {
425 fExperimentStartTime
= 0;
426 fExperimentEndTime
= 0;
427 fCurrentTimestamp
= 0;
429 TmfTimeRange timeRange
= fCurrentExperiment
.getTimeRange();
430 if (timeRange
!= TmfTimeRange
.Null
) {
431 fExperimentStartTime
= timeRange
.getStartTime().getValue();
432 fExperimentEndTime
= timeRange
.getEndTime().getValue();
433 fCurrentTimestamp
= fExperimentStartTime
;
438 private void sendTimeRangeRequest(long startTime
, long endTime
) {
439 if (fTimeRangeRequest
!= null && !fTimeRangeRequest
.isCompleted()) {
440 fTimeRangeRequest
.cancel();
442 TmfTimestamp startTS
= new TmfTimestamp(startTime
, TIME_SCALE
);
443 TmfTimestamp endTS
= new TmfTimestamp(endTime
, TIME_SCALE
);
444 TmfTimeRange timeRange
= new TmfTimeRange(startTS
, endTS
);
446 fTimeRangeHistogram
.clear();
447 fTimeRangeHistogram
.setTimeRange(startTime
, endTime
- startTime
);
448 fTimeRangeRequest
= new HistogramRequest(fTimeRangeHistogram
, timeRange
, ExecutionType
.FOREGROUND
);
449 fCurrentExperiment
.sendRequest(fTimeRangeRequest
);
452 private void sendFullRangeRequest(TmfTimeRange fullRange
) {
453 if (fFullTraceRequest
!= null && !fFullTraceRequest
.isCompleted()) {
454 fFullTraceRequest
.cancel();
456 fFullTraceRequest
= new HistogramRequest(fFullTraceHistogram
, fullRange
,
457 (int) fFullTraceHistogram
.fDataModel
.getNbEvents(), ExecutionType
.BACKGROUND
);
458 fCurrentExperiment
.sendRequest(fFullTraceRequest
);