1 /*******************************************************************************
2 * Copyright (c) 2009 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
13 * 2010-06-20 Yuriy Vashchuk - Histogram optimisations.
14 * 2010-07-16 Yuriy Vashchuk - Base Histogram class simplification.
15 * Selection Window related methods has been
16 * implemented here (Parent Histogram).
17 *******************************************************************************/
18 package org
.eclipse
.linuxtools
.lttng
.ui
.views
.histogram
;
20 import org
.eclipse
.swt
.widgets
.Composite
;
21 import org
.eclipse
.swt
.widgets
.Display
;
24 * <b><u>ParentHistogramCanvas</u></b>
26 * Extended implementation of the HistogramCanvas.
28 * This canvas goal is to display the "Full experiment" histogram.
30 public class ParentHistogramCanvas
extends HistogramCanvas
{
32 private ParentHistogramCanvasPaintListener paintListener
= null;
33 private HistogramCanvasMouseListener mouseListener
= null;
34 private HistogramCanvasKeyListener keyListener
= null;
35 private ParentHistogramCanvasControlListener controlListener
= null;
37 private HistogramSelectedWindow currentWindow
= null;
40 * ParentHistogramCanvas constructor.<p>
41 * Same as HistogramCanvas, but receive a parent HistogramView that we can call from here.
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
46 public ParentHistogramCanvas(HistogramView histogramView
, Composite parent
, int style
) {
47 super(histogramView
, parent
, style
);
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()
57 // 2010-06-20 Yuriy: Moved from parent class
58 createAndAddPaintListener();
59 createAndAddMouseListener();
60 createAndAddKeyListener();
61 createAndAddControlListener();
65 * Create a new HistogramContent for this HistogramCanvas<p>
66 * A new <I>empty</I> canvas will then be created.
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.
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.
78 public void createNewHistogramContent(int canvasSize
, int widthPerBar
, int barsHeight
, double maxBarsDifferenceToAverage
) {
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.
85 // The maximum size the canvas could ever had
86 int canvasMaxSize
= getParent().getDisplay().getBounds().width
;
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
);
93 histogramContent
= new HistogramContent( contentSize
, canvasSize
, widthPerBar
, barsHeight
, maxBarsDifferenceToAverage
);
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
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
);
108 * Create a histogram paint listener and bind it to this canvas.<p>
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.
113 private void createAndAddPaintListener() {
114 paintListener
= new ParentHistogramCanvasPaintListener(this);
115 this.addPaintListener( paintListener
);
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.
122 * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasMouseListener
124 private void createAndAddMouseListener() {
125 mouseListener
= new HistogramCanvasMouseListener(this);
126 this.addMouseListener(mouseListener
);
127 this.addMouseMoveListener(mouseListener
);
128 this.addMouseWheelListener(mouseListener
);
132 * Create a histogram key listener and bind it to this canvas.<p>
134 * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasKeyListener
136 private void createAndAddKeyListener() {
137 keyListener
= new HistogramCanvasKeyListener(this);
138 this.addKeyListener(keyListener
);
142 * Create a histogram control listener and bind it to this canvas.<p>
144 * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramCanvasControlListener
146 private void createAndAddControlListener() {
147 controlListener
= new ParentHistogramCanvasControlListener(this);
148 this.addControlListener(controlListener
);
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>
156 * @param windowTimeDuration Time width (in nanosecond) of the window.
158 public void createNewSelectedWindow(long timestampOfLeftPosition
, long windowTimeDuration
) {
159 currentWindow
= new HistogramSelectedWindow(histogramContent
, timestampOfLeftPosition
, windowTimeDuration
);
163 * Getter for the selection window<p>
165 * @return the current selection window
167 * @see org.eclipse.linuxtools.lttng.ui.views.histogram.HistogramSelectedWindow
169 public HistogramSelectedWindow
getCurrentWindow() {
170 return currentWindow
;
174 * Getter for the selection window width<p>
176 * @return Time width (in nanosecond) of the selection window.
178 public long getSelectedWindowSize() {
179 return currentWindow
.getWindowTimeWidth();
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>
188 * @param newSelectedWindowSize New time width (in nanosecond) of the selection window.
190 public void setSelectedWindowSize(long newSelectedWindowSize
) {
192 if ( newSelectedWindowSize
<= 0 ) {
193 newSelectedWindowSize
= 1L;
195 else if ( newSelectedWindowSize
> (2*histogramContent
.getCompleteTimeInterval()) ) {
196 newSelectedWindowSize
= (2*histogramContent
.getCompleteTimeInterval());
199 currentWindow
.setWindowTimeWidth(newSelectedWindowSize
);
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>
206 * Calculate the new position then re-center the window.<p>
207 * It will also notify the HistogramView that the window changed.
209 * @param newRelativeXPosition New position relative to the last known absolute position.
211 public void moveWindow(int newRelativeXPosition
) {
212 int absolutePosition
= currentWindow
.getWindowXPositionCenter() + newRelativeXPosition
;
214 setWindowCenterPosition(absolutePosition
);
215 notifyParentSelectionWindowChangedAsynchronously();
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>
222 * Recenter the window and notify the HistogramView that the window changed.
224 * @param newRelativeXPosition New absolute position.
226 public void setWindowCenterPosition(int newAbsoluteXPosition
) {
228 // We will check if the coordinate the same
229 if ( newAbsoluteXPosition
!= currentWindow
.getWindowXPositionCenter() ) {
231 long timestampOfLeftPosition
= this.getHistogramContent().getClosestElementFromXPosition( newAbsoluteXPosition
).firstIntervalTimestamp
- currentWindow
.getWindowTimeWidth() / 2;
232 long timestampOfCenterPosition
= 0;
233 long timestampOfRightPosition
= 0;
235 // Let's do the border verifications
236 if ( timestampOfLeftPosition
< histogramContent
.getStartTime() ) {
238 timestampOfLeftPosition
= histogramContent
.getStartTime();
239 timestampOfCenterPosition
= timestampOfLeftPosition
+ currentWindow
.getWindowTimeWidth() / 2;
240 timestampOfRightPosition
= timestampOfLeftPosition
+ currentWindow
.getWindowTimeWidth();
244 timestampOfRightPosition
= this.getHistogramContent().getClosestElementFromXPosition( newAbsoluteXPosition
).firstIntervalTimestamp
+ currentWindow
.getWindowTimeWidth() / 2;
246 if ( timestampOfRightPosition
> histogramContent
.getEndTime() ) {
248 timestampOfRightPosition
= histogramContent
.getEndTime();
249 timestampOfCenterPosition
= timestampOfRightPosition
- currentWindow
.getWindowTimeWidth() / 2;
250 timestampOfLeftPosition
= timestampOfRightPosition
- currentWindow
.getWindowTimeWidth();
254 timestampOfCenterPosition
= this.getHistogramContent().getClosestElementFromXPosition( newAbsoluteXPosition
).firstIntervalTimestamp
;
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
);
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
) );
272 redrawAsynchronously();
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>
281 * Recenter the window and notify the HistogramView that the window changed.
283 * @param timestampOfCenterPosition New timestamp of center position.
285 public void setWindowCenterPosition(long timestampOfCenterPosition
) {
287 // We will check if the coordinate the same
288 if ( timestampOfCenterPosition
!= currentWindow
.getTimestampOfCenterPosition() ) {
290 long timestampOfLeft
= timestampOfCenterPosition
- currentWindow
.getWindowTimeWidth() / 2;
291 long timestampOfCenter
= 0;
292 long timestampOfRight
= 0;
294 int windowXPositionLeft
= histogramContent
.getClosestXPositionFromTimestamp(timestampOfLeft
);
295 int windowXPositionCenter
= 0;
296 int windowXPositionRight
= 0;
298 // Let's do the border verifications
299 if ( timestampOfLeft
< histogramContent
.getStartTime() ) {
301 timestampOfLeft
= histogramContent
.getStartTime();
302 timestampOfCenter
= timestampOfLeft
+ currentWindow
.getWindowTimeWidth() / 2;
303 timestampOfRight
= timestampOfLeft
+ currentWindow
.getWindowTimeWidth();
305 windowXPositionLeft
= histogramContent
.getClosestXPositionFromTimestamp(timestampOfLeft
);
306 windowXPositionCenter
= histogramContent
.getClosestXPositionFromTimestamp(timestampOfCenter
);
307 windowXPositionRight
= histogramContent
.getClosestXPositionFromTimestamp(timestampOfRight
);
311 timestampOfRight
= timestampOfCenterPosition
+ currentWindow
.getWindowTimeWidth() / 2;
312 windowXPositionRight
= histogramContent
.getClosestXPositionFromTimestamp(timestampOfRight
);
314 if ( windowXPositionRight
> histogramContent
.getEndTime() ) {
316 timestampOfRight
= histogramContent
.getEndTime();
317 timestampOfCenter
= timestampOfRight
- currentWindow
.getWindowTimeWidth() / 2;
318 timestampOfLeft
= timestampOfRight
- currentWindow
.getWindowTimeWidth();
320 windowXPositionLeft
= histogramContent
.getClosestXPositionFromTimestamp(timestampOfLeft
);
321 windowXPositionCenter
= histogramContent
.getClosestXPositionFromTimestamp(timestampOfCenter
);
322 windowXPositionRight
= histogramContent
.getClosestXPositionFromTimestamp(timestampOfRight
);
326 timestampOfCenter
= timestampOfCenterPosition
;
327 windowXPositionCenter
= histogramContent
.getClosestXPositionFromTimestamp(timestampOfCenter
);
333 // Firstly we will setup new left, right and center timestamps
334 currentWindow
.setTimestampOfLeftPosition( timestampOfLeft
);
335 currentWindow
.setTimestampOfCenterPosition( timestampOfCenter
);
336 currentWindow
.setTimestampOfRightPosition( timestampOfRight
);
338 // We will do the update in case of different center timestamp
339 if( windowXPositionCenter
!= currentWindow
.getWindowXPositionCenter() ) {
341 // After we will update coordonates using timestamps already recalculated
342 currentWindow
.setWindowXPositionLeft(windowXPositionLeft
);
343 currentWindow
.setWindowXPositionCenter(windowXPositionCenter
);
344 currentWindow
.setWindowXPositionRight(windowXPositionRight
);
346 redrawAsynchronously();
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.
356 * Set the new window size and notify the HistogramView that the window changed.
358 * @param newTime New absoulte time (in nanoseconds) to apply to the window.
360 public void resizeWindowByAbsoluteTime(long newTime
) {
361 if ( newTime
!= getSelectedWindowSize() ) {
363 resizeWindowByAbsoluteTimeWithoutNotification(newTime
);
365 notifyParentSelectionWindowChangedAsynchronously();
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.
373 * Set the new window size and notify the HistogramView that the window changed.
375 * @param newTime New absoulte time (in nanoseconds) to apply to the window.
377 public void resizeWindowByAbsoluteTimeWithoutNotification(long newTime
) {
379 // We will change the size in case of delta (newTime) != 0
382 if(newTime
> getHistogramContent().getEndTime() - getHistogramContent().getStartTime()) {
383 newTime
= getHistogramContent().getEndTime() - getHistogramContent().getStartTime();
386 setSelectedWindowSize(newTime
);
389 // Yuriy: we can't use this function because we change the left and right coordinates.
390 setWindowCenterPosition(currentWindow.getWindowXPositionCenter());
393 long timestampOfLeftPosition
= currentWindow
.getTimestampOfCenterPosition() - currentWindow
.getWindowTimeWidth() / 2;
394 long timestampOfCenterPosition
= currentWindow
.getTimestampOfCenterPosition();
395 long timestampOfRightPosition
= 0;
397 // Let's do the border verifications
398 if ( timestampOfLeftPosition
< histogramContent
.getStartTime() ) {
400 timestampOfLeftPosition
= histogramContent
.getStartTime();
401 timestampOfCenterPosition
= timestampOfLeftPosition
+ currentWindow
.getWindowTimeWidth() / 2;
402 timestampOfRightPosition
= timestampOfLeftPosition
+ currentWindow
.getWindowTimeWidth();
406 timestampOfRightPosition
= currentWindow
.getTimestampOfCenterPosition() + currentWindow
.getWindowTimeWidth() / 2;
408 if ( timestampOfRightPosition
> histogramContent
.getEndTime() ) {
410 timestampOfRightPosition
= histogramContent
.getEndTime();
411 timestampOfCenterPosition
= timestampOfRightPosition
- currentWindow
.getWindowTimeWidth() / 2;
412 timestampOfLeftPosition
= timestampOfRightPosition
- currentWindow
.getWindowTimeWidth();
418 // Firstly we will setup new left, right and center timestamps
419 currentWindow
.setTimestampOfLeftPosition( timestampOfLeftPosition
);
420 currentWindow
.setTimestampOfCenterPosition( timestampOfCenterPosition
);
421 currentWindow
.setTimestampOfRightPosition( timestampOfRightPosition
);
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
) );
428 redrawAsynchronously();
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.
437 public void notifyParentUpdatedInformation() {
438 getHistogramView().updateFullExperimentInformation();
442 * Notify the parent HistogramView that the SelectionWindow changed.<p>
443 * This is intended to be called when the window move or is resized.
445 public void notifyParentSelectionWindowChanged() {
446 // Notify the parent view that something changed
447 getHistogramView().windowChangedNotification();
448 // Send a broadcast to the framework about the window change
449 getHistogramView().sendTmfRangeSynchSignalBroadcast();
453 * Method to call the "Asynchronous NotifyParentSelectionWindowChanged" for this canvas<p>
454 * This allow safe update UI objects from different threads.
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);
463 asynchronousNotifyParentSelectionWindowChanged();
467 * Function to asynchonously notify the parent of the related canvas that the window changed.<p>
469 * Basically, it just run "notifyParentSelectionWindowChanged()" in asyncExec.
472 public void asynchronousNotifyParentSelectionWindowChanged() {
473 // Ignore update if widget is disposed
474 if (this.isDisposed()) return;
476 Display display
= this.getDisplay();
477 display
.asyncExec(new Runnable() {
480 if(!ParentHistogramCanvas
.this.isDisposed())
481 notifyParentSelectionWindowChanged();