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