Add a "Clear Tracing Views" command
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / views / histogram / HistogramView.java
1 /*******************************************************************************
2 * Copyright (c) 2009, 2010, 2011, 2012 Ericsson
3 *
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
8 *
9 * Contributors:
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 *******************************************************************************/
17
18 package org.eclipse.linuxtools.tmf.ui.views.histogram;
19
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.request.ITmfDataRequest.ExecutionType;
25 import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest;
26 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentDisposedSignal;
27 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentRangeUpdatedSignal;
28 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal;
29 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentUpdatedSignal;
30 import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
31 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
32 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
33 import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
34 import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
35 import org.eclipse.linuxtools.tmf.ui.views.TmfView;
36 import org.eclipse.swt.SWT;
37 import org.eclipse.swt.layout.GridData;
38 import org.eclipse.swt.layout.GridLayout;
39 import org.eclipse.swt.widgets.Composite;
40
41 /**
42 * The purpose of this view is to provide graphical time distribution statistics about the experiment/trace events.
43 * <p>
44 * The view is composed of two histograms and two controls:
45 * <ul>
46 * <li>an event distribution histogram for the whole experiment;
47 * <li>an event distribution histogram for current time window (window span);
48 * <li>the timestamp of the currently selected event;
49 * <li>the window span (size of the time window of the smaller histogram).
50 * </ul>
51 * The histograms x-axis show their respective time range.
52 *
53 * @version 1.0
54 * @author Francois Chouinard
55 */
56 public class HistogramView extends TmfView {
57
58 // ------------------------------------------------------------------------
59 // Constants
60 // ------------------------------------------------------------------------
61
62 /**
63 * The view ID as defined in plugin.xml
64 */
65 public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.histogram"; //$NON-NLS-1$
66
67 /**
68 * The initial window span (in nanoseconds)
69 */
70 public static final long INITIAL_WINDOW_SPAN = (1L * 100 * 1000 * 1000); // .1sec
71
72 // Time scale
73 private final byte TIME_SCALE = Histogram.TIME_SCALE;
74
75 // ------------------------------------------------------------------------
76 // Attributes
77 // ------------------------------------------------------------------------
78
79 // Parent widget
80 private Composite fParent;
81
82 // The current experiment
83 private TmfExperiment fCurrentExperiment;
84
85 // Current timestamp/time window
86 private long fExperimentStartTime;
87 private long fExperimentEndTime;
88 private long fWindowStartTime;
89 private long fWindowEndTime;
90 private long fWindowSpan = INITIAL_WINDOW_SPAN;
91 private long fCurrentTimestamp;
92
93 // Time controls
94 private HistogramTextControl fCurrentEventTimeControl;
95 private HistogramTextControl fTimeSpanControl;
96
97 // Histogram/request for the full trace range
98 private static FullTraceHistogram fFullTraceHistogram;
99 private HistogramRequest fFullTraceRequest;
100
101 // Histogram/request for the selected time range
102 private static TimeRangeHistogram fTimeRangeHistogram;
103 private HistogramRequest fTimeRangeRequest;
104
105 // ------------------------------------------------------------------------
106 // Constructor
107 // ------------------------------------------------------------------------
108
109 /**
110 * Default constructor
111 */
112 public HistogramView() {
113 super(ID);
114 }
115
116 @Override
117 public void dispose() {
118 if ((fTimeRangeRequest != null) && !fTimeRangeRequest.isCompleted()) {
119 fTimeRangeRequest.cancel();
120 }
121 if ((fFullTraceRequest != null) && !fFullTraceRequest.isCompleted()) {
122 fFullTraceRequest.cancel();
123 }
124 fFullTraceHistogram.dispose();
125 fTimeRangeHistogram.dispose();
126 super.dispose();
127 }
128
129 // ------------------------------------------------------------------------
130 // TmfView
131 // ------------------------------------------------------------------------
132
133 @Override
134 public void createPartControl(Composite parent) {
135
136 fParent = parent;
137
138 // Control labels
139 final String currentEventLabel = Messages.HistogramView_currentEventLabel;
140 final String windowSpanLabel = Messages.HistogramView_windowSpanLabel;
141
142 // --------------------------------------------------------------------
143 // Set the HistogramView layout
144 // --------------------------------------------------------------------
145
146 Composite viewComposite = new Composite(fParent, SWT.FILL);
147 GridLayout gridLayout = new GridLayout();
148 gridLayout.numColumns = 2;
149 gridLayout.horizontalSpacing = 5;
150 gridLayout.verticalSpacing = 0;
151 gridLayout.marginHeight = 0;
152 gridLayout.marginWidth = 0;
153 viewComposite.setLayout(gridLayout);
154
155 // Use all available space
156 GridData gridData = new GridData();
157 gridData.horizontalAlignment = SWT.FILL;
158 gridData.verticalAlignment = SWT.FILL;
159 gridData.grabExcessHorizontalSpace = true;
160 viewComposite.setLayoutData(gridData);
161
162 // --------------------------------------------------------------------
163 // Time controls
164 // --------------------------------------------------------------------
165
166 Composite controlsComposite = new Composite(viewComposite, SWT.FILL);
167 gridLayout = new GridLayout();
168 gridLayout.numColumns = 2;
169 gridLayout.marginHeight = 0;
170 gridLayout.marginWidth = 0;
171 gridLayout.horizontalSpacing = 5;
172 gridLayout.verticalSpacing = 0;
173 gridLayout.makeColumnsEqualWidth = true;
174 gridLayout.marginLeft = 5;
175 gridLayout.marginRight = 5;
176 controlsComposite.setLayout(gridLayout);
177
178 // Current event time control
179 gridData = new GridData();
180 gridData.horizontalAlignment = SWT.CENTER;
181 gridData.verticalAlignment = SWT.CENTER;
182 fCurrentEventTimeControl = new HistogramCurrentTimeControl(this, controlsComposite, SWT.BORDER, SWT.NONE,
183 currentEventLabel, HistogramUtils.nanosecondsToString(0L));
184 fCurrentEventTimeControl.setLayoutData(gridData);
185
186 // Window span time control
187 gridData = new GridData();
188 gridData.horizontalAlignment = SWT.CENTER;
189 gridData.verticalAlignment = SWT.CENTER;
190 fTimeSpanControl = new HistogramTimeRangeControl(this, controlsComposite, SWT.BORDER, SWT.NONE,
191 windowSpanLabel, HistogramUtils.nanosecondsToString(0L));
192 fTimeSpanControl.setLayoutData(gridData);
193
194 // --------------------------------------------------------------------
195 // Time range histogram
196 // --------------------------------------------------------------------
197
198 Composite timeRangeComposite = new Composite(viewComposite, SWT.FILL);
199 gridLayout = new GridLayout();
200 gridLayout.numColumns = 1;
201 gridLayout.marginHeight = 0;
202 gridLayout.marginWidth = 0;
203 gridLayout.marginTop = 5;
204 gridLayout.horizontalSpacing = 0;
205 gridLayout.verticalSpacing = 0;
206 gridLayout.marginLeft = 5;
207 gridLayout.marginRight = 5;
208 timeRangeComposite.setLayout(gridLayout);
209
210 // Use remaining horizontal space
211 gridData = new GridData();
212 gridData.horizontalAlignment = SWT.FILL;
213 gridData.verticalAlignment = SWT.FILL;
214 gridData.grabExcessHorizontalSpace = true;
215 timeRangeComposite.setLayoutData(gridData);
216
217 // Histogram
218 fTimeRangeHistogram = new TimeRangeHistogram(this, timeRangeComposite);
219
220 // --------------------------------------------------------------------
221 // Full range histogram
222 // --------------------------------------------------------------------
223
224 Composite fullRangeComposite = new Composite(viewComposite, SWT.FILL);
225 gridLayout = new GridLayout();
226 gridLayout.numColumns = 1;
227 gridLayout.marginHeight = 0;
228 gridLayout.marginWidth = 0;
229 gridLayout.marginTop = 5;
230 gridLayout.horizontalSpacing = 0;
231 gridLayout.verticalSpacing = 0;
232 gridLayout.marginLeft = 5;
233 gridLayout.marginRight = 5;
234 fullRangeComposite.setLayout(gridLayout);
235
236 // Use remaining horizontal space
237 gridData = new GridData();
238 gridData.horizontalAlignment = SWT.FILL;
239 gridData.verticalAlignment = SWT.FILL;
240 gridData.horizontalSpan = 2;
241 gridData.grabExcessHorizontalSpace = true;
242 fullRangeComposite.setLayoutData(gridData);
243
244 // Histogram
245 fFullTraceHistogram = new FullTraceHistogram(this, fullRangeComposite);
246
247 // Load the experiment if present
248 fCurrentExperiment = TmfExperiment.getCurrentExperiment();
249 if (fCurrentExperiment != null) {
250 loadExperiment();
251 }
252 }
253
254 @Override
255 public void setFocus() {
256 TmfExperiment experiment = TmfExperiment.getCurrentExperiment();
257 if ((experiment != null) && (experiment != fCurrentExperiment)) {
258 fCurrentExperiment = experiment;
259 initializeHistograms();
260 }
261 fParent.redraw();
262 }
263
264 // ------------------------------------------------------------------------
265 // Accessors
266 // ------------------------------------------------------------------------
267
268 /**
269 * Returns the time range of the current selected window (base on default time scale).
270 *
271 * @return the time range of current selected window.
272 */
273 public TmfTimeRange getTimeRange() {
274 return new TmfTimeRange(new TmfTimestamp(fWindowStartTime, TIME_SCALE), new TmfTimestamp(fWindowEndTime,
275 TIME_SCALE));
276 }
277
278 // ------------------------------------------------------------------------
279 // Operations
280 // ------------------------------------------------------------------------
281
282 /**
283 * Broadcast TmfSignal about new current time value.
284 * @param newTime the new current time.
285 */
286 public void updateCurrentEventTime(long newTime) {
287 if (fCurrentExperiment != null) {
288 TmfTimeRange timeRange = new TmfTimeRange(new TmfTimestamp(newTime, TIME_SCALE), TmfTimestamp.BIG_CRUNCH);
289 HistogramRequest request = new HistogramRequest(fTimeRangeHistogram.getDataModel(), timeRange, 0, 1, 0, ExecutionType.FOREGROUND) {
290 @Override
291 public void handleData(ITmfEvent event) {
292 if (event != null) {
293 TmfTimeSynchSignal signal = new TmfTimeSynchSignal(this, event.getTimestamp());
294 TmfSignalManager.dispatchSignal(signal);
295 }
296 }
297 };
298 fCurrentExperiment.sendRequest(request);
299 }
300 }
301
302 /**
303 * Broadcast TmfSignal about new selected time range.
304 * @param startTime the new start time
305 * @param endTime the new end time
306 */
307 public void updateTimeRange(long startTime, long endTime) {
308 if (fCurrentExperiment != null) {
309 // Build the new time range; keep the current time
310 TmfTimeRange timeRange = new TmfTimeRange(new TmfTimestamp(startTime, TIME_SCALE), new TmfTimestamp(
311 endTime, TIME_SCALE));
312 TmfTimestamp currentTime = new TmfTimestamp(fCurrentTimestamp, TIME_SCALE);
313
314 fTimeSpanControl.setValue(endTime - startTime);
315
316 // Send the FW signal
317 TmfRangeSynchSignal signal = new TmfRangeSynchSignal(this, timeRange, currentTime);
318 TmfSignalManager.dispatchSignal(signal);
319 }
320 }
321
322 /**
323 * Broadcast TmfSignal about new selected time range.
324 * @param newDuration new duration (relative to current start time)
325 */
326 public synchronized void updateTimeRange(long newDuration) {
327 if (fCurrentExperiment != null) {
328 long delta = newDuration - fWindowSpan;
329 long newStartTime = fWindowStartTime + (delta / 2);
330 setNewRange(newStartTime, newDuration);
331 }
332 }
333
334 private void setNewRange(long startTime, long duration) {
335 if (startTime < fExperimentStartTime) {
336 startTime = fExperimentStartTime;
337 }
338
339 long endTime = startTime + duration;
340 if( endTime < startTime ) {
341 endTime = fExperimentEndTime;
342 startTime = fExperimentStartTime;
343 }
344 if (endTime > fExperimentEndTime) {
345 endTime = fExperimentEndTime;
346 if ((endTime - duration) > fExperimentStartTime) {
347 startTime = endTime - duration;
348 } else {
349 startTime = fExperimentStartTime;
350 }
351 }
352 updateTimeRange(startTime, endTime);
353 }
354
355 // ------------------------------------------------------------------------
356 // Signal handlers
357 // ------------------------------------------------------------------------
358
359 /**
360 * Handles experiment selected signal. Loads histogram if new experiment time range is not
361 * equal <code>TmfTimeRange.NULL_RANGE</code>
362 * @param signal the experiment selected signal
363 */
364 @TmfSignalHandler
365 public void experimentSelected(TmfExperimentSelectedSignal signal) {
366 assert (signal != null);
367 fCurrentExperiment = signal.getExperiment();
368 loadExperiment();
369 }
370
371 private void loadExperiment() {
372 initializeHistograms();
373 fParent.redraw();
374 }
375
376 /**
377 * @param signal the incoming signal
378 * @since 2.0
379 */
380 @TmfSignalHandler
381 public void experimentDisposed(TmfExperimentDisposedSignal signal) {
382
383 // Kill any running request
384 if ((fTimeRangeRequest != null) && !fTimeRangeRequest.isCompleted()) {
385 fTimeRangeRequest.cancel();
386 }
387 if ((fFullTraceRequest != null) && !fFullTraceRequest.isCompleted()) {
388 fFullTraceRequest.cancel();
389 }
390
391 // Initialize the internal data
392 fCurrentExperiment = null;
393 fExperimentStartTime = 0;
394 fExperimentEndTime = 0;
395 fWindowStartTime = 0;
396 fWindowEndTime = 0;
397 fWindowSpan = INITIAL_WINDOW_SPAN;
398 fCurrentTimestamp = 0;
399
400 // Clear the UI widgets
401 fFullTraceHistogram.clear();
402 fTimeRangeHistogram.clear();
403 fCurrentEventTimeControl.setValue(0);
404 fTimeSpanControl.setValue(0);
405 }
406
407 /**
408 * Handles experiment range updated signal. Extends histogram according to the new time range. If a
409 * HistogramRequest is already ongoing, it will be cancelled and a new request with the new range
410 * will be issued.
411 *
412 * @param signal the experiment range updated signal
413 */
414 @TmfSignalHandler
415 public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal) {
416
417 if (signal.getExperiment() != fCurrentExperiment) {
418 return;
419 }
420
421 boolean drawTimeRangeHistogram = fExperimentStartTime == 0;
422 TmfTimeRange fullRange = signal.getRange();
423
424 fExperimentStartTime = fullRange.getStartTime().normalize(0, -9).getValue();
425 fExperimentEndTime = fullRange.getEndTime().normalize(0, -9).getValue();
426
427 fFullTraceHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime);
428 fTimeRangeHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime);
429
430 if (drawTimeRangeHistogram) {
431 fCurrentTimestamp = fExperimentStartTime;
432 fCurrentEventTimeControl.setValue(fCurrentTimestamp);
433 fFullTraceHistogram.setTimeRange(fExperimentStartTime, INITIAL_WINDOW_SPAN);
434 fTimeRangeHistogram.setTimeRange(fExperimentStartTime, INITIAL_WINDOW_SPAN);
435 sendTimeRangeRequest(fExperimentStartTime, fExperimentStartTime + INITIAL_WINDOW_SPAN);
436 }
437
438 sendFullRangeRequest(fullRange);
439 }
440
441 /**
442 * Handles the experiment updated signal. Used to update time limits (start and end time)
443 * @param signal the experiment updated signal
444 */
445 @TmfSignalHandler
446 public void experimentUpdated(TmfExperimentUpdatedSignal signal) {
447 if (signal.getExperiment() != fCurrentExperiment) {
448 return;
449 }
450 TmfTimeRange fullRange = signal.getExperiment().getTimeRange();
451 fExperimentStartTime = fullRange.getStartTime().normalize(0, -9).getValue();
452 fExperimentEndTime = fullRange.getEndTime().normalize(0, -9).getValue();
453
454 fFullTraceHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime);
455 fTimeRangeHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime);
456 }
457
458 /**
459 * Handles the current time updated signal. Sets the current time in the time range
460 * histogram as well as the full histogram.
461 *
462 * @param signal the signal to process
463 */
464 @TmfSignalHandler
465 public void currentTimeUpdated(TmfTimeSynchSignal signal) {
466 // Because this can't happen :-)
467 assert (signal != null);
468
469 // Update the selected event time
470 ITmfTimestamp currentTime = signal.getCurrentTime();
471 fCurrentTimestamp = currentTime.normalize(0, -9).getValue();
472
473 // Notify the relevant widgets
474 fFullTraceHistogram.setCurrentEvent(fCurrentTimestamp);
475 fTimeRangeHistogram.setCurrentEvent(fCurrentTimestamp);
476 fCurrentEventTimeControl.setValue(fCurrentTimestamp);
477 }
478
479 /**
480 * Updates the current time range in the time range histogram and full range histogram.
481 * @param signal the signal to process
482 */
483 @TmfSignalHandler
484 public void timeRangeUpdated(TmfRangeSynchSignal signal) {
485 // Because this can't happen :-)
486 assert (signal != null);
487
488 if (fCurrentExperiment != null) {
489 // Update the time range
490 fWindowStartTime = signal.getCurrentRange().getStartTime().normalize(0, -9).getValue();
491 fWindowEndTime = signal.getCurrentRange().getEndTime().normalize(0, -9).getValue();
492 fWindowSpan = fWindowEndTime - fWindowStartTime;
493
494 // Notify the relevant widgets
495 sendTimeRangeRequest(fWindowStartTime, fWindowEndTime);
496 fFullTraceHistogram.setTimeRange(fWindowStartTime, fWindowSpan);
497 fTimeSpanControl.setValue(fWindowSpan);
498 }
499 }
500
501 // ------------------------------------------------------------------------
502 // Helper functions
503 // ------------------------------------------------------------------------
504
505 private void initializeHistograms() {
506 TmfTimeRange fullRange = updateExperimentTimeRange();
507
508 fTimeRangeHistogram.clear();
509 fTimeRangeHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime);
510 fTimeRangeHistogram.setTimeRange(fExperimentStartTime, INITIAL_WINDOW_SPAN);
511 fTimeRangeHistogram.setCurrentEvent(fExperimentStartTime);
512
513 fFullTraceHistogram.clear();
514 fFullTraceHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime);
515 fFullTraceHistogram.setTimeRange(fExperimentStartTime, INITIAL_WINDOW_SPAN);
516 fFullTraceHistogram.setCurrentEvent(fExperimentStartTime);
517
518 fWindowStartTime = fExperimentStartTime;
519 fWindowSpan = INITIAL_WINDOW_SPAN;
520 fWindowEndTime = fWindowStartTime + fWindowSpan;
521
522 fCurrentEventTimeControl.setValue(fExperimentStartTime);
523 fTimeSpanControl.setValue(fWindowSpan);
524
525 if (!fullRange.equals(TmfTimeRange.NULL_RANGE)) {
526 sendTimeRangeRequest(fExperimentStartTime, fExperimentStartTime + fWindowSpan);
527 sendFullRangeRequest(fullRange);
528 }
529 }
530
531 private TmfTimeRange updateExperimentTimeRange() {
532 fExperimentStartTime = 0;
533 fExperimentEndTime = 0;
534 fCurrentTimestamp = 0;
535
536 TmfTimeRange timeRange = fCurrentExperiment.getTimeRange();
537 if (!timeRange.equals(TmfTimeRange.NULL_RANGE)) {
538 fExperimentStartTime = timeRange.getStartTime().normalize(0, -9).getValue();
539 fExperimentEndTime = timeRange.getEndTime().normalize(0, -9).getValue();
540 fCurrentTimestamp = fExperimentStartTime;
541 }
542 return timeRange;
543 }
544
545 private void sendTimeRangeRequest(long startTime, long endTime) {
546 if ((fTimeRangeRequest != null) && !fTimeRangeRequest.isCompleted()) {
547 fTimeRangeRequest.cancel();
548 }
549 TmfTimestamp startTS = new TmfTimestamp(startTime, TIME_SCALE);
550 TmfTimestamp endTS = new TmfTimestamp(endTime, TIME_SCALE);
551 TmfTimeRange timeRange = new TmfTimeRange(startTS, endTS);
552
553 fTimeRangeHistogram.clear();
554 fTimeRangeHistogram.setTimeRange(startTime, endTime - startTime);
555
556 int cacheSize = fCurrentExperiment.getCacheSize();
557 fTimeRangeRequest = new HistogramRequest(fTimeRangeHistogram.getDataModel(), timeRange, 0, TmfDataRequest.ALL_DATA, cacheSize, ExecutionType.FOREGROUND);
558 fCurrentExperiment.sendRequest(fTimeRangeRequest);
559 }
560
561 private void sendFullRangeRequest(TmfTimeRange fullRange) {
562 if ((fFullTraceRequest != null) && !fFullTraceRequest.isCompleted()) {
563 fFullTraceRequest.cancel();
564 }
565 int cacheSize = fCurrentExperiment.getCacheSize();
566 fFullTraceRequest = new HistogramRequest(fFullTraceHistogram.getDataModel(), fullRange, (int) fFullTraceHistogram.fDataModel.getNbEvents(),
567 TmfDataRequest.ALL_DATA, cacheSize, ExecutionType.BACKGROUND);
568 fCurrentExperiment.sendRequest(fFullTraceRequest);
569 }
570
571 }
This page took 0.043322 seconds and 5 git commands to generate.