Merge "tmf: Close the state history files before deleting them"
[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.TmfExperimentRangeUpdatedSignal;
27 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal;
28 import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentUpdatedSignal;
29 import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
30 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
31 import org.eclipse.linuxtools.tmf.core.signal.TmfSignalManager;
32 import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
33 import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
34 import org.eclipse.linuxtools.tmf.ui.views.TmfView;
35 import org.eclipse.swt.SWT;
36 import org.eclipse.swt.layout.GridData;
37 import org.eclipse.swt.layout.GridLayout;
38 import org.eclipse.swt.widgets.Composite;
39
40 /**
41 * The purpose of this view is to provide graphical time distribution statistics about the experiment/trace events.
42 * <p>
43 * The view is composed of two histograms and two controls:
44 * <ul>
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).
49 * </ul>
50 * The histograms x-axis show their respective time range.
51 *
52 * @version 1.0
53 * @author Francois Chouinard
54 */
55 public class HistogramView extends TmfView {
56
57 // ------------------------------------------------------------------------
58 // Constants
59 // ------------------------------------------------------------------------
60
61 /**
62 * The view ID as defined in plugin.xml
63 */
64 public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.histogram"; //$NON-NLS-1$
65
66 /**
67 * The initial window span (in nanoseconds)
68 */
69 public static final long INITIAL_WINDOW_SPAN = (1L * 100 * 1000 * 1000); // .1sec
70
71 // Time scale
72 private final byte TIME_SCALE = Histogram.TIME_SCALE;
73
74 // ------------------------------------------------------------------------
75 // Attributes
76 // ------------------------------------------------------------------------
77
78 // Parent widget
79 private Composite fParent;
80
81 // The current experiment
82 private TmfExperiment<ITmfEvent> fCurrentExperiment;
83
84 // Current timestamp/time window
85 private long fExperimentStartTime;
86 private long fExperimentEndTime;
87 private long fWindowStartTime;
88 private long fWindowEndTime;
89 private long fWindowSpan = INITIAL_WINDOW_SPAN;
90 private long fCurrentTimestamp;
91
92 // Time controls
93 private HistogramTextControl fCurrentEventTimeControl;
94 private HistogramTextControl fTimeSpanControl;
95
96 // Histogram/request for the full trace range
97 private static FullTraceHistogram fFullTraceHistogram;
98 private HistogramRequest fFullTraceRequest;
99
100 // Histogram/request for the selected time range
101 private static TimeRangeHistogram fTimeRangeHistogram;
102 private HistogramRequest fTimeRangeRequest;
103
104 // ------------------------------------------------------------------------
105 // Constructor
106 // ------------------------------------------------------------------------
107
108 /**
109 * Default constructor
110 */
111 public HistogramView() {
112 super(ID);
113 }
114
115 @Override
116 public void dispose() {
117 if ((fTimeRangeRequest != null) && !fTimeRangeRequest.isCompleted()) {
118 fTimeRangeRequest.cancel();
119 }
120 if ((fFullTraceRequest != null) && !fFullTraceRequest.isCompleted()) {
121 fFullTraceRequest.cancel();
122 }
123 fFullTraceHistogram.dispose();
124 fTimeRangeHistogram.dispose();
125 super.dispose();
126 }
127
128 // ------------------------------------------------------------------------
129 // TmfView
130 // ------------------------------------------------------------------------
131
132 @Override
133 @SuppressWarnings("unchecked")
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<ITmfEvent>) TmfExperiment.getCurrentExperiment();
249 if (fCurrentExperiment != null) {
250 loadExperiment();
251 }
252 }
253
254 @Override
255 @SuppressWarnings("unchecked")
256 public void setFocus() {
257 TmfExperiment<ITmfEvent> experiment = (TmfExperiment<ITmfEvent>) TmfExperiment.getCurrentExperiment();
258 if ((experiment != null) && (experiment != fCurrentExperiment)) {
259 fCurrentExperiment = experiment;
260 initializeHistograms();
261 }
262 fParent.redraw();
263 }
264
265 // ------------------------------------------------------------------------
266 // Accessors
267 // ------------------------------------------------------------------------
268
269 /**
270 * Returns the time range of the current selected window (base on default time scale).
271 *
272 * @return the time range of current selected window.
273 */
274 public TmfTimeRange getTimeRange() {
275 return new TmfTimeRange(new TmfTimestamp(fWindowStartTime, TIME_SCALE), new TmfTimestamp(fWindowEndTime,
276 TIME_SCALE));
277 }
278
279 // ------------------------------------------------------------------------
280 // Operations
281 // ------------------------------------------------------------------------
282
283 /**
284 * Broadcast TmfSignal about new current time value.
285 * @param newTime the new current time.
286 */
287 public void updateCurrentEventTime(long newTime) {
288 if (fCurrentExperiment != null) {
289 TmfTimeRange timeRange = new TmfTimeRange(new TmfTimestamp(newTime, TIME_SCALE), TmfTimestamp.BIG_CRUNCH);
290 HistogramRequest request = new HistogramRequest(fTimeRangeHistogram.getDataModel(), timeRange, 0, 1, 0, ExecutionType.FOREGROUND) {
291 @Override
292 public void handleData(ITmfEvent event) {
293 if (event != null) {
294 TmfTimeSynchSignal signal = new TmfTimeSynchSignal(this, event.getTimestamp());
295 TmfSignalManager.dispatchSignal(signal);
296 }
297 }
298 };
299 fCurrentExperiment.sendRequest(request);
300 }
301 }
302
303 /**
304 * Broadcast TmfSignal about new selected time range.
305 * @param startTime the new start time
306 * @param endTime the new end time
307 */
308 public void updateTimeRange(long startTime, long endTime) {
309 if (fCurrentExperiment != null) {
310 // Build the new time range; keep the current time
311 TmfTimeRange timeRange = new TmfTimeRange(new TmfTimestamp(startTime, TIME_SCALE), new TmfTimestamp(
312 endTime, TIME_SCALE));
313 TmfTimestamp currentTime = new TmfTimestamp(fCurrentTimestamp, TIME_SCALE);
314
315 fTimeSpanControl.setValue(endTime - startTime);
316
317 // Send the FW signal
318 TmfRangeSynchSignal signal = new TmfRangeSynchSignal(this, timeRange, currentTime);
319 TmfSignalManager.dispatchSignal(signal);
320 }
321 }
322
323 /**
324 * Broadcast TmfSignal about new selected time range.
325 * @param newDuration new duration (relative to current start time)
326 */
327 public synchronized void updateTimeRange(long newDuration) {
328 if (fCurrentExperiment != null) {
329 long delta = newDuration - fWindowSpan;
330 long newStartTime = fWindowStartTime + (delta / 2);
331 setNewRange(newStartTime, newDuration);
332 }
333 }
334
335 private void setNewRange(long startTime, long duration) {
336 if (startTime < fExperimentStartTime) {
337 startTime = fExperimentStartTime;
338 }
339
340 long endTime = startTime + duration;
341 if( endTime < startTime ) {
342 endTime = fExperimentEndTime;
343 startTime = fExperimentStartTime;
344 }
345 if (endTime > fExperimentEndTime) {
346 endTime = fExperimentEndTime;
347 if ((endTime - duration) > fExperimentStartTime) {
348 startTime = endTime - duration;
349 } else {
350 startTime = fExperimentStartTime;
351 }
352 }
353 updateTimeRange(startTime, endTime);
354 }
355
356 // ------------------------------------------------------------------------
357 // Signal handlers
358 // ------------------------------------------------------------------------
359
360 /**
361 * Handles experiment selected signal. Loads histogram if new experiment time range is not
362 * equal <code>TmfTimeRange.NULL_RANGE</code>
363 * @param signal the experiment selected signal
364 */
365 @TmfSignalHandler
366 @SuppressWarnings("unchecked")
367 public void experimentSelected(TmfExperimentSelectedSignal<ITmfEvent> signal) {
368 assert (signal != null);
369 fCurrentExperiment = (TmfExperiment<ITmfEvent>) signal.getExperiment();
370 loadExperiment();
371 }
372
373 private void loadExperiment() {
374 initializeHistograms();
375 fParent.redraw();
376 }
377
378 /**
379 * Handles experiment range updated signal. Extends histogram according to the new time range. If a
380 * HistogramRequest is already ongoing, it will be cancelled and a new request with the new range
381 * will be issued.
382 *
383 * @param signal the experiment range updated signal
384 */
385 @TmfSignalHandler
386 public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal) {
387
388 if (signal.getExperiment() != fCurrentExperiment) {
389 return;
390 }
391
392 boolean drawTimeRangeHistogram = fExperimentStartTime == 0;
393 TmfTimeRange fullRange = signal.getRange();
394
395 fExperimentStartTime = fullRange.getStartTime().normalize(0, -9).getValue();
396 fExperimentEndTime = fullRange.getEndTime().normalize(0, -9).getValue();
397
398 fFullTraceHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime);
399 fTimeRangeHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime);
400
401 if (drawTimeRangeHistogram) {
402 fCurrentTimestamp = fExperimentStartTime;
403 fCurrentEventTimeControl.setValue(fCurrentTimestamp);
404 fFullTraceHistogram.setTimeRange(fExperimentStartTime, INITIAL_WINDOW_SPAN);
405 fTimeRangeHistogram.setTimeRange(fExperimentStartTime, INITIAL_WINDOW_SPAN);
406 sendTimeRangeRequest(fExperimentStartTime, fExperimentStartTime + INITIAL_WINDOW_SPAN);
407 }
408
409 sendFullRangeRequest(fullRange);
410 }
411
412 /**
413 * Handles the experiment updated signal. Used to update time limits (start and end time)
414 * @param signal the experiment updated signal
415 */
416 @TmfSignalHandler
417 public void experimentUpdated(TmfExperimentUpdatedSignal signal) {
418 if (signal.getExperiment() != fCurrentExperiment) {
419 return;
420 }
421 TmfTimeRange fullRange = signal.getExperiment().getTimeRange();
422 fExperimentStartTime = fullRange.getStartTime().normalize(0, -9).getValue();
423 fExperimentEndTime = fullRange.getEndTime().normalize(0, -9).getValue();
424
425 fFullTraceHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime);
426 fTimeRangeHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime);
427 }
428
429 /**
430 * Handles the current time updated signal. Sets the current time in the time range
431 * histogram as well as the full histogram.
432 *
433 * @param signal the signal to process
434 */
435 @TmfSignalHandler
436 public void currentTimeUpdated(TmfTimeSynchSignal signal) {
437 // Because this can't happen :-)
438 assert (signal != null);
439
440 // Update the selected event time
441 ITmfTimestamp currentTime = signal.getCurrentTime();
442 fCurrentTimestamp = currentTime.normalize(0, -9).getValue();
443
444 // Notify the relevant widgets
445 fFullTraceHistogram.setCurrentEvent(fCurrentTimestamp);
446 fTimeRangeHistogram.setCurrentEvent(fCurrentTimestamp);
447 fCurrentEventTimeControl.setValue(fCurrentTimestamp);
448 }
449
450 /**
451 * Updates the current time range in the time range histogram and full range histogram.
452 * @param signal the signal to process
453 */
454 @TmfSignalHandler
455 public void timeRangeUpdated(TmfRangeSynchSignal signal) {
456 // Because this can't happen :-)
457 assert (signal != null);
458
459 if (fCurrentExperiment != null) {
460 // Update the time range
461 fWindowStartTime = signal.getCurrentRange().getStartTime().normalize(0, -9).getValue();
462 fWindowEndTime = signal.getCurrentRange().getEndTime().normalize(0, -9).getValue();
463 fWindowSpan = fWindowEndTime - fWindowStartTime;
464
465 // Notify the relevant widgets
466 sendTimeRangeRequest(fWindowStartTime, fWindowEndTime);
467 fFullTraceHistogram.setTimeRange(fWindowStartTime, fWindowSpan);
468 fTimeSpanControl.setValue(fWindowSpan);
469 }
470 }
471
472 // ------------------------------------------------------------------------
473 // Helper functions
474 // ------------------------------------------------------------------------
475
476 private void initializeHistograms() {
477 TmfTimeRange fullRange = updateExperimentTimeRange(fCurrentExperiment);
478
479 fTimeRangeHistogram.clear();
480 fTimeRangeHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime);
481 fTimeRangeHistogram.setTimeRange(fExperimentStartTime, INITIAL_WINDOW_SPAN);
482 fTimeRangeHistogram.setCurrentEvent(fExperimentStartTime);
483
484 fFullTraceHistogram.clear();
485 fFullTraceHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime);
486 fFullTraceHistogram.setTimeRange(fExperimentStartTime, INITIAL_WINDOW_SPAN);
487 fFullTraceHistogram.setCurrentEvent(fExperimentStartTime);
488
489 fWindowStartTime = fExperimentStartTime;
490 fWindowSpan = INITIAL_WINDOW_SPAN;
491 fWindowEndTime = fWindowStartTime + fWindowSpan;
492
493 fCurrentEventTimeControl.setValue(fExperimentStartTime);
494 fTimeSpanControl.setValue(fWindowSpan);
495
496 if (!fullRange.equals(TmfTimeRange.NULL_RANGE)) {
497 sendTimeRangeRequest(fExperimentStartTime, fExperimentStartTime + fWindowSpan);
498 sendFullRangeRequest(fullRange);
499 }
500 }
501
502 private TmfTimeRange updateExperimentTimeRange(TmfExperiment<ITmfEvent> experiment) {
503 fExperimentStartTime = 0;
504 fExperimentEndTime = 0;
505 fCurrentTimestamp = 0;
506
507 TmfTimeRange timeRange = fCurrentExperiment.getTimeRange();
508 if (!timeRange.equals(TmfTimeRange.NULL_RANGE)) {
509 fExperimentStartTime = timeRange.getStartTime().normalize(0, -9).getValue();
510 fExperimentEndTime = timeRange.getEndTime().normalize(0, -9).getValue();
511 fCurrentTimestamp = fExperimentStartTime;
512 }
513 return timeRange;
514 }
515
516 private void sendTimeRangeRequest(long startTime, long endTime) {
517 if ((fTimeRangeRequest != null) && !fTimeRangeRequest.isCompleted()) {
518 fTimeRangeRequest.cancel();
519 }
520 TmfTimestamp startTS = new TmfTimestamp(startTime, TIME_SCALE);
521 TmfTimestamp endTS = new TmfTimestamp(endTime, TIME_SCALE);
522 TmfTimeRange timeRange = new TmfTimeRange(startTS, endTS);
523
524 fTimeRangeHistogram.clear();
525 fTimeRangeHistogram.setTimeRange(startTime, endTime - startTime);
526
527 int cacheSize = fCurrentExperiment.getCacheSize();
528 fTimeRangeRequest = new HistogramRequest(fTimeRangeHistogram.getDataModel(), timeRange, 0, TmfDataRequest.ALL_DATA, cacheSize, ExecutionType.FOREGROUND);
529 fCurrentExperiment.sendRequest(fTimeRangeRequest);
530 }
531
532 private void sendFullRangeRequest(TmfTimeRange fullRange) {
533 if ((fFullTraceRequest != null) && !fFullTraceRequest.isCompleted()) {
534 fFullTraceRequest.cancel();
535 }
536 int cacheSize = fCurrentExperiment.getCacheSize();
537 fFullTraceRequest = new HistogramRequest(fFullTraceHistogram.getDataModel(), fullRange, (int) fFullTraceHistogram.fDataModel.getNbEvents(),
538 TmfDataRequest.ALL_DATA, cacheSize, ExecutionType.BACKGROUND);
539 fCurrentExperiment.sendRequest(fFullTraceRequest);
540 }
541
542 }
This page took 0.043001 seconds and 6 git commands to generate.