2010-11-09 Francois Chouinard <fchouinard@gmail.com> Contribution for Bug315307
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng.ui / src / org / eclipse / linuxtools / lttng / ui / views / histogram / HistogramView.java
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
11 *
12 * Modifications:
13 * 2010-06-10 Yuriy Vashchuk - GUI reorganisation, simplification and some
14 * related code improvements.
15 * 2010-06-20 Yuriy Vashchuk - Histograms optimisation.
16 * 2010-07-16 Yuriy Vashchuk - Histogram Canvas Heritage correction
17 *******************************************************************************/
18
19 package org.eclipse.linuxtools.lttng.ui.views.histogram;
20
21 import org.eclipse.linuxtools.lttng.event.LttngEvent;
22 import org.eclipse.linuxtools.lttng.event.LttngTimestamp;
23 import org.eclipse.linuxtools.tmf.event.TmfTimeRange;
24 import org.eclipse.linuxtools.tmf.event.TmfTimestamp;
25 import org.eclipse.linuxtools.tmf.experiment.TmfExperiment;
26 import org.eclipse.linuxtools.tmf.request.ITmfDataRequest;
27 import org.eclipse.linuxtools.tmf.request.ITmfDataRequest.ExecutionType;
28 import org.eclipse.linuxtools.tmf.signal.TmfExperimentSelectedSignal;
29 import org.eclipse.linuxtools.tmf.signal.TmfRangeSynchSignal;
30 import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler;
31 import org.eclipse.linuxtools.tmf.signal.TmfTimeSynchSignal;
32 import org.eclipse.linuxtools.tmf.trace.ITmfTrace;
33 import org.eclipse.linuxtools.tmf.ui.views.TmfView;
34 import org.eclipse.swt.SWT;
35 import org.eclipse.swt.events.ControlEvent;
36 import org.eclipse.swt.events.ControlListener;
37 import org.eclipse.swt.graphics.Font;
38 import org.eclipse.swt.graphics.FontData;
39 import org.eclipse.swt.layout.GridData;
40 import org.eclipse.swt.layout.GridLayout;
41 import org.eclipse.swt.widgets.Composite;
42 import org.eclipse.swt.widgets.Text;
43
44 /**
45 * <b><u>HistogramView</u></b>
46 * <p>
47 * View that contain an visual approach to the window that control the request.
48 * This is intended to replace the TimeFrameView
49 * <p>
50 * This view is composed of 2 canvas, one for the whole experiment and one for the selected window in the experiment.
51 * It also contain a certain number of controls to print or change informations about the experiment.
52 */
53 public class HistogramView extends TmfView implements ControlListener {
54
55 // *** TODO ***
56 // Here is what's left to do in this view
57 //
58 // 1- Make sure the interval time is small enough on very big trace (bug 311930)
59 // The interval time of the content is dynamically assigned from the screen width and trace duration.
60 // However, on very big trace (more than 1 hour), we could end up with time interval that are > 1 seconds,
61 // which is not very precise.
62 // An algorithm need to be implemented to make sure we "increase" the number of interval in the content if
63 // their precision is getting too bad.
64 //
65 // 2- Make sure all control are thread safe (bug 309348)
66 // Right now, all the basic controls (i.e. Text and Label) are sensible to "Thread Access Exception" if
67 // updated from different threads; we need to carefully decide when/where to redraw them.
68 // This is a real problem since there is a lot of thread going on in this view.
69 // All basic control should be subclassed to offer "Asynchronous" functions.
70 //
71 // 3- Implement a "preferences view" for the HistogramView (bug 311935)
72 // There is a lot of adjustable preferences in the view, however there is no way to adjust them right now
73 // at run time. There should be a view of some kind of "menu" to allow the user to change them while executing.
74 // Most of the pertinent values are in HistogramConstant.java or in this file.
75
76 public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.histogram"; //$NON-NLS-1$
77
78 // "Minimum" screen width size. On smaller screen, we will apply several space saving technique
79 private static final int SCREEN_SMALL_IF_SMALLER_THAN = 1600;
80
81 /*
82 // 2010-06-20 Yuriy: We will use the dynamic height.
83 // Size of the "full trace" canvas
84 private static final int FULL_TRACE_CANVAS_HEIGHT = 25;
85 */
86 private static final int FULL_TRACE_BAR_WIDTH = 1;
87 private static final double FULL_TRACE_DIFFERENCE_TO_AVERAGE = 1.5;
88
89 // Size of the "Selected Window" canvas
90 /*
91 // 2010-06-20 Yuriy
92 private static final int SELECTED_WINDOW_CANVAS_WIDTH = 300;
93 private static final int SMALL_SELECTED_WINDOW_CANVAS_WIDTH = 200;
94 private static final int SELECTED_WINDOW_CANVAS_HEIGHT = 60;
95 */
96 private static final int SELECTED_WINDOW_BAR_WIDTH = 1;
97 private static final double SELECTED_WINDOW_DIFFERENCE_TO_AVERAGE = 10.0;
98
99 // For the two "events" label (Max and Min number of events in the selection), we force a width
100 // This will prevent the control from moving horizontally if the number of events in the selection varies
101 private static final int NB_EVENTS_FIXED_WIDTH = 50;
102
103 // The "small font" height used to display time will be "default font" minus this constant
104 private static final int SMALL_FONT_MODIFIER = 2;
105 private static final int VERY_SMALL_FONT_MODIFIER = 4;
106
107 // *** TODO ***
108 // This need to be changed as soon the framework implement a "window"
109 // private static long DEFAULT_WINDOW_SIZE = (10L * 100 * 1000 * 1000); // 1sec
110 private static long DEFAULT_WINDOW_SIZE = (1L * 100 * 1000 * 1000); // .1sec
111
112 // The last experiment received/used by the view
113 private TmfExperiment<LttngEvent> lastUsedExperiment = null;
114
115 // Parent of the view
116 private Composite parent = null;
117
118 // Request and canvas for the "full trace" part
119 private HistogramRequest dataBackgroundFullRequest = null;
120 private static ParentHistogramCanvas fullExperimentCanvas = null;
121
122 // Request and canvas for the "selected window"
123 private HistogramRequest selectedWindowRequest = null;
124 private static ChildrenHistogramCanvas selectedWindowCanvas = null;
125
126 // Content of the timeTextGroup
127 // Since the user can modify them with erroneous value,
128 // we will keep track of the value internally
129 private long currentEventTime = 0L;
130
131 // *** All the UI control below
132 //
133 // NOTE : All textboxes will be READ_ONLY.
134 // So the user will be able to select/copy the value in them but not to change it
135 private Text txtExperimentStartTime = null;
136 private Text txtExperimentStopTime = null;
137
138 private Text txtWindowStartTime = null;
139 private Text txtWindowStopTime = null;
140 private Text txtWindowMaxNbEvents = null;
141 private Text txtWindowMinNbEvents = null;
142
143 // We move the time label to header from TimeTextGroup.java
144 private static final String WINDOW_TIMESPAN_LABEL_TEXT = Messages.HistogramView_windowSpanLabel;
145 private static final String WINDOW_CENTER_TIME_LABEL_TEXT = Messages.HistogramView_windowCenterLabel;
146 private static final String CURRENT_EVENT_TIME_LABEL_TEXT = Messages.HistogramView_currentEventLabel;
147 private TimeTextGroup ntgWindowTimeSpan = null;
148 private TimeTextGroup ntgWindowCenterTime = null;
149 private TimeTextGroup ntgCurrentEventTime = null;
150
151 /**
152 * Default constructor of the view
153 */
154 public HistogramView() {
155 super(ID);
156 }
157
158 /**
159 * Create the UI controls of this view
160 *
161 * @param parent The composite parent of this view
162 */
163 @Override
164 public void createPartControl(Composite newParent) {
165 // Save the parent
166 parent = newParent;
167
168 // Default font
169 Font font = parent.getFont();
170 FontData tmpFontData = font.getFontData()[0];
171
172
173 Font smallFont = null;
174 int nbEventWidth = -1;
175 int selectedCanvasWidth = -1;
176 boolean doesTimeTextGroupNeedAdjustment = false;
177
178 // Calculate if we need "small screen" fixes
179 if ( parent.getDisplay().getBounds().width < SCREEN_SMALL_IF_SMALLER_THAN ) {
180
181 // A lot smaller font for timestamp
182 smallFont = new Font(font.getDevice(), tmpFontData.getName(), tmpFontData.getHeight() - VERY_SMALL_FONT_MODIFIER, tmpFontData.getStyle());
183
184 /*
185 // 2010-06-20 Yuriy
186 // Smaller selection window canvas
187 selectedCanvasWidth = SMALL_SELECTED_WINDOW_CANVAS_WIDTH;
188 */
189 // Smaller event number text field
190 nbEventWidth = NB_EVENTS_FIXED_WIDTH/2;
191
192 // Tell the text group to ajust
193 doesTimeTextGroupNeedAdjustment = true;
194
195 } else {
196
197 // Slightly smaller font for timestamp
198 smallFont = new Font(font.getDevice(), tmpFontData.getName(), tmpFontData.getHeight() - SMALL_FONT_MODIFIER, tmpFontData.getStyle());
199 // Usual size for selected window and event number text field
200 nbEventWidth = NB_EVENTS_FIXED_WIDTH;
201 /*
202 // 2010-06-20 Yuriy
203 selectedCanvasWidth = SELECTED_WINDOW_CANVAS_WIDTH;
204 */
205 // No ajustement needed by the text group
206 doesTimeTextGroupNeedAdjustment = false;
207
208 }
209
210
211 /////////////////////////////////////////////////////////////////////////////////////
212 // Layout for the whole view, other elements will be in a child composite of this one
213 // Contains :
214 // Composite layoutSelectionWindow
215 // Composite layoutTimesSpinner
216 // Composite layoutExperimentHistogram
217 /////////////////////////////////////////////////////////////////////////////////////
218 Composite layoutFullView = new Composite(parent, SWT.FILL);
219 GridLayout gridFullView = new GridLayout();
220 gridFullView.numColumns = 2;
221 gridFullView.horizontalSpacing = 0;
222 gridFullView.verticalSpacing = 0;
223 gridFullView.marginHeight = 0;
224 gridFullView.marginWidth = 0;
225 layoutFullView.setLayout(gridFullView);
226
227
228 /////////////////////////////////////////////////////////////////////////////////////
229 // Layout that contain the time spinners
230 // Contains :
231 // NanosecTextGroup ntgCurrentEventTime
232 // NanosecTextGroup ntgTimeRangeWindow
233 // NanosecTextGroup ntgCurrentWindowTime
234 /////////////////////////////////////////////////////////////////////////////////////
235 Composite layoutTimeSpinners = new Composite(layoutFullView, SWT.NONE);
236 GridLayout gridTimesSpinner = new GridLayout();
237 gridTimesSpinner.numColumns = 3;
238 gridTimesSpinner.marginHeight = 0;
239 gridTimesSpinner.marginWidth = 0;
240 gridTimesSpinner.horizontalSpacing = 5;
241 gridTimesSpinner.verticalSpacing = 0;
242 gridTimesSpinner.makeColumnsEqualWidth = true;
243 gridTimesSpinner.marginLeft = 5;
244 gridTimesSpinner.marginRight = 5;
245 layoutTimeSpinners.setLayout(gridTimesSpinner);
246
247 GridData gridDataCurrentEvent = new GridData();
248 gridDataCurrentEvent.horizontalAlignment = SWT.LEFT;
249 gridDataCurrentEvent.verticalAlignment = SWT.CENTER;
250 ntgCurrentEventTime = new TimeTextGroup(this, layoutTimeSpinners, SWT.BORDER, SWT.BORDER, CURRENT_EVENT_TIME_LABEL_TEXT, HistogramConstant.formatNanoSecondsTime(0L), doesTimeTextGroupNeedAdjustment);
251 ntgCurrentEventTime.setLayoutData(gridDataCurrentEvent);
252
253 GridData gridDataTimeSpan = new GridData();
254 gridDataTimeSpan.horizontalAlignment = SWT.CENTER;
255 gridDataTimeSpan.verticalAlignment = SWT.CENTER;
256 ntgWindowTimeSpan = new TimeTextGroup(this, layoutTimeSpinners, SWT.BORDER, SWT.BORDER, WINDOW_TIMESPAN_LABEL_TEXT, HistogramConstant.formatNanoSecondsTime(0L), doesTimeTextGroupNeedAdjustment);
257 ntgWindowTimeSpan.setLayoutData(gridDataTimeSpan);
258
259 GridData gridDataWindowCenter = new GridData();
260 gridDataWindowCenter.horizontalAlignment = SWT.RIGHT;
261 gridDataWindowCenter.verticalAlignment = SWT.CENTER;
262 ntgWindowCenterTime = new TimeTextGroup(this, layoutTimeSpinners, SWT.BORDER, SWT.BORDER, WINDOW_CENTER_TIME_LABEL_TEXT, HistogramConstant.formatNanoSecondsTime(0L), doesTimeTextGroupNeedAdjustment);
263 ntgWindowCenterTime.setLayoutData(gridDataWindowCenter);
264
265
266 /////////////////////////////////////////////////////////////////////////////////////
267 // Layout that contain the SelectionWindow
268 // Contains :
269 // Label txtWindowStartTime
270 // Label txtWindowStopTime
271 // Label txtWindowMaxNbEvents
272 // Label txtWindowMinNbEvents
273 // ChildrenHistogramCanvas selectedWindowCanvas
274 /////////////////////////////////////////////////////////////////////////////////////
275 Composite layoutSelectionWindow = new Composite(layoutFullView, SWT.FILL);
276 GridLayout gridSelectionWindow = new GridLayout();
277 gridSelectionWindow.numColumns = 3;
278 gridSelectionWindow.marginHeight = 0;
279 gridSelectionWindow.marginWidth = 2;
280 gridSelectionWindow.marginTop = 5;
281 gridSelectionWindow.horizontalSpacing = 0;
282 gridSelectionWindow.verticalSpacing = 0;
283 layoutSelectionWindow.setLayout(gridSelectionWindow);
284
285 GridData gridDataSelectionWindow = new GridData();
286 gridDataSelectionWindow.horizontalAlignment = SWT.FILL;
287 gridDataSelectionWindow.verticalAlignment = SWT.FILL;
288 layoutSelectionWindow.setLayoutData(gridDataSelectionWindow);
289
290 GridData gridDataSelectionWindowCanvas = new GridData();
291 gridDataSelectionWindowCanvas.horizontalSpan = 2;
292 gridDataSelectionWindowCanvas.verticalSpan = 2;
293 gridDataSelectionWindowCanvas.horizontalAlignment = SWT.FILL;
294 gridDataSelectionWindowCanvas.grabExcessHorizontalSpace = true;
295 gridDataSelectionWindowCanvas.verticalAlignment = SWT.FILL;
296 /*
297 // 2010-06-20 Yuriy
298 gridDataSelectionWindowCanvas.heightHint = SELECTED_WINDOW_CANVAS_HEIGHT;
299 gridDataSelectionWindowCanvas.minimumHeight = SELECTED_WINDOW_CANVAS_HEIGHT;
300 */
301 gridDataSelectionWindowCanvas.widthHint = selectedCanvasWidth;
302 gridDataSelectionWindowCanvas.minimumWidth = selectedCanvasWidth;
303 selectedWindowCanvas = new ChildrenHistogramCanvas(this, layoutSelectionWindow, SWT.BORDER);
304 selectedWindowCanvas.setLayoutData(gridDataSelectionWindowCanvas);
305
306 GridData gridDataWindowMaxEvents = new GridData();
307 gridDataWindowMaxEvents.horizontalAlignment = SWT.RIGHT;
308 gridDataWindowMaxEvents.verticalAlignment = SWT.TOP;
309 // Force a width, to avoid the control to enlarge if the number of events change
310 gridDataWindowMaxEvents.minimumWidth = nbEventWidth;
311 txtWindowMaxNbEvents = new Text(layoutSelectionWindow, SWT.READ_ONLY);
312 txtWindowMaxNbEvents.setFont(smallFont);
313 txtWindowMaxNbEvents.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
314 txtWindowMaxNbEvents.setEditable(false);
315 txtWindowMaxNbEvents.setText("0"); //$NON-NLS-1$
316 txtWindowMaxNbEvents.setLayoutData(gridDataWindowMaxEvents);
317
318 GridData gridDataWindowMinEvents = new GridData();
319 gridDataWindowMinEvents.horizontalAlignment = SWT.RIGHT;
320 gridDataWindowMinEvents.verticalAlignment = SWT.BOTTOM;
321 // Force a width, to avoid the control to enlarge if the number of events change
322 gridDataWindowMinEvents.minimumWidth = nbEventWidth;
323 txtWindowMinNbEvents = new Text(layoutSelectionWindow, SWT.READ_ONLY);
324 txtWindowMinNbEvents.setFont(smallFont);
325 txtWindowMinNbEvents.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
326 txtWindowMinNbEvents.setEditable(false);
327 txtWindowMinNbEvents.setText("0"); //$NON-NLS-1$
328 txtWindowMinNbEvents.setLayoutData(gridDataWindowMinEvents);
329
330 GridData gridDataWindowStart = new GridData();
331 gridDataWindowStart.horizontalAlignment = SWT.LEFT;
332 gridDataWindowStart.verticalAlignment = SWT.BOTTOM;
333 txtWindowStartTime = new Text(layoutSelectionWindow, SWT.READ_ONLY);
334 txtWindowStartTime.setFont(smallFont);
335 txtWindowStartTime.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
336 txtWindowStartTime.setEditable(false);
337 txtWindowStartTime.setText("0.000000000"); //$NON-NLS-1$
338 txtWindowStartTime.setLayoutData(gridDataWindowStart);
339
340 GridData gridDataWindowStop = new GridData();
341 gridDataWindowStop.horizontalAlignment = SWT.RIGHT;
342 gridDataWindowStop.verticalAlignment = SWT.BOTTOM;
343 txtWindowStopTime = new Text(layoutSelectionWindow, SWT.READ_ONLY);
344 txtWindowStopTime.setFont(smallFont);
345 txtWindowStopTime.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
346 txtWindowStopTime.setEditable(false);
347 txtWindowStopTime.setText("0.000000000"); //$NON-NLS-1$
348 txtWindowStopTime.setLayoutData(gridDataWindowStop);
349
350
351 /*
352 // 2010-06-10 Yuriy: NOT NEEDED AFTER GUI IMPROVEMENTS. WORK FINE WITOUT THIS HACK
353 // *** HACK ***
354 // To align properly AND to make sure the canvas size is fixed, we NEED to make sure all "section" of the
355 // gridlayout are taken (and if possible of a fixed size).
356 // However, SWT is VERY VERY DUMB and won't consider griddata that contain no control.
357 // Since there will be missing a section, the SelectedWindowCanvas + NbEventsText will take 3 spaces, but
358 // startTimeText + stopTimeText will take only 2 (as if empty the other griddata of 1 will get ignored).
359 // StopTime will then take over the missing space; I want to align "stopTime" right on the end of canvas, so
360 // the added space to stop time would make it being aligned improperly
361 // So I NEED the empty griddata to be considered!
362 // Visually :
363 // |---------------|---------------|-----------|
364 // |SelectionCanvas SelectionCanvas|NbEventText|
365 // |SelectionCanvas SelectionCanvas|NbEventText|
366 // |---------------|---------------|-----------|
367 // |StartTime | StopTime| ??? |
368 // |---------------|---------------|-----------|
369 //
370 // So since SWT will only consider griddata with control,
371 // I need to create a totally useless control in the ??? section.
372 // That's ugly, useless and it is generally a bad practice.
373 //
374 // *** SUB-HACK ***
375 // Other interesting fact about SWT : the way it draws (Fill/Expand control in grid) will change if
376 // the control is a Text or a Label.
377 // A Label here will be "pushed" by startTime/stopTime Text and won't fill the full space as NbEventText.
378 // A Text here will NOT be "pushed" and would give a nice visual output.
379 // (NB : No, I am NOT kidding, try it for yourself!)
380 //
381 // Soooooo I guess I will use a Text here. Way to go SWT!
382 // Downside is that disabled textbox has a slightly different color (even if you force it yourself) so if I want
383 // to make the text "invisible", I have to keep it enabled (but read only), so it can be clicked on.
384 //
385 // Label uselessControlToByPassSWTStupidBug = new Label(layoutSelectionWindow, SWT.BORDER); // WON'T align correctly!!!
386 //GridData gridDataSpacer = new GridData(SWT.FILL, SWT.TOP, true, true, 1, 1);
387 GridData gridDataSpacer = new GridData();
388 gridDataWindowStop.horizontalAlignment = SWT.FILL;
389 gridDataWindowStop.verticalAlignment = SWT.TOP;
390 gridDataSpacer.minimumWidth = nbEventWidth;
391 Text uselessControlToByPassSWTStupidBug = new Text(layoutSelectionWindow, SWT.READ_ONLY); // WILL align correctly!!!
392 uselessControlToByPassSWTStupidBug.setEditable(false);
393 uselessControlToByPassSWTStupidBug.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
394 uselessControlToByPassSWTStupidBug.setLayoutData(gridDataSpacer);
395 */
396
397
398 /////////////////////////////////////////////////////////////////////////////////////
399 // Layout that contain the complete experiment histogram and related controls.
400 // Contains :
401 // ParentHistogramCanvas fullExperimentCanvas
402 // Text txtExperimentStartTime
403 // Text txtExperimentStopTime
404 /////////////////////////////////////////////////////////////////////////////////////
405 Composite layoutExperimentHistogram = new Composite(layoutFullView, SWT.FILL);
406
407 GridLayout gridExperimentHistogram = new GridLayout();
408 gridExperimentHistogram.numColumns = 2;
409 gridExperimentHistogram.marginHeight = 0;
410 gridExperimentHistogram.marginWidth = 0;
411 gridExperimentHistogram.horizontalSpacing = 0;
412 gridExperimentHistogram.verticalSpacing = 0;
413 gridExperimentHistogram.marginLeft = 5;
414 gridExperimentHistogram.marginRight = 5;
415 layoutExperimentHistogram.setLayout(gridExperimentHistogram);
416
417 /*
418 // 2010-06-10 Yuriy: NOT NEEDED AFTER GUI IMPROVEMENTS
419 GridData gridDataExperimentHistogram = new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1);
420 layoutExperimentHistogram.setLayoutData(gridDataExperimentHistogram);
421 */
422
423 // *** Everything related to the experiment canvas is below
424 GridData gridDataExperimentCanvas = new GridData();
425 gridDataExperimentCanvas.horizontalSpan = 2;
426 gridDataExperimentCanvas.horizontalAlignment = SWT.FILL;
427 gridDataExperimentCanvas.grabExcessHorizontalSpace = true;
428 gridDataExperimentCanvas.verticalAlignment = SWT.FILL;
429 gridDataExperimentCanvas.grabExcessVerticalSpace = true;
430 /*
431 // 2010-06-20 Yuriy: We use the dynamic height.
432 gridDataExperimentCanvas.heightHint = FULL_TRACE_CANVAS_HEIGHT;
433 gridDataExperimentCanvas.minimumHeight = FULL_TRACE_CANVAS_HEIGHT;
434 */
435 fullExperimentCanvas = new ParentHistogramCanvas(this, layoutExperimentHistogram, SWT.BORDER);
436 fullExperimentCanvas.setLayoutData(gridDataExperimentCanvas);
437 layoutExperimentHistogram.setLayoutData(gridDataExperimentCanvas);
438
439 GridData gridDataExperimentStart = new GridData();
440 gridDataExperimentStart.horizontalAlignment = SWT.LEFT;
441 gridDataExperimentStart.verticalAlignment = SWT.BOTTOM;
442 txtExperimentStartTime = new Text(layoutExperimentHistogram, SWT.READ_ONLY);
443 txtExperimentStartTime.setFont(smallFont);
444 txtExperimentStartTime.setText("0.000000000"); //$NON-NLS-1$
445 txtExperimentStartTime.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
446 txtExperimentStartTime.setEditable(false);
447 txtExperimentStartTime.setLayoutData(gridDataExperimentStart);
448
449 GridData gridDataExperimentStop = new GridData();
450 gridDataExperimentStop.horizontalAlignment = SWT.RIGHT;
451 gridDataExperimentStop.verticalAlignment = SWT.BOTTOM;
452 txtExperimentStopTime = new Text(layoutExperimentHistogram, SWT.READ_ONLY);
453 txtExperimentStopTime.setFont(smallFont);
454 txtExperimentStopTime.setText("0.000000000"); //$NON-NLS-1$
455 txtExperimentStopTime.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
456 txtExperimentStopTime.setEditable(false);
457 txtExperimentStopTime.setLayoutData(gridDataExperimentStop);
458 }
459
460 // *** FIXME ***
461 // This is mainly used because of a because in the "experimentSelected()" notification, we shouldn't need this
462 /**
463 * Method called when the view receive the focus.<p>
464 * If ExperimentSelected didn't send us a request yet, get the current Experiment and fire requests
465 */
466 @SuppressWarnings("unchecked")
467 @Override
468 public void setFocus() {
469 // WARNING : This does not seem to be thread safe
470 TmfExperiment<LttngEvent> tmpExperiment = (TmfExperiment<LttngEvent>)TmfExperiment.getCurrentExperiment();
471
472 if ( (dataBackgroundFullRequest == null) && (tmpExperiment != null) ) {
473 createCanvasAndRequests(tmpExperiment);
474 }
475
476 // Call a redraw for everything
477 parent.redraw();
478 }
479
480 /**
481 * Method called when the user select (double-click on) an experiment.<p>
482 * We will create the needed canvas and fire the requests.
483 *
484 * @param signal Signal received from the framework. Contain the experiment.
485 */
486 @SuppressWarnings("unchecked")
487 @TmfSignalHandler
488 public void experimentSelected(TmfExperimentSelectedSignal<LttngEvent> signal) {
489 TmfExperiment<LttngEvent> tmpExperiment = (TmfExperiment<LttngEvent>)signal.getExperiment();
490 createCanvasAndRequests(tmpExperiment);
491 }
492
493
494 // *** VERIFY ***
495 // Not sure what this should do since I don't know when it will be called
496 // Let's do the same thing as experimentSelected for now
497 //
498 /**
499 * Method called when an experiment is updated (??).<p>
500 * ...for now, do nothing, as udating an experiment running in the background might cause crash
501 *
502 * @param signal Signal received from the framework. Contain the experiment.
503 */
504 /*
505 @SuppressWarnings("unchecked")
506 @TmfSignalHandler
507 public void experimentUpdated(TmfExperimentUpdatedSignal signal) {
508
509 TmfExperiment<LttngEvent> tmpExperiment = (TmfExperiment<LttngEvent>)signal.getExperiment();
510
511 // Make sure the UI object are sane
512 resetControlsContent();
513
514 // Redraw the canvas right away to have something "clean" as soon as we can
515 fullExperimentCanvas.redraw();
516 selectedWindowCanvas.redraw();
517
518 // Recreate the request
519 createCanvasAndRequests(tmpExperiment);
520 }
521 */
522
523 /**
524 * Method called when synchronization is active and that the user select an event.
525 * We update the current event timeTextGroup and move the selected window if needed.
526 *
527 * @param signal Signal received from the framework. Contain the event.
528 */
529 @TmfSignalHandler
530 public void currentTimeUpdated(TmfTimeSynchSignal signal) {
531 // In case we received our own signal
532 if ( (signal != null) && (signal.getSource() != this) ) {
533 TmfTimestamp currentTime = signal.getCurrentTime();
534
535 // Update the current event controls
536 currentEventTime = currentTime.getValue();
537 updateSelectedEventTime();
538
539 // If the given event is outside the selection window, recenter the window
540 if ( isGivenTimestampInSelectedWindow( currentEventTime ) == false) {
541 fullExperimentCanvas.setWindowCenterPosition( fullExperimentCanvas.getHistogramContent().getClosestXPositionFromTimestamp(currentEventTime) );
542 // Notify control that the window changed
543 windowChangedNotification();
544 // Send a broadcast to the framework about the window change
545 sendTmfRangeSynchSignalBroadcast();
546 }
547 }
548 }
549
550 @TmfSignalHandler
551 public void synchToTimeRange(TmfRangeSynchSignal signal) {
552 if ( (signal != null) ) {
553 if ( lastUsedExperiment != null ) {
554 long currentTime = signal.getCurrentTime().getValue();
555 long windowStart = signal.getCurrentRange().getStartTime().getValue();
556 long windowEnd = signal.getCurrentRange().getEndTime().getValue();
557 long windowTimeWidth = (windowEnd - windowStart);
558
559 // Recenter the window
560 fullExperimentCanvas.setSelectedWindowSize(windowTimeWidth);
561 fullExperimentCanvas.setWindowCenterPosition( fullExperimentCanvas.getHistogramContent().getClosestXPositionFromTimestamp(windowStart + (windowTimeWidth/2)) );
562
563 // *** HACK ***
564 // Views could send us incorrect current event value (event outside the current window)
565 // Here we make sure the value is sane, otherwise, we force it as the left border of the window
566 if ( isGivenTimestampInSelectedWindow( currentTime ) == false ) {
567 currentTime = windowStart;
568 }
569 currentEventTime = currentTime;
570
571 // Notify control that the window changed
572 windowChangedNotification();
573
574 // Make sure we redraw the change
575 fullExperimentCanvas.redraw();
576 }
577 }
578 }
579
580
581 /*
582 * Create the canvas needed and issue the requests
583 *
584 * @param newExperiment Experiment we will use for the request
585 */
586 private void createCanvasAndRequests(TmfExperiment<LttngEvent> newExperiment) {
587 // Save the experiment we are about to use
588 lastUsedExperiment = newExperiment;
589
590 // // Create a copy of the trace that will be use only by the full experiment request
591 // TmfExperiment<LttngEvent> experimentCopy = newExperiment.createTraceCopy();
592
593 // Create the content for the full experiment.
594 // This NEED to be created first, as we use it in the selectedWindowCanvas
595 fullExperimentCanvas.createNewHistogramContent(
596 fullExperimentCanvas.getSize().x,
597 FULL_TRACE_BAR_WIDTH,
598 /*
599 // 2010-06-20 Yuriy: We will use the dynamic height.
600 FULL_TRACE_CANVAS_HEIGHT
601 */
602 fullExperimentCanvas.getSize().y / 2,
603 FULL_TRACE_DIFFERENCE_TO_AVERAGE
604 );
605
606 TmfTimeRange timeRange = getExperimentTimeRange(newExperiment);
607
608 // We will take the half of the full experiment length in case of bigger window size than the full experiment length
609 if(timeRange.getEndTime().getValue() - timeRange.getStartTime().getValue() > DEFAULT_WINDOW_SIZE ) {
610 fullExperimentCanvas.createNewSelectedWindow(
611 timeRange.getStartTime().getValue(),
612 DEFAULT_WINDOW_SIZE
613 );
614 } else {
615 fullExperimentCanvas.createNewSelectedWindow(
616 timeRange.getStartTime().getValue(),
617 (timeRange.getEndTime().getValue() - timeRange.getStartTime().getValue() ) / 2
618 );
619 }
620
621 currentEventTime = timeRange.getStartTime().getValue();
622
623 // Set the window of the fullTrace canvas visible.
624 fullExperimentCanvas.getCurrentWindow().setSelectedWindowVisible(true);
625 fullExperimentCanvas.getHistogramContent().resetTable(timeRange.getStartTime().getValue(), timeRange.getEndTime().getValue());
626
627 // Create the content for the selected window.
628 selectedWindowCanvas.createNewHistogramContent(
629 selectedWindowCanvas.getSize().x,
630 SELECTED_WINDOW_BAR_WIDTH,
631 selectedWindowCanvas.getSize().y,
632 SELECTED_WINDOW_DIFFERENCE_TO_AVERAGE
633 );
634 selectedWindowCanvas.getHistogramContent().resetTable(fullExperimentCanvas.getCurrentWindow().getTimestampOfLeftPosition(), fullExperimentCanvas.getCurrentWindow().getTimestampOfRightPosition());
635
636 // Make sure the UI object are sane
637 resetControlsContent();
638
639 // Redraw the canvas right away to have something "clean" as soon as we can
640 if ( dataBackgroundFullRequest != null ) {
641 fullExperimentCanvas.redraw();
642 selectedWindowCanvas.redraw();
643 }
644 // Nullify the (possible) old request to be sure we start we something clean
645 // Note : this is very important for the order of the request below,
646 // see "TODO" in performSelectedWindowEventsRequest
647 dataBackgroundFullRequest = null;
648 selectedWindowRequest = null;
649
650 // Perform both request.
651 // Order is important here, the small/synchronous request for the selection window should go first
652 performSelectedWindowEventsRequest(newExperiment);
653 performAllTraceEventsRequest(newExperiment);
654 }
655
656 // Before completing its indexing, the experiment doesn't know start/end time.
657 // However, LTTng individual traces have this knowledge so we should ask them
658 // directly.
659 private TmfTimeRange getExperimentTimeRange(TmfExperiment<LttngEvent> experiment) {
660 // Before completing its indexing, the experiment doesn't know start/end time.
661 // However, LTTng individual traces have this knowledge so we should ask them
662 // directly.
663 TmfTimestamp startTime = TmfTimestamp.BigCrunch;
664 TmfTimestamp endTime = TmfTimestamp.BigBang;
665 for (ITmfTrace trace : experiment.getTraces()) {
666 TmfTimestamp traceStartTime = trace.getStartTime();
667 if (traceStartTime.compareTo(startTime, true) < 0)
668 startTime = traceStartTime;
669 TmfTimestamp traceEndTime = trace.getEndTime();
670 if (traceEndTime.compareTo(endTime, true) > 0)
671 endTime = traceEndTime;
672 }
673 TmfTimeRange tmpRange = new TmfTimeRange(startTime, endTime);
674 return tmpRange;
675 }
676
677 /**
678 * Perform a new request for the Selection window.<p>
679 * This assume the full experiment canvas has correct information about the selected window;
680 * we need the fullExperimentCanvas' HistogramContent to be created and a selection window to be set.
681 *
682 * @param experiment The experiment we will select from
683 */
684 public void performSelectedWindowEventsRequest(TmfExperiment<LttngEvent> experiment) {
685
686 if(fullExperimentCanvas != null) {
687 HistogramSelectedWindow curSelectedWindow = fullExperimentCanvas.getCurrentWindow();
688
689 TmfTimeRange timeRange = getExperimentTimeRange(experiment);
690
691 // If no selection window exists, we will try to create one;
692 // however this will most likely fail as the content is probably not created either
693 if ( curSelectedWindow == null ) {
694 // We will take the half of the full experiment length in case of bigger window size than the full experiment length
695 if(timeRange.getEndTime().getValue() - timeRange.getStartTime().getValue() > DEFAULT_WINDOW_SIZE ) {
696 fullExperimentCanvas.createNewSelectedWindow(
697 timeRange.getStartTime().getValue(),
698 DEFAULT_WINDOW_SIZE
699 );
700 } else {
701 fullExperimentCanvas.createNewSelectedWindow(
702 timeRange.getStartTime().getValue(),
703 (timeRange.getEndTime().getValue() - timeRange.getStartTime().getValue() ) / 2
704 );
705 }
706 curSelectedWindow = fullExperimentCanvas.getCurrentWindow();
707 }
708
709 // The request will go from the Left timestamp of the window to the Right timestamp
710 // This assume that out-of-bound value are handled by the SelectionWindow itself
711 LttngTimestamp ts1 = new LttngTimestamp( curSelectedWindow.getTimestampOfLeftPosition() );
712 LttngTimestamp ts2 = new LttngTimestamp( curSelectedWindow.getTimestampOfRightPosition() );
713 TmfTimeRange tmpRange = new TmfTimeRange(ts1, ts2);
714
715 // Set a (dynamic) time interval
716 long intervalTime = ( (ts2.getValue() - ts1.getValue()) / selectedWindowCanvas.getHistogramContent().getNbElement() );
717
718 selectedWindowRequest = performRequest(experiment, selectedWindowCanvas, tmpRange, intervalTime, ExecutionType.FOREGROUND);
719 selectedWindowCanvas.redrawAsynchronously();
720 }
721
722 }
723
724 /**
725 * Perform a new request for the full experiment.<p>
726 * NOTE : this is very long, we need to implement a way to run this in parallel (see TODO)
727 *
728 * @param experiment The experiment we will select from
729 */
730 public void performAllTraceEventsRequest(TmfExperiment<LttngEvent> experiment) {
731 // Create a new time range from "start" to "end"
732 // That way, we will get "everything" in the trace
733 // LttngTimestamp ts1 = new LttngTimestamp( experiment.getStartTime() );
734 // LttngTimestamp ts2 = new LttngTimestamp( experiment.getEndTime() );
735 // TmfTimeRange tmpRange = new TmfTimeRange(ts1, ts2);
736
737 TmfTimeRange tmpRange = getExperimentTimeRange(experiment);
738 TmfTimestamp startTime = tmpRange.getStartTime();
739 TmfTimestamp endTime = tmpRange.getEndTime();
740
741 // Set a (dynamic) time interval
742 long intervalTime = ( (endTime.getValue() - startTime.getValue()) / fullExperimentCanvas.getHistogramContent().getNbElement() );
743
744 // *** VERIFY ***
745 // This would enable "fixed interval" instead of dynamic one.
746 // ... we don't need it, do we?
747 //
748 // long intervalTime = ((long)(0.001 * (double)1000000000));
749
750 // *** TODO ***
751 // It would be interesting if there was a way to tell the framework to run the request "in parallel" here.
752 // Mean a completetly independant copy of the Expereiment would be done and we would proceed on that.
753 //
754 dataBackgroundFullRequest = performRequest(experiment, fullExperimentCanvas, tmpRange, intervalTime, ExecutionType.BACKGROUND);
755
756
757 fullExperimentCanvas.getCurrentWindow().setWindowXPositionLeft(fullExperimentCanvas.getHistogramContent().getClosestXPositionFromTimestamp(fullExperimentCanvas.getCurrentWindow().getTimestampOfLeftPosition()));
758 fullExperimentCanvas.getCurrentWindow().setWindowXPositionCenter(fullExperimentCanvas.getHistogramContent().getClosestXPositionFromTimestamp(fullExperimentCanvas.getCurrentWindow().getTimestampOfCenterPosition()));
759 fullExperimentCanvas.getCurrentWindow().setWindowXPositionRight(fullExperimentCanvas.getHistogramContent().getClosestXPositionFromTimestamp(fullExperimentCanvas.getCurrentWindow().getTimestampOfRightPosition()));
760
761 fullExperimentCanvas.redrawAsynchronously();
762 }
763
764 // *** VERIFY ***
765 // This function is synchronized, is it a good idea?
766 // Tis is done to make sure requests arrive somewhat in order,
767 // this is especially important when request are issued from different thread.
768 /**
769 * Create a new request from the given data and send it to the framework.<p>
770 * The request will be queued and processed later.
771 *
772 * @param experiment The experiment we will process the request on
773 * @param targetCanvas The canvas that will received the result
774 * @param newRange The range of the request
775 * @param newInterval The interval of time we use to store the result into the HistogramContent
776 */
777 private synchronized HistogramRequest performRequest(TmfExperiment<LttngEvent> experiment, HistogramCanvas targetCanvas, TmfTimeRange newRange, long newInterval, ITmfDataRequest.ExecutionType execType) {
778 HistogramRequest returnedRequest = null;
779
780 // *** FIXME ***
781 // EVIL BUG!
782 // We use int.MAX_VALUE because we want every events BUT we don't know the number inside the range.
783 // HOWEVER, this would cause the request to run forever (or until it reach the end of trace).
784 // Seeting an EndTime does not seems to stop the request
785 returnedRequest = new HistogramRequest(newRange, Integer.MAX_VALUE, targetCanvas, newInterval, execType );
786
787 // Send the request to the framework : it will be queued and processed later
788 experiment.sendRequest(returnedRequest);
789
790 return returnedRequest;
791 }
792
793 /**
794 * Function used to warn that the selection window changed.<p>
795 * This might be called because the window moved or because its size changed.<p>
796 *
797 * We will update the different control related to the selection window.
798 */
799 public void windowChangedNotification() {
800
801 if ( lastUsedExperiment != null ) {
802 // If a request is ongoing, try to stop it
803 if (selectedWindowRequest != null && !selectedWindowRequest.isCompleted()) {
804 selectedWindowRequest.cancel();
805 }
806
807 if(fullExperimentCanvas != null) {
808 // If the current event time is outside the new window, change the current event
809 // The new current event will be the one closest to the LEFT side of the new window
810 if ( isGivenTimestampInSelectedWindow(currentEventTime) == false ) {
811 currentEventChangeNotification( fullExperimentCanvas.getCurrentWindow().getTimestampOfLeftPosition() );
812 }
813 }
814
815 // Perform a new request to read data about the new window
816 performSelectedWindowEventsRequest(lastUsedExperiment);
817 }
818 }
819
820 /**
821 * Function used to tell that the current event changed.<p>
822 * This might be called because the user changed the current event or
823 * because the last current event is now outside the selection window.<p>
824 *
825 * We update the related control and send a signal to notify other views of the new current event.
826 *
827 * @param newCurrentEventTime
828 */
829 public void currentEventChangeNotification(long newCurrentEventTime) {
830
831 // Notify other views in the framework
832 if (currentEventTime != newCurrentEventTime) {
833 currentEventTime = newCurrentEventTime;
834
835 // Update the UI control
836 updateSelectedEventTime();
837 }
838 }
839
840 public void sendTmfTimeSynchSignalBroadcast() {
841
842 // System.out.println("sendTmfTimeSynchSignalBroadcast " + System.currentTimeMillis());
843
844 // Send a signal to the framework
845 LttngTimestamp tmpTimestamp = new LttngTimestamp(currentEventTime);
846 broadcast(new TmfTimeSynchSignal(this, tmpTimestamp));
847 }
848
849 /**
850 * Function used to tell that the timerange (window) changed.<p>
851 * This will most likely be called if the time window is resized.
852 *
853 * We send a signal to notify other views of the new timerange.
854 */
855 public void sendTmfRangeSynchSignalBroadcast() {
856
857 if (TmfExperiment.getCurrentExperiment() == null)
858 return;
859
860 long startTime = fullExperimentCanvas.getCurrentWindow().getTimestampOfLeftPosition();
861 if ( startTime < fullExperimentCanvas.getHistogramContent().getStartTime() ) {
862 startTime = fullExperimentCanvas.getHistogramContent().getStartTime();
863 }
864 LttngTimestamp tmpStartTime = new LttngTimestamp(startTime);
865
866 long endTime = fullExperimentCanvas.getCurrentWindow().getTimestampOfRightPosition();
867 if ( endTime > fullExperimentCanvas.getHistogramContent().getEndTime() ) {
868 endTime = fullExperimentCanvas.getHistogramContent().getEndTime();
869 }
870 LttngTimestamp tmpEndTime = new LttngTimestamp(endTime);
871
872 TmfTimeRange tmpTimeRange = new TmfTimeRange(tmpStartTime, tmpEndTime);
873 LttngTimestamp tmpEventTime = new LttngTimestamp(currentEventTime);
874
875 // Send a signal to the framework
876 broadcast(new TmfRangeSynchSignal(this, tmpTimeRange, tmpEventTime));
877 }
878
879 /**
880 * Function that will be called when one of the time text group value is changed.<p>
881 * Since we don't (and can't unless we subclass them) know which one, we check them all.
882 */
883 public void timeTextGroupChangeNotification() {
884
885 if(ntgCurrentEventTime != null) {
886 // If the user changed the current event time, call the notification
887 long newCurrentTime = ntgCurrentEventTime.getValue();
888 if ( newCurrentTime != currentEventTime ) {
889 currentEventChangeNotification( newCurrentTime );
890 // Send a broadcast to the framework about the window change
891 sendTmfTimeSynchSignalBroadcast();
892 }
893 }
894
895 if(ntgWindowCenterTime != null && fullExperimentCanvas != null) {
896 // If the user changed the selected window time, recenter the window and call the notification
897 long newSelectedWindowTime = ntgWindowCenterTime.getValue();
898 if ( newSelectedWindowTime != fullExperimentCanvas.getCurrentWindow().getTimestampOfCenterPosition() ) {
899 fullExperimentCanvas.setWindowCenterPosition(newSelectedWindowTime);
900 // Send a broadcast to the framework about the window change
901 sendTmfRangeSynchSignalBroadcast();
902 }
903 }
904
905 if(ntgWindowTimeSpan != null && fullExperimentCanvas != null) {
906 // If the user changed the selected window size, resize the window and call the notification
907 long newSelectedWindowTimeRange = ntgWindowTimeSpan.getValue();
908 if ( newSelectedWindowTimeRange != fullExperimentCanvas.getCurrentWindow().getWindowTimeWidth() ) {
909 fullExperimentCanvas.resizeWindowByAbsoluteTime(newSelectedWindowTimeRange);
910 // Send a broadcast to the framework about the window change
911 sendTmfRangeSynchSignalBroadcast();
912 }
913 }
914
915 }
916
917 /**
918 * Getter for the last used experiment.<p>
919 * This might be different than the current experiment or even null.
920 *
921 * @return the last experiment we used in this view
922 */
923 public TmfExperiment<LttngEvent> getLastUsedExperiment() {
924 return lastUsedExperiment;
925 }
926
927 /**
928 * Check if a given timestamp is inside the selection window.<p>
929 * This assume fullExperimentCanvas contain a valid HistogramContent
930 *
931 * @param timestamp the timestamp to check
932 *
933 * @return if the time is inside the selection window or not
934 */
935 public boolean isGivenTimestampInSelectedWindow(long timestamp) {
936 boolean returnedValue = true;
937
938 // If the content is not set correctly, this will return weird (or even null) result
939 if ( (timestamp < fullExperimentCanvas.getCurrentWindow().getTimestampOfLeftPosition() ) ||
940 (timestamp > fullExperimentCanvas.getCurrentWindow().getTimestampOfRightPosition() ) )
941 {
942 returnedValue = false;
943 }
944
945 return returnedValue;
946 }
947
948 /**
949 * Reset the content of all Controls.<p>
950 * WARNING : Calls in there are not thread safe and can't be called from different thread than "main"
951 */
952 public void resetControlsContent() {
953
954 TmfExperiment<LttngEvent> tmpExperiment = getLastUsedExperiment();
955
956 // Use the previous Start and End time, or default if they are not available
957 String startTime = null;
958 String stopTime = null;
959 if ( tmpExperiment != null ) {
960 startTime = HistogramConstant.formatNanoSecondsTime( tmpExperiment.getStartTime().getValue() );
961 stopTime = HistogramConstant.formatNanoSecondsTime( tmpExperiment.getEndTime().getValue() );
962 }
963 else {
964 startTime = HistogramConstant.formatNanoSecondsTime( 0L );
965 stopTime = HistogramConstant.formatNanoSecondsTime( 0L );
966 }
967
968 txtExperimentStartTime.setText( startTime );
969 txtExperimentStopTime.setText( stopTime );
970 txtExperimentStartTime.getParent().layout();
971
972 txtWindowMaxNbEvents.setText("" + 0); //$NON-NLS-1$
973 txtWindowMinNbEvents.setText("" + 0); //$NON-NLS-1$
974 txtWindowStartTime.setText( HistogramConstant.formatNanoSecondsTime( 0L ) );
975 txtWindowStopTime.setText( HistogramConstant.formatNanoSecondsTime( 0L ) );
976 txtWindowStartTime.getParent().layout();
977
978 ntgWindowCenterTime.setValue( HistogramConstant.formatNanoSecondsTime( 0L ) );
979 ntgWindowTimeSpan.setValue( HistogramConstant.formatNanoSecondsTime( 0L ) );
980
981 // Using "startTime" here can avoid an useless TmfTimeSynchSignal here
982 // However it look ugly to have only this time
983 ntgCurrentEventTime.setValue( HistogramConstant.formatNanoSecondsTime( 0L ) );
984 }
985
986 /**
987 * Update the content of the controls related to the full experiment canvas<p>
988 * WARNING : Calls in there are not thread safe and can't be called from different thread than "main"
989 */
990 public void updateFullExperimentInformation() {
991
992 if(fullExperimentCanvas != null) {
993 String startTime = HistogramConstant.formatNanoSecondsTime( fullExperimentCanvas.getHistogramContent().getStartTime() );
994 String stopTime = HistogramConstant.formatNanoSecondsTime( fullExperimentCanvas.getHistogramContent().getEndTime() );
995
996 txtExperimentStartTime.setText( startTime );
997 txtExperimentStopTime.setText( stopTime );
998 }
999
1000 // Take one of the parent and call its layout to update control size
1001 // Since both control have the same parent, only one call is needed
1002 txtExperimentStartTime.getParent().layout();
1003
1004 // Update the selected window, just in case
1005 // This should give a better user experience and it is low cost
1006 updateSelectedWindowInformation();
1007 }
1008
1009 /**
1010 * Update the content of the controls related to the selection window canvas<p>
1011 * WARNING : Calls in there are not thread safe and can't be called from different thread than "main"
1012 */
1013 public void updateSelectedWindowInformation() {
1014 // Update the timestamp as well
1015 updateSelectedWindowTimestamp();
1016
1017 if(selectedWindowCanvas != null) {
1018 txtWindowMaxNbEvents.setText( Long.toString(selectedWindowCanvas.getHistogramContent().getHeighestEventCount()) );
1019 txtWindowMinNbEvents.setText(Long.toString(0));
1020 }
1021
1022 // Refresh the layout
1023 txtWindowMaxNbEvents.getParent().layout();
1024 }
1025
1026 /**
1027 * Update the content of the controls related to the timestamp of the selection window<p>
1028 * WARNING : Calls in there are not thread safe and can't be called from different thread than "main"
1029 */
1030 public void updateSelectedWindowTimestamp() {
1031
1032 if(selectedWindowCanvas != null) {
1033 String startTime = HistogramConstant.formatNanoSecondsTime( selectedWindowCanvas.getHistogramContent().getStartTime() );
1034 String stopTime = HistogramConstant.formatNanoSecondsTime( selectedWindowCanvas.getHistogramContent().getEndTime() );
1035 txtWindowStartTime.setText( startTime );
1036 txtWindowStopTime.setText( stopTime );
1037 }
1038
1039 if(fullExperimentCanvas != null) {
1040 ntgWindowCenterTime.setValue( fullExperimentCanvas.getCurrentWindow().getTimestampOfCenterPosition() );
1041 ntgWindowTimeSpan.setValue( fullExperimentCanvas.getCurrentWindow().getWindowTimeWidth() );
1042
1043 // If the current event time is outside the selection window, recenter our window
1044 if ( isGivenTimestampInSelectedWindow(ntgCurrentEventTime.getValue()) == false ) {
1045 currentEventChangeNotification( fullExperimentCanvas.getCurrentWindow().getTimestampOfCenterPosition() );
1046 }
1047 }
1048
1049 // Take one control in each group to call to refresh the layout
1050 // Since both control have the same parent, only one call is needed
1051 txtWindowStartTime.getParent().layout();
1052 ntgWindowCenterTime.getParent().layout();
1053 }
1054
1055 /**
1056 * Update the controls related current event.<p>
1057 * The call here SHOULD be thread safe and can be call from any threads.
1058 */
1059 public void updateSelectedEventTime() {
1060 ntgCurrentEventTime.setValueAsynchronously(currentEventTime);
1061 // sendTmfTimeSynchSignalBroadcast();
1062 // Tell the selection canvas which event is currently selected
1063 // This give a nice graphic output
1064 selectedWindowCanvas.getHistogramContent().setSelectedEventTimeInWindow(currentEventTime);
1065 selectedWindowCanvas.redrawAsynchronously();
1066 }
1067
1068 /**
1069 * Method called when the view is moved.<p>
1070 *
1071 * Just redraw everything...
1072 *
1073 * @param event The control event generated by the move.
1074 */
1075 @Override
1076 public void controlMoved(ControlEvent event) {
1077 parent.redraw();
1078 }
1079
1080 /**
1081 * Method called when the view is resized.<p>
1082 *
1083 * We will make sure that the size didn't change more than the content size.<p>
1084 * Otherwise we need to perform a new request for the full experiment because we are missing data).
1085 *
1086 * @param event The control event generated by the resize.
1087 */
1088 @Override
1089 public void controlResized(ControlEvent event) {
1090
1091 // Ouch! The screen enlarged (screen resolution changed?) so far that we miss content to fill the space.
1092 if ( parent.getDisplay().getBounds().width > fullExperimentCanvas.getHistogramContent().getNbElement() ) {
1093 if ( lastUsedExperiment != null ) {
1094 createCanvasAndRequests(lastUsedExperiment);
1095 }
1096 }
1097
1098 }
1099
1100 /*
1101 * Getter of FullExperimentCanvas
1102 *
1103 * @return FullExperimentCanvas object
1104 */
1105 public static ParentHistogramCanvas getFullExperimentCanvas() {
1106 return fullExperimentCanvas;
1107 }
1108
1109 /*
1110 * Getter of SelectedWindowCanvas
1111 *
1112 * @return SelectedWindowCanvas object
1113 */
1114 public static ChildrenHistogramCanvas getSelectedWindowCanvas() {
1115 return selectedWindowCanvas;
1116 }
1117
1118
1119 /*
1120 * Getter of DEFAULT_WINDOW_SIZE
1121 *
1122 * @return DEFAULT_WINDOW_SIZE value
1123 */
1124 public static long getDEFAULT_WINDOW_SIZE() {
1125 return DEFAULT_WINDOW_SIZE;
1126 }
1127
1128 /**
1129 * Getter for dataBackgroundFullRequest variable
1130 * @return the dataBackgroundFullRequest instance
1131 */
1132 public HistogramRequest getDataBackgroundFullRequest() {
1133 return dataBackgroundFullRequest;
1134 }
1135
1136 /**
1137 * Getter for selectedWindowRequest variable
1138 * @return the selectedWindowRequest instance
1139 */
1140 public HistogramRequest getSelectedWindowRequest() {
1141 return selectedWindowRequest;
1142 }
1143
1144 }
This page took 0.055785 seconds and 5 git commands to generate.