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