1 /*******************************************************************************
2 * Copyright (c) 2009, 2010, 2011, 2012 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 *******************************************************************************/
18 package org
.eclipse
.linuxtools
.tmf
.ui
.views
.histogram
;
20 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEvent
;
21 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfTimestamp
;
22 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimeRange
;
23 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimestamp
;
24 import org
.eclipse
.linuxtools
.tmf
.core
.experiment
.TmfExperiment
;
25 import org
.eclipse
.linuxtools
.tmf
.core
.request
.ITmfDataRequest
.ExecutionType
;
26 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfExperimentRangeUpdatedSignal
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfExperimentSelectedSignal
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfRangeSynchSignal
;
29 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalHandler
;
30 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfSignalManager
;
31 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTimeSynchSignal
;
32 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.TmfView
;
33 import org
.eclipse
.swt
.SWT
;
34 import org
.eclipse
.swt
.layout
.GridData
;
35 import org
.eclipse
.swt
.layout
.GridLayout
;
36 import org
.eclipse
.swt
.widgets
.Composite
;
39 * <b><u>HistogramView</u></b>
41 * The purpose of this view is to provide graphical time distribution statistics about the experiment/trace events.
43 * The view is composed of two histograms and two controls:
45 * <li>an event distribution histogram for the whole experiment;
46 * <li>an event distribution histogram for current time window (window span);
47 * <li>the timestamp of the currently selected event;
48 * <li>the window span (size of the time window of the smaller histogram).
50 * The histograms x-axis show their respective time range.
52 public class HistogramView
extends TmfView
{
54 // ------------------------------------------------------------------------
56 // ------------------------------------------------------------------------
58 // The view ID as defined in plugin.xml
59 public static final String ID
= "org.eclipse.linuxtools.tmf.ui.views.histogram"; //$NON-NLS-1$
61 // The initial window span (in nanoseconds)
62 public static final long INITIAL_WINDOW_SPAN
= (1L * 100 * 1000 * 1000); // .1sec
65 private final byte TIME_SCALE
= Histogram
.TIME_SCALE
;
67 // ------------------------------------------------------------------------
69 // ------------------------------------------------------------------------
72 private Composite fParent
;
74 // The current experiment
75 private TmfExperiment
<ITmfEvent
> fCurrentExperiment
;
77 // Current timestamp/time window
78 private long fExperimentStartTime
;
79 private long fExperimentEndTime
;
80 private long fWindowStartTime
;
81 private long fWindowEndTime
;
82 private long fWindowSpan
= INITIAL_WINDOW_SPAN
;
83 private long fCurrentTimestamp
;
86 private HistogramTextControl fCurrentEventTimeControl
;
87 private HistogramTextControl fTimeSpanControl
;
89 // Histogram/request for the full trace range
90 private static FullTraceHistogram fFullTraceHistogram
;
91 private HistogramRequest fFullTraceRequest
;
93 // Histogram/request for the selected time range
94 private static TimeRangeHistogram fTimeRangeHistogram
;
95 private HistogramRequest fTimeRangeRequest
;
97 // ------------------------------------------------------------------------
99 // ------------------------------------------------------------------------
101 public HistogramView() {
106 public void dispose() {
107 if (fTimeRangeRequest
!= null && !fTimeRangeRequest
.isCompleted()) {
108 fTimeRangeRequest
.cancel();
110 if (fFullTraceRequest
!= null && !fFullTraceRequest
.isCompleted()) {
111 fFullTraceRequest
.cancel();
113 fFullTraceHistogram
.dispose();
114 fTimeRangeHistogram
.dispose();
118 // ------------------------------------------------------------------------
120 // ------------------------------------------------------------------------
123 @SuppressWarnings("unchecked")
124 public void createPartControl(Composite parent
) {
129 final String currentEventLabel
= Messages
.HistogramView_currentEventLabel
;
130 final String windowSpanLabel
= Messages
.HistogramView_windowSpanLabel
;
132 // --------------------------------------------------------------------
133 // Set the HistogramView layout
134 // --------------------------------------------------------------------
136 Composite viewComposite
= new Composite(fParent
, SWT
.FILL
);
137 GridLayout gridLayout
= new GridLayout();
138 gridLayout
.numColumns
= 2;
139 gridLayout
.horizontalSpacing
= 5;
140 gridLayout
.verticalSpacing
= 0;
141 gridLayout
.marginHeight
= 0;
142 gridLayout
.marginWidth
= 0;
143 viewComposite
.setLayout(gridLayout
);
145 // Use all available space
146 GridData gridData
= new GridData();
147 gridData
.horizontalAlignment
= SWT
.FILL
;
148 gridData
.verticalAlignment
= SWT
.FILL
;
149 gridData
.grabExcessHorizontalSpace
= true;
150 viewComposite
.setLayoutData(gridData
);
152 // --------------------------------------------------------------------
154 // --------------------------------------------------------------------
156 Composite controlsComposite
= new Composite(viewComposite
, SWT
.FILL
);
157 gridLayout
= new GridLayout();
158 gridLayout
.numColumns
= 2;
159 gridLayout
.marginHeight
= 0;
160 gridLayout
.marginWidth
= 0;
161 gridLayout
.horizontalSpacing
= 5;
162 gridLayout
.verticalSpacing
= 0;
163 gridLayout
.makeColumnsEqualWidth
= true;
164 gridLayout
.marginLeft
= 5;
165 gridLayout
.marginRight
= 5;
166 controlsComposite
.setLayout(gridLayout
);
168 // Current event time control
169 gridData
= new GridData();
170 gridData
.horizontalAlignment
= SWT
.CENTER
;
171 gridData
.verticalAlignment
= SWT
.CENTER
;
172 fCurrentEventTimeControl
= new HistogramCurrentTimeControl(this, controlsComposite
, SWT
.BORDER
, SWT
.NONE
,
173 currentEventLabel
, HistogramUtils
.nanosecondsToString(0L));
174 fCurrentEventTimeControl
.setLayoutData(gridData
);
176 // Window span time control
177 gridData
= new GridData();
178 gridData
.horizontalAlignment
= SWT
.CENTER
;
179 gridData
.verticalAlignment
= SWT
.CENTER
;
180 fTimeSpanControl
= new HistogramTimeRangeControl(this, controlsComposite
, SWT
.BORDER
, SWT
.NONE
,
181 windowSpanLabel
, HistogramUtils
.nanosecondsToString(0L));
182 fTimeSpanControl
.setLayoutData(gridData
);
184 // --------------------------------------------------------------------
185 // Time range histogram
186 // --------------------------------------------------------------------
188 Composite timeRangeComposite
= new Composite(viewComposite
, SWT
.FILL
);
189 gridLayout
= new GridLayout();
190 gridLayout
.numColumns
= 1;
191 gridLayout
.marginHeight
= 0;
192 gridLayout
.marginWidth
= 0;
193 gridLayout
.marginTop
= 5;
194 gridLayout
.horizontalSpacing
= 0;
195 gridLayout
.verticalSpacing
= 0;
196 gridLayout
.marginLeft
= 5;
197 gridLayout
.marginRight
= 5;
198 timeRangeComposite
.setLayout(gridLayout
);
200 // Use remaining horizontal space
201 gridData
= new GridData();
202 gridData
.horizontalAlignment
= SWT
.FILL
;
203 gridData
.verticalAlignment
= SWT
.FILL
;
204 gridData
.grabExcessHorizontalSpace
= true;
205 timeRangeComposite
.setLayoutData(gridData
);
208 fTimeRangeHistogram
= new TimeRangeHistogram(this, timeRangeComposite
);
210 // --------------------------------------------------------------------
211 // Full range histogram
212 // --------------------------------------------------------------------
214 Composite fullRangeComposite
= new Composite(viewComposite
, SWT
.FILL
);
215 gridLayout
= new GridLayout();
216 gridLayout
.numColumns
= 1;
217 gridLayout
.marginHeight
= 0;
218 gridLayout
.marginWidth
= 0;
219 gridLayout
.marginTop
= 5;
220 gridLayout
.horizontalSpacing
= 0;
221 gridLayout
.verticalSpacing
= 0;
222 gridLayout
.marginLeft
= 5;
223 gridLayout
.marginRight
= 5;
224 fullRangeComposite
.setLayout(gridLayout
);
226 // Use remaining horizontal space
227 gridData
= new GridData();
228 gridData
.horizontalAlignment
= SWT
.FILL
;
229 gridData
.verticalAlignment
= SWT
.FILL
;
230 gridData
.horizontalSpan
= 2;
231 gridData
.grabExcessHorizontalSpace
= true;
232 fullRangeComposite
.setLayoutData(gridData
);
235 fFullTraceHistogram
= new FullTraceHistogram(this, fullRangeComposite
);
237 // Load the experiment if present
238 fCurrentExperiment
= (TmfExperiment
<ITmfEvent
>) TmfExperiment
.getCurrentExperiment();
239 if (fCurrentExperiment
!= null)
244 @SuppressWarnings("unchecked")
245 public void setFocus() {
246 TmfExperiment
<ITmfEvent
> experiment
= (TmfExperiment
<ITmfEvent
>) TmfExperiment
.getCurrentExperiment();
247 if ((experiment
!= null) && (experiment
!= fCurrentExperiment
)) {
248 fCurrentExperiment
= experiment
;
249 initializeHistograms();
254 // ------------------------------------------------------------------------
256 // ------------------------------------------------------------------------
258 public TmfTimeRange
getTimeRange() {
259 return new TmfTimeRange(new TmfTimestamp(fWindowStartTime
, TIME_SCALE
), new TmfTimestamp(fWindowEndTime
,
263 // ------------------------------------------------------------------------
265 // ------------------------------------------------------------------------
267 public void updateCurrentEventTime(long newTime
) {
268 if (fCurrentExperiment
!= null) {
269 TmfTimeRange timeRange
= new TmfTimeRange(new TmfTimestamp(newTime
, TIME_SCALE
), TmfTimestamp
.BigCrunch
);
270 HistogramRequest request
= new HistogramRequest(fTimeRangeHistogram
.getDataModel(), timeRange
, 0, 1, ExecutionType
.FOREGROUND
) {
272 public void handleData(ITmfEvent event
) {
274 TmfTimeSynchSignal signal
= new TmfTimeSynchSignal(this, event
.getTimestamp());
275 TmfSignalManager
.dispatchSignal(signal
);
279 fCurrentExperiment
.sendRequest(request
);
283 public void updateTimeRange(long startTime
, long endTime
) {
284 if (fCurrentExperiment
!= null) {
285 // Build the new time range; keep the current time
286 TmfTimeRange timeRange
= new TmfTimeRange(new TmfTimestamp(startTime
, TIME_SCALE
), new TmfTimestamp(
287 endTime
, TIME_SCALE
));
288 TmfTimestamp currentTime
= new TmfTimestamp(fCurrentTimestamp
, TIME_SCALE
);
290 fTimeSpanControl
.setValue(endTime
- startTime
);
292 // Send the FW signal
293 TmfRangeSynchSignal signal
= new TmfRangeSynchSignal(this, timeRange
, currentTime
);
294 TmfSignalManager
.dispatchSignal(signal
);
298 public synchronized void updateTimeRange(long newDuration
) {
299 if (fCurrentExperiment
!= null) {
300 long delta
= newDuration
- fWindowSpan
;
301 long newStartTime
= fWindowStartTime
+ delta
/ 2;
302 setNewRange(newStartTime
, newDuration
);
306 private void setNewRange(long startTime
, long duration
) {
307 if (startTime
< fExperimentStartTime
)
308 startTime
= fExperimentStartTime
;
310 long endTime
= startTime
+ duration
;
311 if (endTime
> fExperimentEndTime
) {
312 endTime
= fExperimentEndTime
;
313 if (endTime
- duration
> fExperimentStartTime
)
314 startTime
= endTime
- duration
;
316 startTime
= fExperimentStartTime
;
319 updateTimeRange(startTime
, endTime
);
322 // ------------------------------------------------------------------------
324 // ------------------------------------------------------------------------
327 @SuppressWarnings("unchecked")
328 public void experimentSelected(TmfExperimentSelectedSignal
<ITmfEvent
> signal
) {
329 assert (signal
!= null);
330 fCurrentExperiment
= (TmfExperiment
<ITmfEvent
>) signal
.getExperiment();
334 private void loadExperiment() {
335 initializeHistograms();
340 public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal
) {
342 if (signal
.getExperiment() != fCurrentExperiment
) {
346 boolean drawTimeRangeHistogram
= fExperimentStartTime
== 0;
347 TmfTimeRange fullRange
= signal
.getRange();
349 fExperimentStartTime
= fullRange
.getStartTime().getValue();
350 fExperimentEndTime
= fullRange
.getEndTime().getValue();
352 fFullTraceHistogram
.setFullRange(fExperimentStartTime
, fExperimentEndTime
);
353 fTimeRangeHistogram
.setFullRange(fExperimentStartTime
, fExperimentEndTime
);
355 if (drawTimeRangeHistogram
) {
356 fCurrentTimestamp
= fExperimentStartTime
;
357 fCurrentEventTimeControl
.setValue(fCurrentTimestamp
);
358 fFullTraceHistogram
.setTimeRange(fExperimentStartTime
, INITIAL_WINDOW_SPAN
);
359 fTimeRangeHistogram
.setTimeRange(fExperimentStartTime
, INITIAL_WINDOW_SPAN
);
360 sendTimeRangeRequest(fExperimentStartTime
, fExperimentStartTime
+ INITIAL_WINDOW_SPAN
);
363 sendFullRangeRequest(fullRange
);
367 public void currentTimeUpdated(TmfTimeSynchSignal signal
) {
368 // Because this can't happen :-)
369 assert (signal
!= null);
371 // Update the selected event time
372 ITmfTimestamp currentTime
= signal
.getCurrentTime();
373 fCurrentTimestamp
= currentTime
.getValue();
375 // Notify the relevant widgets
376 fFullTraceHistogram
.setCurrentEvent(fCurrentTimestamp
);
377 fTimeRangeHistogram
.setCurrentEvent(fCurrentTimestamp
);
378 fCurrentEventTimeControl
.setValue(fCurrentTimestamp
);
382 public void timeRangeUpdated(TmfRangeSynchSignal signal
) {
383 // Because this can't happen :-)
384 assert (signal
!= null);
386 if (fCurrentExperiment
!= null) {
387 // Update the time range
388 fWindowStartTime
= signal
.getCurrentRange().getStartTime().getValue();
389 fWindowEndTime
= signal
.getCurrentRange().getEndTime().getValue();
390 fWindowSpan
= fWindowEndTime
- fWindowStartTime
;
392 // Notify the relevant widgets
393 sendTimeRangeRequest(fWindowStartTime
, fWindowEndTime
);
394 fFullTraceHistogram
.setTimeRange(fWindowStartTime
, fWindowSpan
);
395 fTimeSpanControl
.setValue(fWindowSpan
);
399 // ------------------------------------------------------------------------
401 // ------------------------------------------------------------------------
403 private void initializeHistograms() {
404 TmfTimeRange fullRange
= updateExperimentTimeRange(fCurrentExperiment
);
406 fTimeRangeHistogram
.clear();
407 fTimeRangeHistogram
.setFullRange(fExperimentStartTime
, fExperimentEndTime
);
408 fTimeRangeHistogram
.setTimeRange(fExperimentStartTime
, INITIAL_WINDOW_SPAN
);
409 fTimeRangeHistogram
.setCurrentEvent(fExperimentStartTime
);
411 fFullTraceHistogram
.clear();
412 fFullTraceHistogram
.setFullRange(fExperimentStartTime
, fExperimentEndTime
);
413 fFullTraceHistogram
.setTimeRange(fExperimentStartTime
, INITIAL_WINDOW_SPAN
);
414 fFullTraceHistogram
.setCurrentEvent(fExperimentStartTime
);
416 fWindowStartTime
= fExperimentStartTime
;
417 fWindowSpan
= INITIAL_WINDOW_SPAN
;
418 fWindowEndTime
= fWindowStartTime
+ fWindowSpan
;
420 fCurrentEventTimeControl
.setValue(fExperimentStartTime
);
421 fTimeSpanControl
.setValue(fWindowSpan
);
423 sendTimeRangeRequest(fExperimentStartTime
, fExperimentStartTime
+ fWindowSpan
);
424 sendFullRangeRequest(fullRange
);
427 private TmfTimeRange
updateExperimentTimeRange(TmfExperiment
<ITmfEvent
> experiment
) {
428 fExperimentStartTime
= 0;
429 fExperimentEndTime
= 0;
430 fCurrentTimestamp
= 0;
432 TmfTimeRange timeRange
= fCurrentExperiment
.getTimeRange();
433 if (timeRange
!= TmfTimeRange
.Null
) {
434 fExperimentStartTime
= timeRange
.getStartTime().getValue();
435 fExperimentEndTime
= timeRange
.getEndTime().getValue();
436 fCurrentTimestamp
= fExperimentStartTime
;
441 private void sendTimeRangeRequest(long startTime
, long endTime
) {
442 if (fTimeRangeRequest
!= null && !fTimeRangeRequest
.isCompleted()) {
443 fTimeRangeRequest
.cancel();
445 TmfTimestamp startTS
= new TmfTimestamp(startTime
, TIME_SCALE
);
446 TmfTimestamp endTS
= new TmfTimestamp(endTime
, TIME_SCALE
);
447 TmfTimeRange timeRange
= new TmfTimeRange(startTS
, endTS
);
449 fTimeRangeHistogram
.clear();
450 fTimeRangeHistogram
.setTimeRange(startTime
, endTime
- startTime
);
451 fTimeRangeRequest
= new HistogramRequest(fTimeRangeHistogram
.getDataModel(), timeRange
, ExecutionType
.FOREGROUND
);
452 fCurrentExperiment
.sendRequest(fTimeRangeRequest
);
455 private void sendFullRangeRequest(TmfTimeRange fullRange
) {
456 if (fFullTraceRequest
!= null && !fFullTraceRequest
.isCompleted()) {
457 fFullTraceRequest
.cancel();
459 fFullTraceRequest
= new HistogramRequest(fFullTraceHistogram
.getDataModel(), fullRange
, (int) fFullTraceHistogram
.fDataModel
.getNbEvents(),
460 ExecutionType
.BACKGROUND
);
461 fCurrentExperiment
.sendRequest(fFullTraceRequest
);