Commit | Line | Data |
---|---|---|
6e512b93 | 1 | /******************************************************************************* |
c392540b | 2 | * Copyright (c) 2009, 2010, 2011 Ericsson |
6e512b93 ASL |
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: | |
b59134e1 | 10 | * William Bourque - Initial API and implementation |
c392540b FC |
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 | |
6e512b93 | 15 | *******************************************************************************/ |
3e9fdb8b | 16 | |
6e512b93 ASL |
17 | package org.eclipse.linuxtools.lttng.ui.views.histogram; |
18 | ||
b59134e1 | 19 | import org.eclipse.linuxtools.lttng.event.LttngEvent; |
b59134e1 | 20 | import org.eclipse.linuxtools.tmf.event.TmfTimeRange; |
833a21aa | 21 | import org.eclipse.linuxtools.tmf.event.TmfTimestamp; |
b59134e1 | 22 | import org.eclipse.linuxtools.tmf.experiment.TmfExperiment; |
550d787e | 23 | import org.eclipse.linuxtools.tmf.request.ITmfDataRequest.ExecutionType; |
74237cc3 | 24 | import org.eclipse.linuxtools.tmf.signal.TmfExperimentRangeUpdatedSignal; |
ff4ed569 | 25 | import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal; |
ed4b3b9f | 26 | import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal; |
b59134e1 | 27 | import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler; |
c392540b | 28 | import org.eclipse.linuxtools.tmf.signal.TmfSignalManager; |
b59134e1 WB |
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; | |
252ae4bd | 33 | import org.eclipse.swt.layout.GridLayout; |
6e512b93 | 34 | import org.eclipse.swt.widgets.Composite; |
6e512b93 | 35 | |
544fe9b7 WB |
36 | /** |
37 | * <b><u>HistogramView</u></b> | |
38 | * <p> | |
c392540b FC |
39 | * The purpose of this view is to provide graphical time distribution statistics |
40 | * about the experiment/trace events. | |
544fe9b7 | 41 | * <p> |
c392540b FC |
42 | * The view is composed of two histograms and two controls: |
43 | * <ul> | |
44 | * <li>an event distribution histogram for the whole experiment; | |
45 | * <li>an event distribution histogram for current time window (window span); | |
46 | * <li>the timestamp of the currently selected event; | |
47 | * <li>the window span (size of the time window of the smaller histogram). | |
48 | * </ul> | |
49 | * The histograms x-axis show their respective time range. | |
544fe9b7 | 50 | */ |
c392540b FC |
51 | public class HistogramView extends TmfView { |
52 | ||
53 | // ------------------------------------------------------------------------ | |
54 | // Constants | |
55 | // ------------------------------------------------------------------------ | |
56 | ||
57 | // The view ID as defined in plugin.xml | |
3b38ea61 | 58 | public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.histogram"; //$NON-NLS-1$ |
c392540b FC |
59 | |
60 | // The initial window span (in nanoseconds) | |
61 | public static long INITIAL_WINDOW_SPAN = (1L * 100 * 1000 * 1000); // .1sec | |
62 | ||
63 | // Time scale | |
64 | private final byte TIME_SCALE = Histogram.TIME_SCALE; | |
65 | ||
66 | // ------------------------------------------------------------------------ | |
67 | // Attributes | |
68 | // ------------------------------------------------------------------------ | |
69 | ||
70 | // Parent widget | |
71 | private Composite fParent; | |
72 | ||
73 | // The current experiment | |
74 | private TmfExperiment<LttngEvent> fCurrentExperiment; | |
75 | ||
76 | // Current timestamp/time window | |
77 | private long fExperimentStartTime; | |
78 | private long fExperimentEndTime; | |
79 | private long fWindowStartTime; | |
80 | private long fWindowEndTime; | |
81 | private long fWindowSpan = INITIAL_WINDOW_SPAN; | |
82 | private long fCurrentTimestamp; | |
83 | ||
84 | // Time controls | |
85 | private HistogramTextControl fCurrentEventTimeControl; | |
86 | private HistogramTextControl fTimeSpanControl; | |
87 | ||
88 | // Histogram/request for the full trace range | |
89 | private static FullTraceHistogram fFullTraceHistogram; | |
90 | private HistogramRequest fFullTraceRequest; | |
91 | ||
92 | // Histogram/request for the selected time range | |
93 | private static TimeRangeHistogram fTimeRangeHistogram; | |
94 | private HistogramRequest fTimeRangeRequest; | |
95 | ||
96 | // ------------------------------------------------------------------------ | |
97 | // Constructor | |
98 | // ------------------------------------------------------------------------ | |
99 | ||
100 | public HistogramView() { | |
101 | super(ID); | |
102 | } | |
103 | ||
6a13fa07 | 104 | @Override |
c392540b | 105 | public void dispose() { |
6a13fa07 FC |
106 | fFullTraceHistogram.dispose(); |
107 | fTimeRangeHistogram.dispose(); | |
c392540b FC |
108 | } |
109 | ||
110 | // ------------------------------------------------------------------------ | |
111 | // TmfView | |
112 | // ------------------------------------------------------------------------ | |
113 | ||
114 | @Override | |
b59134e1 | 115 | @SuppressWarnings("unchecked") |
c392540b FC |
116 | public void createPartControl(Composite parent) { |
117 | ||
118 | fParent = parent; | |
119 | ||
120 | // Control labels | |
121 | final String currentEventLabel = Messages.HistogramView_currentEventLabel; | |
122 | final String windowSpanLabel = Messages.HistogramView_windowSpanLabel; | |
123 | ||
124 | // -------------------------------------------------------------------- | |
125 | // Set the HistogramView layout | |
126 | // -------------------------------------------------------------------- | |
127 | ||
128 | Composite viewComposite = new Composite(fParent, SWT.FILL); | |
129 | GridLayout gridLayout = new GridLayout(); | |
130 | gridLayout.numColumns = 2; | |
131 | gridLayout.horizontalSpacing = 5; | |
132 | gridLayout.verticalSpacing = 0; | |
133 | gridLayout.marginHeight = 0; | |
134 | gridLayout.marginWidth = 0; | |
135 | viewComposite.setLayout(gridLayout); | |
136 | ||
137 | // Use all available space | |
138 | GridData gridData = new GridData(); | |
139 | gridData.horizontalAlignment = SWT.FILL; | |
140 | gridData.verticalAlignment = SWT.FILL; | |
141 | gridData.grabExcessHorizontalSpace = true; | |
142 | viewComposite.setLayoutData(gridData); | |
143 | ||
144 | // -------------------------------------------------------------------- | |
145 | // Time controls | |
146 | // -------------------------------------------------------------------- | |
147 | ||
148 | Composite controlsComposite = new Composite(viewComposite, SWT.FILL); | |
149 | gridLayout = new GridLayout(); | |
150 | gridLayout.numColumns = 2; | |
151 | gridLayout.marginHeight = 0; | |
152 | gridLayout.marginWidth = 0; | |
153 | gridLayout.horizontalSpacing = 5; | |
154 | gridLayout.verticalSpacing = 0; | |
155 | gridLayout.makeColumnsEqualWidth = true; | |
156 | gridLayout.marginLeft = 5; | |
157 | gridLayout.marginRight = 5; | |
158 | controlsComposite.setLayout(gridLayout); | |
159 | ||
160 | // Current event time control | |
161 | gridData = new GridData(); | |
162 | gridData.horizontalAlignment = SWT.CENTER; | |
163 | gridData.verticalAlignment = SWT.CENTER; | |
164 | fCurrentEventTimeControl = new HistogramCurrentTimeControl(this, controlsComposite, SWT.BORDER, SWT.BORDER, currentEventLabel, | |
165 | HistogramUtils.nanosecondsToString(0L)); | |
166 | fCurrentEventTimeControl.setLayoutData(gridData); | |
167 | ||
168 | // Window span time control | |
169 | gridData = new GridData(); | |
170 | gridData.horizontalAlignment = SWT.CENTER; | |
171 | gridData.verticalAlignment = SWT.CENTER; | |
172 | fTimeSpanControl = new HistogramTimeRangeControl(this, controlsComposite, SWT.BORDER, SWT.BORDER, windowSpanLabel, | |
173 | HistogramUtils.nanosecondsToString(0L)); | |
174 | fTimeSpanControl.setLayoutData(gridData); | |
175 | ||
176 | // -------------------------------------------------------------------- | |
177 | // Time range histogram | |
178 | // -------------------------------------------------------------------- | |
179 | ||
180 | Composite timeRangeComposite = new Composite(viewComposite, SWT.FILL); | |
181 | gridLayout = new GridLayout(); | |
182 | gridLayout.numColumns = 1; | |
183 | gridLayout.marginHeight = 0; | |
184 | gridLayout.marginWidth = 0; | |
185 | gridLayout.marginTop = 5; | |
186 | gridLayout.horizontalSpacing = 0; | |
187 | gridLayout.verticalSpacing = 0; | |
188 | gridLayout.marginLeft = 5; | |
189 | gridLayout.marginRight = 5; | |
190 | timeRangeComposite.setLayout(gridLayout); | |
191 | ||
192 | // Use remaining horizontal space | |
193 | gridData = new GridData(); | |
194 | gridData.horizontalAlignment = SWT.FILL; | |
195 | gridData.verticalAlignment = SWT.FILL; | |
196 | gridData.grabExcessHorizontalSpace = true; | |
197 | timeRangeComposite.setLayoutData(gridData); | |
198 | ||
199 | // Histogram | |
200 | fTimeRangeHistogram = new TimeRangeHistogram(this, timeRangeComposite); | |
201 | ||
202 | // -------------------------------------------------------------------- | |
203 | // Full range histogram | |
204 | // -------------------------------------------------------------------- | |
205 | ||
206 | Composite fullRangeComposite = new Composite(viewComposite, SWT.FILL); | |
207 | gridLayout = new GridLayout(); | |
208 | gridLayout.numColumns = 1; | |
209 | gridLayout.marginHeight = 0; | |
210 | gridLayout.marginWidth = 0; | |
211 | gridLayout.marginTop = 5; | |
212 | gridLayout.horizontalSpacing = 0; | |
213 | gridLayout.verticalSpacing = 0; | |
214 | gridLayout.marginLeft = 5; | |
215 | gridLayout.marginRight = 5; | |
216 | fullRangeComposite.setLayout(gridLayout); | |
217 | ||
218 | // Use remaining horizontal space | |
219 | gridData = new GridData(); | |
220 | gridData.horizontalAlignment = SWT.FILL; | |
221 | gridData.verticalAlignment = SWT.FILL; | |
222 | gridData.horizontalSpan = 2; | |
223 | gridData.grabExcessHorizontalSpace = true; | |
224 | fullRangeComposite.setLayoutData(gridData); | |
225 | ||
226 | // Histogram | |
227 | fFullTraceHistogram = new FullTraceHistogram(this, fullRangeComposite); | |
228 | ||
229 | // Load the experiment if present | |
230 | fCurrentExperiment = (TmfExperiment<LttngEvent>) TmfExperiment.getCurrentExperiment(); | |
231 | if (fCurrentExperiment != null) | |
232 | loadExperiment(); | |
ecfd1d41 | 233 | } |
c392540b FC |
234 | |
235 | @Override | |
3e9fdb8b | 236 | @SuppressWarnings("unchecked") |
c392540b FC |
237 | public void setFocus() { |
238 | TmfExperiment<LttngEvent> experiment = (TmfExperiment<LttngEvent>) TmfExperiment.getCurrentExperiment(); | |
239 | if ((experiment != null) && (experiment != fCurrentExperiment)) { | |
240 | fCurrentExperiment = experiment; | |
241 | initializeHistograms(); | |
242 | } | |
243 | fParent.redraw(); | |
833a21aa | 244 | } |
c392540b FC |
245 | |
246 | // ------------------------------------------------------------------------ | |
247 | // Accessors | |
248 | // ------------------------------------------------------------------------ | |
249 | ||
250 | public TmfTimeRange getTimeRange() { | |
251 | return new TmfTimeRange(new TmfTimestamp(fWindowStartTime, TIME_SCALE), new TmfTimestamp(fWindowEndTime, TIME_SCALE)); | |
252 | } | |
253 | ||
254 | // ------------------------------------------------------------------------ | |
255 | // Operations | |
256 | // ------------------------------------------------------------------------ | |
257 | ||
258 | public void updateCurrentEventTime(long newTime) { | |
259 | if (fCurrentExperiment != null) { | |
260 | TmfTimeRange timeRange = new TmfTimeRange(new TmfTimestamp(newTime, TIME_SCALE), TmfTimestamp.BigCrunch); | |
74237cc3 | 261 | HistogramRequest request = new HistogramRequest(fTimeRangeHistogram, timeRange, 0, 1, ExecutionType.FOREGROUND) { |
c392540b FC |
262 | @Override |
263 | public void handleData(LttngEvent event) { | |
264 | if (event != null) { | |
265 | TmfTimeSynchSignal signal = new TmfTimeSynchSignal(this, event.getTimestamp()); | |
266 | TmfSignalManager.dispatchSignal(signal); | |
267 | } | |
268 | } | |
269 | }; | |
270 | fCurrentExperiment.sendRequest(request); | |
271 | } | |
272 | } | |
273 | ||
274 | public void updateTimeRange(long startTime, long endTime) { | |
275 | if (fCurrentExperiment != null) { | |
276 | // Build the new time range; keep the current time | |
277 | TmfTimeRange timeRange = new TmfTimeRange(new TmfTimestamp(startTime, TIME_SCALE), new TmfTimestamp(endTime, TIME_SCALE)); | |
278 | TmfTimestamp currentTime = new TmfTimestamp(fCurrentTimestamp, TIME_SCALE); | |
6a13fa07 | 279 | |
c392540b FC |
280 | fTimeSpanControl.setValue(endTime - startTime); |
281 | ||
282 | // Send the FW signal | |
283 | TmfRangeSynchSignal signal = new TmfRangeSynchSignal(this, timeRange, currentTime); | |
284 | TmfSignalManager.dispatchSignal(signal); | |
285 | } | |
286 | } | |
287 | ||
288 | public synchronized void updateTimeRange(long newDuration) { | |
289 | if (fCurrentExperiment != null) { | |
6a13fa07 FC |
290 | long delta = newDuration - fWindowSpan; |
291 | long newStartTime = fWindowStartTime + delta / 2; | |
292 | setNewRange(newStartTime, newDuration); | |
c392540b FC |
293 | } |
294 | } | |
295 | ||
296 | private void setNewRange(long startTime, long duration) { | |
297 | if (startTime < fExperimentStartTime) | |
6a13fa07 | 298 | startTime = fExperimentStartTime; |
c392540b FC |
299 | |
300 | long endTime = startTime + duration; | |
301 | if (endTime > fExperimentEndTime) { | |
6a13fa07 FC |
302 | endTime = fExperimentEndTime; |
303 | if (endTime - duration > fExperimentStartTime) | |
304 | startTime = endTime - duration; | |
305 | else { | |
306 | startTime = fExperimentStartTime; | |
307 | } | |
c392540b FC |
308 | } |
309 | updateTimeRange(startTime, endTime); | |
833a21aa | 310 | } |
c392540b FC |
311 | |
312 | // ------------------------------------------------------------------------ | |
313 | // Signal handlers | |
314 | // ------------------------------------------------------------------------ | |
315 | ||
1406f802 | 316 | @TmfSignalHandler |
c392540b FC |
317 | @SuppressWarnings("unchecked") |
318 | public void experimentSelected(TmfExperimentSelectedSignal<LttngEvent> signal) { | |
319 | assert (signal != null); | |
320 | fCurrentExperiment = (TmfExperiment<LttngEvent>) signal.getExperiment(); | |
321 | loadExperiment(); | |
ecfd1d41 | 322 | } |
550d787e | 323 | |
c392540b | 324 | private void loadExperiment() { |
c392540b FC |
325 | initializeHistograms(); |
326 | fParent.redraw(); | |
550d787e FC |
327 | } |
328 | ||
74237cc3 FC |
329 | @TmfSignalHandler |
330 | @SuppressWarnings("unchecked") | |
331 | public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal) { | |
332 | ||
333 | fCurrentExperiment = (TmfExperiment<LttngEvent>) signal.getExperiment(); | |
334 | boolean drawTimeRangeHistogram = fExperimentStartTime == 0; | |
335 | TmfTimeRange fullRange = signal.getRange(); | |
336 | ||
337 | fExperimentStartTime = fullRange.getStartTime().getValue(); | |
338 | fExperimentEndTime = fullRange.getEndTime().getValue(); | |
339 | ||
340 | fFullTraceHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime); | |
341 | fTimeRangeHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime); | |
342 | ||
343 | if (drawTimeRangeHistogram) { | |
344 | fCurrentTimestamp = fExperimentStartTime; | |
345 | fCurrentEventTimeControl.setValue(fCurrentTimestamp); | |
346 | fFullTraceHistogram.setTimeRange(fExperimentStartTime, INITIAL_WINDOW_SPAN); | |
347 | fTimeRangeHistogram.setTimeRange(fExperimentStartTime, INITIAL_WINDOW_SPAN); | |
348 | sendTimeRangeRequest(fExperimentStartTime, fExperimentStartTime + INITIAL_WINDOW_SPAN); | |
349 | } | |
350 | ||
351 | sendFullRangeRequest(fullRange); | |
352 | } | |
c392540b FC |
353 | |
354 | @TmfSignalHandler | |
355 | public void currentTimeUpdated(TmfTimeSynchSignal signal) { | |
356 | // Because this can't happen :-) | |
357 | assert (signal != null); | |
358 | ||
359 | // Update the selected event time | |
360 | TmfTimestamp currentTime = signal.getCurrentTime(); | |
361 | fCurrentTimestamp = currentTime.getValue(); | |
362 | ||
363 | // Notify the relevant widgets | |
364 | fFullTraceHistogram.setCurrentEvent(fCurrentTimestamp); | |
365 | fTimeRangeHistogram.setCurrentEvent(fCurrentTimestamp); | |
366 | fCurrentEventTimeControl.setValue(fCurrentTimestamp); | |
ecfd1d41 | 367 | } |
f05aabed | 368 | |
c392540b FC |
369 | @TmfSignalHandler |
370 | public void timeRangeUpdated(TmfRangeSynchSignal signal) { | |
371 | // Because this can't happen :-) | |
372 | assert (signal != null); | |
373 | ||
374 | if (fCurrentExperiment != null) { | |
375 | // Update the time range | |
376 | fWindowStartTime = signal.getCurrentRange().getStartTime().getValue(); | |
377 | fWindowEndTime = signal.getCurrentRange().getEndTime().getValue(); | |
378 | fWindowSpan = fWindowEndTime - fWindowStartTime; | |
379 | ||
380 | // Notify the relevant widgets | |
381 | sendTimeRangeRequest(fWindowStartTime, fWindowEndTime); | |
382 | fFullTraceHistogram.setTimeRange(fWindowStartTime, fWindowSpan); | |
383 | fTimeSpanControl.setValue(fWindowSpan); | |
384 | } | |
b59134e1 | 385 | } |
c392540b FC |
386 | |
387 | // ------------------------------------------------------------------------ | |
388 | // Helper functions | |
389 | // ------------------------------------------------------------------------ | |
390 | ||
391 | private void initializeHistograms() { | |
74237cc3 FC |
392 | TmfTimeRange fullRange = updateExperimentTimeRange(fCurrentExperiment); |
393 | ||
394 | fTimeRangeHistogram.clear(); | |
c392540b FC |
395 | fTimeRangeHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime); |
396 | fTimeRangeHistogram.setTimeRange(fExperimentStartTime, INITIAL_WINDOW_SPAN); | |
397 | fTimeRangeHistogram.setCurrentEvent(fExperimentStartTime); | |
398 | ||
74237cc3 | 399 | fFullTraceHistogram.clear(); |
6a13fa07 | 400 | fFullTraceHistogram.setFullRange(fExperimentStartTime, fExperimentEndTime); |
c392540b FC |
401 | fFullTraceHistogram.setTimeRange(fExperimentStartTime, INITIAL_WINDOW_SPAN); |
402 | fFullTraceHistogram.setCurrentEvent(fExperimentStartTime); | |
403 | ||
404 | fWindowStartTime = fExperimentStartTime; | |
405 | fWindowSpan = INITIAL_WINDOW_SPAN; | |
406 | fWindowEndTime = fWindowStartTime + fWindowSpan; | |
6a13fa07 | 407 | |
c392540b FC |
408 | fCurrentEventTimeControl.setValue(fExperimentStartTime); |
409 | fTimeSpanControl.setValue(fWindowSpan); | |
6a13fa07 | 410 | |
c392540b | 411 | sendTimeRangeRequest(fExperimentStartTime, fExperimentStartTime + fWindowSpan); |
74237cc3 FC |
412 | sendFullRangeRequest(fullRange); |
413 | } | |
414 | ||
415 | private TmfTimeRange updateExperimentTimeRange(TmfExperiment<LttngEvent> experiment) { | |
416 | fExperimentStartTime = 0; | |
417 | fExperimentEndTime = 0; | |
418 | fCurrentTimestamp = 0; | |
419 | ||
420 | TmfTimeRange timeRange = fCurrentExperiment.getTimeRange(); | |
421 | if (timeRange != TmfTimeRange.Null) { | |
422 | fExperimentStartTime = timeRange.getStartTime().getValue(); | |
423 | fExperimentEndTime = timeRange.getEndTime().getValue(); | |
424 | fCurrentTimestamp = fExperimentStartTime; | |
425 | } | |
426 | return timeRange; | |
b59134e1 | 427 | } |
c392540b FC |
428 | |
429 | private void sendTimeRangeRequest(long startTime, long endTime) { | |
430 | if (fTimeRangeRequest != null && !fTimeRangeRequest.isCompleted()) { | |
431 | fTimeRangeRequest.cancel(); | |
088c1d4e | 432 | } |
c392540b FC |
433 | TmfTimestamp startTS = new TmfTimestamp(startTime, TIME_SCALE); |
434 | TmfTimestamp endTS = new TmfTimestamp(endTime, TIME_SCALE); | |
435 | TmfTimeRange timeRange = new TmfTimeRange(startTS, endTS); | |
436 | ||
437 | fTimeRangeHistogram.clear(); | |
438 | fTimeRangeHistogram.setTimeRange(startTime, endTime - startTime); | |
439 | fTimeRangeRequest = new HistogramRequest(fTimeRangeHistogram, timeRange, ExecutionType.FOREGROUND); | |
440 | fCurrentExperiment.sendRequest(fTimeRangeRequest); | |
088c1d4e | 441 | } |
c392540b | 442 | |
74237cc3 | 443 | private void sendFullRangeRequest(TmfTimeRange fullRange) { |
c392540b FC |
444 | if (fFullTraceRequest != null && !fFullTraceRequest.isCompleted()) { |
445 | fFullTraceRequest.cancel(); | |
446 | } | |
74237cc3 FC |
447 | fFullTraceRequest = new HistogramRequest(fFullTraceHistogram, fullRange, (int) fFullTraceHistogram.fDataModel.getNbEvents(), |
448 | ExecutionType.BACKGROUND); | |
c392540b | 449 | fCurrentExperiment.sendRequest(fFullTraceRequest); |
ed4b3b9f | 450 | } |
c392540b | 451 | |
6e512b93 | 452 | } |