2010-10-26 Francois Chouinard <fchouinard@gmail.com> Contribution for Bug309042
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng.ui / src / org / eclipse / linuxtools / lttng / ui / views / histogram / ParentHistogramCanvas.java
CommitLineData
6e512b93
ASL
1/*******************************************************************************
2 * Copyright (c) 2009 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
3e9fdb8b
FC
11 *
12 * Modifications:
13 * 2010-06-20 Yuriy Vashchuk - Histogram optimisations.
f05aabed
FC
14 * 2010-07-16 Yuriy Vashchuk - Base Histogram class simplification.
15 * Selection Window related methods has been
16 * implemented here (Parent Histogram).
6e512b93
ASL
17 *******************************************************************************/
18package org.eclipse.linuxtools.lttng.ui.views.histogram;
19
20import org.eclipse.swt.widgets.Composite;
f05aabed 21import org.eclipse.swt.widgets.Display;
6e512b93
ASL
22
23/**
24 * <b><u>ParentHistogramCanvas</u></b>
25 * <p>
26 * Extended implementation of the HistogramCanvas.
27 * <p>
7c1540ab 28 * This canvas goal is to display the "Full experiment" histogram.
6e512b93
ASL
29 */
30public class ParentHistogramCanvas extends HistogramCanvas {
31
f05aabed
FC
32 private ParentHistogramCanvasPaintListener paintListener = null;
33 private HistogramCanvasMouseListener mouseListener = null;
34 private HistogramCanvasKeyListener keyListener = null;
35 private ParentHistogramCanvasControlListener controlListener = null;
36
37 private HistogramSelectedWindow currentWindow = null;
6e512b93
ASL
38
39 /**
40 * ParentHistogramCanvas constructor.<p>
41 * Same as HistogramCanvas, but receive a parent HistogramView that we can call from here.
42 *
43 * @param parent Composite control which will be the parent of the new instance (cannot be null)
44 * @param Style the style of control to construct
45 */
f05aabed
FC
46 public ParentHistogramCanvas(HistogramView histogramView, Composite parent, int style) {
47 super(histogramView, parent, style);
6e512b93 48
f05aabed
FC
49 // New selected window, not visible by default
50 if (histogramView !=null && HistogramView.getFullExperimentCanvas() != null) {
51 createNewSelectedWindow(
52 HistogramView.getFullExperimentCanvas().getHistogramContent().getStartTime() + HistogramView.getDEFAULT_WINDOW_SIZE() / 2,
53 HistogramView.getDEFAULT_WINDOW_SIZE()
54 );
55 }
3e9fdb8b
FC
56
57 // 2010-06-20 Yuriy: Moved from parent class
3e9fdb8b
FC
58 createAndAddPaintListener();
59 createAndAddMouseListener();
60 createAndAddKeyListener();
3e9fdb8b 61 createAndAddControlListener();
6e512b93
ASL
62 }
63
7c1540ab
WB
64 /**
65 * Create a new HistogramContent for this HistogramCanvas<p>
66 * A new <I>empty</I> canvas will then be created.
67 *
68 * IMPORTANT NOTE : This implementaton use the next power of 2 to the full screen resolution as the content size.
69 * This allow us to resize the canvas at low cost (i.e. : no need to reissue a full request)
70 * We need a "particular" paint listener that know about this.
71 *
72 * @param canvasSize Size of the parent canvas.
73 * @param widthPerBar Width of the histogram "bars"
74 * @param barsHeight Height of the histogram "bars"
75 * @param maxBarsDifferenceToAverage Factor used to "chop" bars that are too tall. Set to something big (100.0?) if not needed.
76 */
77 @Override
1406f802 78 public void createNewHistogramContent(int canvasSize, int widthPerBar, int barsHeight, double maxBarsDifferenceToAverage) {
7c1540ab
WB
79
80 // *** FIXME ***
81 // Note there MIGHT be some unhandled case, like if the resolution of the screen change
82 // or if a new screen is plugged.
83 // Let's ignore them for now.
84 //
85 // The maximum size the canvas could ever had
86 int canvasMaxSize = getParent().getDisplay().getBounds().width;
87
88 // Calculate the power of two superior to the max size
89 int exp = (int)Math.ceil( Math.log( (double)canvasMaxSize ) / Math.log(2.0) );
90 int contentSize = (int)Math.pow(2, exp);
91
92 // Create the content
93 histogramContent = new HistogramContent( contentSize, canvasSize, widthPerBar, barsHeight, maxBarsDifferenceToAverage);
7ef9ae3f
WB
94
95 // We need to ajust the "maxDifferenceToAverageFactor" as the bars we draw might be slitghly larger than the value asked
96 // Each "interval" are concatenated when draw so the worst case should be :
97 // contentSize / (closest power of 2 to canvasMaxSize)
98 // Ex : if canvasSize is 1500 -> (2048 / 1024) == 2 so maxDiff should be twice larger
99 //
100 // Note : this is not perfect, if the screen is resized after we calculate this, the resulting output can be quite ugly
101 // For this reason, this will be recalculated in the paintListener as well.
102 double maxBarsDiffFactor = ((double)contentSize / Math.pow(2, exp-1));
103 histogramContent.setMaxDifferenceToAverageFactor(maxBarsDiffFactor);
7c1540ab 104 }
f05aabed 105
7c1540ab
WB
106
107 /*
108 * Create a histogram paint listener and bind it to this canvas.<p>
109 *
110 * Note : This one is a bit particular, as it is made to draw content that is of a power of 2.
111 * The default one draw content that is relative to the real pixels size.
112 */
f05aabed 113 private void createAndAddPaintListener() {
3e9fdb8b 114 paintListener = new ParentHistogramCanvasPaintListener(this);
7c1540ab
WB
115 this.addPaintListener( paintListener );
116 }
f05aabed
FC
117
118 /*
119 * Create a histogram mouse listener and bind it to this canvas.<p>
120 * Note : this mouse listener handle the mouse, the move and the wheel at once.
121 *
122 * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasMouseListener
123 */
124 private void createAndAddMouseListener() {
125 mouseListener = new HistogramCanvasMouseListener(this);
126 this.addMouseListener(mouseListener);
127 this.addMouseMoveListener(mouseListener);
128 this.addMouseWheelListener(mouseListener);
129 }
130
131 /*
132 * Create a histogram key listener and bind it to this canvas.<p>
133 *
134 * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasKeyListener
135 */
136 private void createAndAddKeyListener() {
137 keyListener = new HistogramCanvasKeyListener(this);
138 this.addKeyListener(keyListener);
139 }
7c1540ab 140
3e9fdb8b
FC
141 /*
142 * Create a histogram control listener and bind it to this canvas.<p>
143 *
144 * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasControlListener
145 */
f05aabed 146 private void createAndAddControlListener() {
3e9fdb8b
FC
147 controlListener = new ParentHistogramCanvasControlListener(this);
148 this.addControlListener(controlListener);
149 }
f05aabed
FC
150
151 /**
152 * Create a new selection window of the size (time width) given.<p>
153 * The window initial position is at X = 0.
154 * The window is created hidden, it won't be draw unless it is set to visible.<p>
155 *
156 * @param windowTimeDuration Time width (in nanosecond) of the window.
157 */
158 public void createNewSelectedWindow(long timestampOfLeftPosition, long windowTimeDuration) {
159 currentWindow = new HistogramSelectedWindow(histogramContent, timestampOfLeftPosition, windowTimeDuration);
160 }
161
162 /**
163 * Getter for the selection window<p>
164 *
165 * @return the current selection window
166 *
167 * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramSelectedWindow
168 */
169 public HistogramSelectedWindow getCurrentWindow() {
170 return currentWindow;
171 }
172
173 /**
174 * Getter for the selection window width<p>
175 *
176 * @return Time width (in nanosecond) of the selection window.
177 */
178 public long getSelectedWindowSize() {
179 return currentWindow.getWindowTimeWidth();
180 }
3e9fdb8b 181
f05aabed
FC
182 /**
183 * Setter for the selection window width<p>
184 * The window size will be ajusted if it does not respect one of these constraints :
185 * - The window size cannot be smaller than a single histogram content interval.<p>
186 * - The window size cannot be larger than twice the histogram content complete time interval.<p>
187 *
188 * @param newSelectedWindowSize New time width (in nanosecond) of the selection window.
189 */
190 public void setSelectedWindowSize(long newSelectedWindowSize) {
191
192 if ( newSelectedWindowSize <= 0 ) {
193 newSelectedWindowSize = 1L;
194 }
195 else if ( newSelectedWindowSize > (2*histogramContent.getCompleteTimeInterval()) ) {
196 newSelectedWindowSize = (2*histogramContent.getCompleteTimeInterval());
197 }
198
199 currentWindow.setWindowTimeWidth(newSelectedWindowSize);
200 }
3e9fdb8b 201
6e512b93
ASL
202 /**
203 * Function that is called when the selection window is moved.<p>
204 * Note: Given position should be relative to the previous (centered) absolute position.<p>
205 *
206 * Calculate the new position then re-center the window.<p>
207 * It will also notify the HistogramView that the window changed.
208 *
209 * @param newRelativeXPosition New position relative to the last known absolute position.
210 */
1406f802 211 public void moveWindow(int newRelativeXPosition) {
833a21aa 212 int absolutePosition = currentWindow.getWindowXPositionCenter() + newRelativeXPosition;
6e512b93 213
1406f802 214 setWindowCenterPosition(absolutePosition);
833a21aa 215 notifyParentSelectionWindowChangedAsynchronously();
6e512b93 216 }
f05aabed 217
6e512b93
ASL
218 /**
219 * Function that is called when the selection window is re-centered.<p>
220 * Note: Given position should be absolute to the window and need to be the selection window center.<p>
221 *
222 * Recenter the window and notify the HistogramView that the window changed.
223 *
224 * @param newRelativeXPosition New absolute position.
225 */
1406f802 226 public void setWindowCenterPosition(int newAbsoluteXPosition) {
6e512b93 227
f05aabed
FC
228 // We will check if the coordinate the same
229 if ( newAbsoluteXPosition != currentWindow.getWindowXPositionCenter() ) {
230
231 long timestampOfLeftPosition = this.getHistogramContent().getClosestElementFromXPosition( newAbsoluteXPosition ).firstIntervalTimestamp - currentWindow.getWindowTimeWidth() / 2;
232 long timestampOfCenterPosition = 0;
233 long timestampOfRightPosition = 0;
234
235 // Let's do the border verifications
236 if ( timestampOfLeftPosition < histogramContent.getStartTime() ) {
237
238 timestampOfLeftPosition = histogramContent.getStartTime();
239 timestampOfCenterPosition = timestampOfLeftPosition + currentWindow.getWindowTimeWidth() / 2;
240 timestampOfRightPosition = timestampOfLeftPosition + currentWindow.getWindowTimeWidth();
241
242 } else {
243
244 timestampOfRightPosition = this.getHistogramContent().getClosestElementFromXPosition( newAbsoluteXPosition ).firstIntervalTimestamp + currentWindow.getWindowTimeWidth() / 2;
245
246 if ( timestampOfRightPosition > histogramContent.getEndTime() ) {
247
248 timestampOfRightPosition = histogramContent.getEndTime();
249 timestampOfCenterPosition = timestampOfRightPosition - currentWindow.getWindowTimeWidth() / 2;
250 timestampOfLeftPosition = timestampOfRightPosition - currentWindow.getWindowTimeWidth();
251
252 } else {
253
254 timestampOfCenterPosition = this.getHistogramContent().getClosestElementFromXPosition( newAbsoluteXPosition ).firstIntervalTimestamp;
255
256 }
257
258 }
259
260 // We will do the update in case of different center timestamp
261 if( timestampOfCenterPosition != currentWindow.getTimestampOfCenterPosition() ) {
262 // Firstly we will setup new left, right and center timestamps
263 currentWindow.setTimestampOfLeftPosition( timestampOfLeftPosition );
264 currentWindow.setTimestampOfCenterPosition( timestampOfCenterPosition );
265 currentWindow.setTimestampOfRightPosition( timestampOfRightPosition );
266
267 // After we will update coordonates using timestamps already recalculated
268 currentWindow.setWindowXPositionLeft( histogramContent.getClosestXPositionFromTimestamp(timestampOfLeftPosition) );
269 currentWindow.setWindowXPositionCenter( histogramContent.getClosestXPositionFromTimestamp(timestampOfCenterPosition) );
270 currentWindow.setWindowXPositionRight( histogramContent.getClosestXPositionFromTimestamp(timestampOfRightPosition) );
271
272 redrawAsynchronously();
273 }
6e512b93 274 }
f05aabed
FC
275 }
276
277 /**
278 * Function that is called when the selection window is re-centered.<p>
279 * Note: Given position should be timestamp in the experiment timerange<p>
280 *
281 * Recenter the window and notify the HistogramView that the window changed.
282 *
283 * @param timestampOfCenterPosition New timestamp of center position.
284 */
285 public void setWindowCenterPosition(long timestampOfCenterPosition) {
6e512b93 286
f05aabed
FC
287 // We will check if the coordinate the same
288 if ( timestampOfCenterPosition != currentWindow.getTimestampOfCenterPosition() ) {
289
290 long timestampOfLeft = timestampOfCenterPosition - currentWindow.getWindowTimeWidth() / 2;
291 long timestampOfCenter = 0;
292 long timestampOfRight = 0;
293
294 int windowXPositionLeft = histogramContent.getClosestXPositionFromTimestamp(timestampOfLeft);
295 int windowXPositionCenter = 0;
296 int windowXPositionRight = 0;
297
298 // Let's do the border verifications
299 if ( timestampOfLeft < histogramContent.getStartTime() ) {
300
301 timestampOfLeft = histogramContent.getStartTime();
302 timestampOfCenter = timestampOfLeft + currentWindow.getWindowTimeWidth() / 2;
303 timestampOfRight = timestampOfLeft + currentWindow.getWindowTimeWidth();
304
305 windowXPositionLeft = histogramContent.getClosestXPositionFromTimestamp(timestampOfLeft);
306 windowXPositionCenter = histogramContent.getClosestXPositionFromTimestamp(timestampOfCenter);
307 windowXPositionRight = histogramContent.getClosestXPositionFromTimestamp(timestampOfRight);
308
309 } else {
310
311 timestampOfRight = timestampOfCenterPosition + currentWindow.getWindowTimeWidth() / 2;
312 windowXPositionRight = histogramContent.getClosestXPositionFromTimestamp(timestampOfRight);
313
314 if ( windowXPositionRight > histogramContent.getEndTime() ) {
315
316 timestampOfRight = histogramContent.getEndTime();
317 timestampOfCenter = timestampOfRight - currentWindow.getWindowTimeWidth() / 2;
318 timestampOfLeft = timestampOfRight - currentWindow.getWindowTimeWidth();
319
320 windowXPositionLeft = histogramContent.getClosestXPositionFromTimestamp(timestampOfLeft);
321 windowXPositionCenter = histogramContent.getClosestXPositionFromTimestamp(timestampOfCenter);
322 windowXPositionRight = histogramContent.getClosestXPositionFromTimestamp(timestampOfRight);
323
324 } else {
325
326 timestampOfCenter = timestampOfCenterPosition;
327 windowXPositionCenter = histogramContent.getClosestXPositionFromTimestamp(timestampOfCenter);
328
329 }
330
331 }
332
333 // Firstly we will setup new left, right and center timestamps
334 currentWindow.setTimestampOfLeftPosition( timestampOfLeft );
335 currentWindow.setTimestampOfCenterPosition( timestampOfCenter );
336 currentWindow.setTimestampOfRightPosition( timestampOfRight );
337
338 // We will do the update in case of different center timestamp
339 if( windowXPositionCenter != currentWindow.getWindowXPositionCenter() ) {
340
341 // After we will update coordonates using timestamps already recalculated
342 currentWindow.setWindowXPositionLeft(windowXPositionLeft);
343 currentWindow.setWindowXPositionCenter(windowXPositionCenter);
344 currentWindow.setWindowXPositionRight(windowXPositionRight);
345
346 redrawAsynchronously();
347 }
6e512b93
ASL
348 }
349 }
350
f05aabed 351
6e512b93 352 /**
088c1d4e
WB
353 * Function that is called when the selection window size (time width) changed by an absolute time.<p>
354 * Note: Given time should be in nanoseconds, positive.
6e512b93
ASL
355 *
356 * Set the new window size and notify the HistogramView that the window changed.
357 *
088c1d4e 358 * @param newTime New absoulte time (in nanoseconds) to apply to the window.
6e512b93 359 */
1406f802 360 public void resizeWindowByAbsoluteTime(long newTime) {
088c1d4e 361 if ( newTime != getSelectedWindowSize() ) {
f05aabed
FC
362
363 resizeWindowByAbsoluteTimeWithoutNotification(newTime);
6e512b93 364
833a21aa 365 notifyParentSelectionWindowChangedAsynchronously();
f05aabed
FC
366 }
367 }
368
369 /**
370 * Function that is called when the selection window size (time width) changed by an absolute time.<p>
371 * Note: Given time should be in nanoseconds, positive.
372 *
373 * Set the new window size and notify the HistogramView that the window changed.
374 *
375 * @param newTime New absoulte time (in nanoseconds) to apply to the window.
376 */
377 public void resizeWindowByAbsoluteTimeWithoutNotification(long newTime) {
378
379 // We will change the size in case of delta (newTime) != 0
380 if (newTime != 0 ) {
381
382 if(newTime > getHistogramContent().getEndTime() - getHistogramContent().getStartTime()) {
383 newTime = getHistogramContent().getEndTime() - getHistogramContent().getStartTime();
384 }
385
386 setSelectedWindowSize(newTime);
387
388 /*
389 // Yuriy: we can't use this function because we change the left and right coordinates.
390 setWindowCenterPosition(currentWindow.getWindowXPositionCenter());
391 */
392
393 long timestampOfLeftPosition = currentWindow.getTimestampOfCenterPosition() - currentWindow.getWindowTimeWidth() / 2;
394 long timestampOfCenterPosition = currentWindow.getTimestampOfCenterPosition();
395 long timestampOfRightPosition = 0;
396
397 // Let's do the border verifications
398 if ( timestampOfLeftPosition < histogramContent.getStartTime() ) {
399
400 timestampOfLeftPosition = histogramContent.getStartTime();
401 timestampOfCenterPosition = timestampOfLeftPosition + currentWindow.getWindowTimeWidth() / 2;
402 timestampOfRightPosition = timestampOfLeftPosition + currentWindow.getWindowTimeWidth();
403
404 } else {
405
406 timestampOfRightPosition = currentWindow.getTimestampOfCenterPosition() + currentWindow.getWindowTimeWidth() / 2;
407
408 if ( timestampOfRightPosition > histogramContent.getEndTime() ) {
409
410 timestampOfRightPosition = histogramContent.getEndTime();
411 timestampOfCenterPosition = timestampOfRightPosition - currentWindow.getWindowTimeWidth() / 2;
412 timestampOfLeftPosition = timestampOfRightPosition - currentWindow.getWindowTimeWidth();
413
414 }
415
416 }
417
418 // Firstly we will setup new left, right and center timestamps
419 currentWindow.setTimestampOfLeftPosition( timestampOfLeftPosition );
420 currentWindow.setTimestampOfCenterPosition( timestampOfCenterPosition );
421 currentWindow.setTimestampOfRightPosition( timestampOfRightPosition );
422
423 // After we will update coordonates using timestamps already recalculated
424 currentWindow.setWindowXPositionLeft( histogramContent.getClosestXPositionFromTimestamp(timestampOfLeftPosition) );
425 currentWindow.setWindowXPositionCenter( histogramContent.getClosestXPositionFromTimestamp(timestampOfCenterPosition) );
426 currentWindow.setWindowXPositionRight( histogramContent.getClosestXPositionFromTimestamp(timestampOfRightPosition) );
427
6e512b93
ASL
428 redrawAsynchronously();
429 }
430 }
431
432 /**
433 * Notify the parent HistogramView that we have updated information.<p>
434 * This is intended to be called at the end of the request when we know we have up-to-date information.
435 */
436 @Override
437 public void notifyParentUpdatedInformation() {
f05aabed 438 getHistogramView().updateFullExperimentInformation();
6e512b93
ASL
439 }
440
441 /**
442 * Notify the parent HistogramView that the SelectionWindow changed.<p>
443 * This is intended to be called when the window move or is resized.
444 */
6e512b93
ASL
445 public void notifyParentSelectionWindowChanged() {
446 // Notify the parent view that something changed
f05aabed 447 getHistogramView().windowChangedNotification();
1406f802 448 // Send a broadcast to the framework about the window change
f05aabed 449 getHistogramView().sendTmfRangeSynchSignalBroadcast();
6e512b93 450 }
f05aabed
FC
451
452 /**
453 * Method to call the "Asynchronous NotifyParentSelectionWindowChanged" for this canvas<p>
454 * This allow safe update UI objects from different threads.
455 *
456 */
457 public void notifyParentSelectionWindowChangedAsynchronously() {
458 // Create a new redrawer in case it doesn't exist yet (we never know with thread!)
459 if ( canvasRedrawer == null ) {
460 canvasRedrawer = new AsyncCanvasRedrawer(this);
461 }
462
463 asynchronousNotifyParentSelectionWindowChanged();
464 }
465
466 /**
467 * Function to asynchonously notify the parent of the related canvas that the window changed.<p>
468 *
469 * Basically, it just run "notifyParentSelectionWindowChanged()" in asyncExec.
470 *
471 */
472 public void asynchronousNotifyParentSelectionWindowChanged() {
db1ea19b
FC
473 // Ignore update if widget is disposed
474 if (this.isDisposed()) return;
475
f05aabed
FC
476 Display display = this.getDisplay();
477 display.asyncExec(new Runnable() {
d4011df2 478 @Override
f05aabed 479 public void run() {
db1ea19b
FC
480 if(!ParentHistogramCanvas.this.isDisposed())
481 notifyParentSelectionWindowChanged();
f05aabed
FC
482 }
483 });
484 }
6e512b93 485}
This page took 0.053449 seconds and 5 git commands to generate.