tmf: Correct the statistics partial event count
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / viewers / statistics / TmfStatisticsViewer.java
CommitLineData
cfd22ad0
MD
1/*******************************************************************************
2 * Copyright (c) 2012 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 * Mathieu Denis <mathieu.denis@polymtl.ca> - Initial API and implementation
11 *******************************************************************************/
12
13package org.eclipse.linuxtools.tmf.ui.viewers.statistics;
14
15import java.util.List;
16
17import org.eclipse.jface.viewers.TreeViewer;
18import org.eclipse.jface.viewers.TreeViewerColumn;
19import org.eclipse.jface.viewers.Viewer;
20import org.eclipse.jface.viewers.ViewerComparator;
21import org.eclipse.linuxtools.tmf.core.component.TmfComponent;
05627bda
MD
22import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
23import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
24import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
25import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentRangeUpdatedSignal;
26import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentUpdatedSignal;
27import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
28import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
29import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
30import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
31import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewer;
cfd22ad0
MD
32import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.AbsTmfStatisticsTree;
33import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.ITmfColumnDataProvider;
34import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseColumnData;
35import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseColumnDataProvider;
36import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseStatisticsTree;
37import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeNode;
38import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeRootFactory;
39import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfTreeContentProvider;
40import org.eclipse.swt.SWT;
41import org.eclipse.swt.events.SelectionAdapter;
42import org.eclipse.swt.events.SelectionEvent;
43import org.eclipse.swt.graphics.Color;
44import org.eclipse.swt.graphics.Cursor;
cfd22ad0
MD
45import org.eclipse.swt.widgets.Composite;
46import org.eclipse.swt.widgets.Control;
47import org.eclipse.swt.widgets.Display;
48import org.eclipse.swt.widgets.Event;
49import org.eclipse.swt.widgets.Listener;
50
51/**
52 * A basic viewer to display statistics in the statistics view.
53 *
8b60cb37
MD
54 * It is linked to a single ITmfTrace until its disposal.
55 *
cfd22ad0
MD
56 * @author Mathieu Denis
57 * @version 2.0
58 * @since 2.0
59 */
05627bda 60public class TmfStatisticsViewer extends TmfViewer {
cfd22ad0
MD
61
62 /**
05627bda 63 * The initial window span (in nanoseconds)
cfd22ad0 64 */
05627bda
MD
65 public static final long INITIAL_WINDOW_SPAN = (1L * 100 * 1000 * 1000); // .1sec
66
67 /**
68 * Timestamp scale (nanosecond)
69 */
70 public static final byte TIME_SCALE = -9;
71
72 /**
73 * Default PAGE_SIZE for background requests.
74 */
75 protected static final int PAGE_SIZE = 50000;
76
77 /**
78 * Refresh frequency.
79 */
80 protected final Long STATS_INPUT_CHANGED_REFRESH = 5000L;
81
82 /**
83 * Stores the request to the experiment
84 */
85 protected TmfStatisticsRequest fRequest = null;
86
87 /**
88 * Stores the ranged request to the experiment
89 */
90 protected TmfStatisticsRequest fRequestRange = null;
cfd22ad0
MD
91
92 /**
93 * The actual tree viewer to display
94 */
95 protected TreeViewer fTreeViewer;
96
97 /**
05627bda
MD
98 * The statistics tree linked to this viewer
99 */
100 protected AbsTmfStatisticsTree fStatisticsData;
101
102 /**
103 * Update synchronization parameter (used for streaming): Update busy
104 * indicator.
105 */
106 protected boolean fStatisticsUpdateBusy = false;
107
108 /**
109 * Update synchronization parameter (used for streaming): Update pending
110 * indicator.
111 */
112 protected boolean fStatisticsUpdatePending = false;
113
114 /**
115 * Update synchronization parameter (used for streaming): Pending Update
116 * time range.
117 */
118 protected TmfTimeRange fStatisticsUpdateRange = null;
119
120 /**
121 * Update synchronization object.
122 */
123 protected final Object fStatisticsUpdateSyncObj = new Object();
124
3c934968
MD
125 /**
126 * Update range synchronization object.
127 */
128 protected final Object fStatisticsRangeUpdateSyncObj = new Object();
129
05627bda
MD
130 /**
131 * Indicates to process all events
132 */
133 private boolean fProcessAll;
134
135 /**
136 * View instance counter (for multiple statistics views)
cfd22ad0
MD
137 */
138 private static int fCountInstance = 0;
139
140 /**
141 * Number of this instance. Used as an instance ID.
142 */
143 private int fInstanceNb;
144
05627bda
MD
145 /**
146 * The trace that is displayed by this viewer
147 */
148 private ITmfTrace fTrace;
149
cfd22ad0
MD
150 /**
151 * Object to store the cursor while waiting for the experiment to load
152 */
153 private Cursor fWaitCursor = null;
154
155 /**
05627bda
MD
156 * Counts the number of times waitCursor() has been called. It avoids
157 * removing the waiting cursor, since there may be multiple requests running
158 * at the same time.
159 */
160 private int fWaitCursorCount = 0;
161
162 /**
163 * Tells to send a time range request when the experiment gets updated.
164 */
165 private boolean fSendRangeRequest = true;
166
167 /**
168 * Empty constructor. To be used in conjunction with
169 * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
170 */
171 public TmfStatisticsViewer() {
172 super();
173 }
174
175 /**
176 * Create a basic statistics viewer. To be used in conjunction with
177 * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
178 *
179 * @param parent
180 * The parent composite that will hold the viewer
181 * @param viewerName
182 * The name that will be assigned to this viewer
183 * @param trace
184 * The trace that is displayed by this viewer
185 * @see TmfComponent
186 */
187 public TmfStatisticsViewer(Composite parent, String viewerName, ITmfTrace trace) {
188 init(parent, viewerName, trace);
189 }
190
191 /**
192 * Initialize the statistics viewer.
cfd22ad0
MD
193 *
194 * @param parent
05627bda
MD
195 * The parent component of the viewer.
196 * @param viewerName
197 * The name to give to the viewer.
198 * @param trace
199 * The trace that will be displayed by the viewer.
cfd22ad0 200 */
05627bda
MD
201 public void init(Composite parent, String viewerName, ITmfTrace trace) {
202 super.init(parent, viewerName);
cfd22ad0
MD
203 // Increment a counter to make sure the tree ID is unique.
204 fCountInstance++;
205 fInstanceNb = fCountInstance;
05627bda
MD
206 fTrace = trace;
207
208 // The viewer will process all events if he is assigned to the experiment
209 fProcessAll = (trace instanceof TmfExperiment);
210
211 initContent(parent);
8b60cb37 212 initInput();
05627bda
MD
213 }
214
215 /*
216 * (non-Javadoc)
217 *
218 * @see org.eclipse.linuxtools.tmf.core.component.TmfComponent#dispose()
219 */
220 @Override
221 public void dispose() {
222 super.dispose();
223 if (fWaitCursor != null) {
224 fWaitCursor.dispose();
225 }
226 /*
227 * Make sure there is no request running before removing the statistics
228 * tree
229 */
230 cancelOngoingRequest(fRequestRange);
231 cancelOngoingRequest(fRequest);
8b60cb37
MD
232
233 // Clean the model
234 TmfStatisticsTreeRootFactory.removeStatTreeRoot(getTreeID());
05627bda
MD
235 }
236
237 /**
238 * Handles the signal about new experiment range.
239 *
240 * @param signal
241 * The experiment range updated signal
242 */
243 @TmfSignalHandler
244 public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal) {
245 TmfExperiment experiment = signal.getExperiment();
246 // validate
247 if (!experiment.equals(TmfExperiment.getCurrentExperiment())) {
248 return;
249 }
250
3c934968
MD
251 synchronized (fStatisticsRangeUpdateSyncObj) {
252 // Sends the time range request only once from this method.
253 if (fSendRangeRequest) {
254 fSendRangeRequest = false;
255 // Calculate the selected time range to request
256 long startTime = signal.getRange().getStartTime().normalize(0, TIME_SCALE).getValue();
257 TmfTimestamp startTS = new TmfTimestamp(startTime, TIME_SCALE);
258 TmfTimestamp endTS = new TmfTimestamp(startTime + INITIAL_WINDOW_SPAN, TIME_SCALE);
259 TmfTimeRange timeRange = new TmfTimeRange(startTS, endTS);
260
261 requestTimeRangeData(experiment, timeRange);
262 }
05627bda
MD
263 }
264 requestData(experiment, signal.getRange());
265 }
266
267 /**
268 * Handles the experiment updated signal. This will detect new events in
269 * case the indexing is not coalesced with a statistics request.
270 *
271 * @param signal
272 * The experiment updated signal
273 */
274 @TmfSignalHandler
275 public void experimentUpdated(TmfExperimentUpdatedSignal signal) {
276 TmfExperiment experiment = signal.getExperiment();
277 if (!experiment.equals(TmfExperiment.getCurrentExperiment())) {
278 return;
279 }
280
281 long nbEvents = 0;
282 if (fRequest != null) {
283 nbEvents = fRequest.getLastEventIndex();
284 }
285 /*
286 * In the normal case, the statistics request is coalesced with indexing
287 * and the number of events are the same, there is nothing to do. But if
288 * it's not the case, trigger a new request to count the new events.
289 */
290 if (nbEvents < experiment.getNbEvents()) {
291 requestData(experiment, experiment.getTimeRange());
292 }
293 }
294
295 /**
296 * * Handles the time range updated signal. It updates the time range
297 * statistics.
298 *
299 * @param signal
300 * Contains the information about the new selected time range.
301 */
302 @TmfSignalHandler
303 public void timeRangeUpdated(TmfRangeSynchSignal signal) {
304 /*
305 * It is possible that the time range changes while a request is
306 * processing.
307 */
308 cancelOngoingRequest(fRequestRange);
309
310 requestTimeRangeData(TmfExperiment.getCurrentExperiment(), signal.getCurrentRange());
311 }
312
313 /*
314 * Returns the primary control associated with this viewer.
315 *
316 * @return the SWT control which displays this viewer's content
317 */
318 @Override
319 public Control getControl() {
320 return fTreeViewer.getControl();
321 }
322
323 /**
324 * Get the input of the viewer.
325 *
326 * @return an object representing the input of the statistics viewer.
327 */
328 public Object getInput() {
329 return fTreeViewer.getInput();
330 }
331
332 /**
333 * Return the size of the request when performing background request.
334 *
335 * @return the block size for background request.
336 */
337 public int getPageSize() {
338 return PAGE_SIZE;
339 }
340
341 /**
342 * Return the number of events to receive before a refresh of the viewer is
343 * performed.
344 *
345 * @return the input refresh rate
346 */
347 public long getRefreshRate() {
348 return STATS_INPUT_CHANGED_REFRESH;
349 }
350
351 /**
352 * This method can be overridden to implement another way of representing
353 * the statistics data and to retrieve the information for display.
354 *
355 * @return a TmfStatisticsData object.
356 */
357 public AbsTmfStatisticsTree getStatisticData() {
358 if (fStatisticsData == null) {
359 fStatisticsData = new TmfBaseStatisticsTree();
360 }
361 return fStatisticsData;
362 }
363
364 /**
365 * Returns a unique ID based on name to be associated with the statistics
366 * tree for this viewer. For a same name, it will always return the same ID.
367 *
368 * @return a unique statistics tree ID.
369 */
370 public String getTreeID() {
371 return getName() + fInstanceNb;
372 }
373
374 @Override
375 public void refresh() {
376 final Control viewerControl = getControl();
377 // Ignore update if disposed
378 if (viewerControl.isDisposed()) {
379 return;
380 }
381
382 viewerControl.getDisplay().asyncExec(new Runnable() {
383 @Override
384 public void run() {
385 if (!viewerControl.isDisposed()) {
386 fTreeViewer.refresh();
387 }
388 }
389 });
390 }
391
3c934968
MD
392 /**
393 * Will force a request on the partial event count if one is needed.
394 */
395 public void sendPartialRequestOnNextUpdate() {
396 synchronized (fStatisticsRangeUpdateSyncObj) {
397 fSendRangeRequest = true;
398 }
399 }
400
05627bda
MD
401 /**
402 * Focus on the statistics tree of the viewer
403 */
404 public void setFocus() {
405 fTreeViewer.getTree().setFocus();
406 }
407
05627bda
MD
408 /**
409 * Cancels the request if it is not already completed
410 *
411 * @param request
412 * The request to be canceled
413 */
414 protected void cancelOngoingRequest(ITmfDataRequest request) {
415 if (request != null && !request.isCompleted()) {
416 request.cancel();
417 }
418 }
419
420 /**
421 * This method can be overridden to change the representation of the data in
422 * the columns.
423 *
424 * @return an object implementing ITmfBaseColumnDataProvider.
425 */
426 protected ITmfColumnDataProvider getColumnDataProvider() {
427 return new TmfBaseColumnDataProvider();
428 }
cfd22ad0 429
05627bda
MD
430 /**
431 * Initialize the content that will be drawn in this viewer
432 *
433 * @param parent
434 * The parent of the control to create
435 */
436 protected void initContent(Composite parent) {
cfd22ad0 437 final List<TmfBaseColumnData> columnDataList = getColumnDataProvider().getColumnData();
cfd22ad0
MD
438
439 fTreeViewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
440 fTreeViewer.setContentProvider(new TmfTreeContentProvider());
441 fTreeViewer.getTree().setHeaderVisible(true);
442 fTreeViewer.setUseHashlookup(true);
443
444 // Creates the columns defined by the column data provider
445 for (final TmfBaseColumnData columnData : columnDataList) {
446 final TreeViewerColumn treeColumn = new TreeViewerColumn(fTreeViewer, columnData.getAlignment());
447 treeColumn.getColumn().setText(columnData.getHeader());
448 treeColumn.getColumn().setWidth(columnData.getWidth());
449 treeColumn.getColumn().setToolTipText(columnData.getTooltip());
450
451 if (columnData.getComparator() != null) { // A comparator is defined.
452 // Adds a listener on the columns header for sorting purpose.
453 treeColumn.getColumn().addSelectionListener(new SelectionAdapter() {
454
455 private ViewerComparator reverseComparator;
456
457 @Override
458 public void widgetSelected(SelectionEvent e) {
459 // Initializes the reverse comparator once.
460 if (reverseComparator == null) {
461 reverseComparator = new ViewerComparator() {
462 @Override
463 public int compare(Viewer viewer, Object e1, Object e2) {
464 return -1 * columnData.getComparator().compare(viewer, e1, e2);
465 }
466 };
467 }
468
469 if (fTreeViewer.getTree().getSortDirection() == SWT.UP
470 || fTreeViewer.getTree().getSortColumn() != treeColumn.getColumn()) {
471 /*
472 * Puts the descendant order if the old order was
473 * up or if the selected column has changed.
474 */
475 fTreeViewer.setComparator(columnData.getComparator());
476 fTreeViewer.getTree().setSortDirection(SWT.DOWN);
477 } else {
478 /*
479 * Puts the ascendant ordering if the selected
480 * column hasn't changed.
481 */
482 fTreeViewer.setComparator(reverseComparator);
483 fTreeViewer.getTree().setSortDirection(SWT.UP);
484 }
485 fTreeViewer.getTree().setSortColumn(treeColumn.getColumn());
486 }
487 });
488 }
489 treeColumn.setLabelProvider(columnData.getLabelProvider());
490 }
491
492 // Handler that will draw the bar charts.
493 fTreeViewer.getTree().addListener(SWT.EraseItem, new Listener() {
494 @Override
495 public void handleEvent(Event event) {
496 if (columnDataList.get(event.index).getPercentageProvider() != null) {
497 TmfStatisticsTreeNode node = (TmfStatisticsTreeNode) event.item.getData();
498
499 double percentage = columnDataList.get(event.index).getPercentageProvider().getPercentage(node);
500 if (percentage == 0) { // No bar to draw
501 return;
502 }
503
504 if ((event.detail & SWT.SELECTED) > 0) { // The item is selected.
505 // Draws our own background to avoid overwritten the bar.
506 event.gc.fillRectangle(event.x, event.y, event.width, event.height);
507 event.detail &= ~SWT.SELECTED;
508 }
509
510 int barWidth = (int) ((fTreeViewer.getTree().getColumn(event.index).getWidth() - 8) * percentage);
511 int oldAlpha = event.gc.getAlpha();
512 Color oldForeground = event.gc.getForeground();
513 Color oldBackground = event.gc.getBackground();
514 /*
515 * Draws a transparent gradient rectangle from the color of
516 * foreground and background.
517 */
518 event.gc.setAlpha(64);
519 event.gc.setForeground(event.item.getDisplay().getSystemColor(SWT.COLOR_BLUE));
520 event.gc.setBackground(event.item.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
521 event.gc.fillGradientRectangle(event.x, event.y, barWidth, event.height, true);
522 event.gc.drawRectangle(event.x, event.y, barWidth, event.height);
523 // Restores old values
524 event.gc.setForeground(oldForeground);
525 event.gc.setBackground(oldBackground);
526 event.gc.setAlpha(oldAlpha);
527 event.detail &= ~SWT.BACKGROUND;
528 }
529 }
530 });
531
532 // Initializes the comparator parameters
533 fTreeViewer.setComparator(columnDataList.get(0).getComparator());
534 fTreeViewer.getTree().setSortColumn(fTreeViewer.getTree().getColumn(0));
535 fTreeViewer.getTree().setSortDirection(SWT.DOWN);
536 }
537
8b60cb37
MD
538 /**
539 * Initializes the input for the tree viewer.
540 *
541 * @param input
542 * The input of this viewer, or <code>null</code> if none
543 */
544 protected void initInput() {
545 String treeID = getTreeID();
546 TmfStatisticsTreeNode experimentTreeNode;
547 if (TmfStatisticsTreeRootFactory.containsTreeRoot(treeID)) {
548 // The experiment root is already present
549 experimentTreeNode = TmfStatisticsTreeRootFactory.getStatTreeRoot(treeID);
550
551 // Checks if the trace is already in the statistics tree.
552 int numNodeTraces = experimentTreeNode.getNbChildren();
553
554 int numTraces = 1;
555 ITmfTrace[] trace = { fTrace };
556 // For experiment, gets all the traces within it
557 if (fTrace instanceof TmfExperiment) {
558 TmfExperiment experiment = (TmfExperiment) fTrace;
559 numTraces = experiment.getTraces().length;
560 trace = experiment.getTraces();
561 }
562
563 if (numTraces == numNodeTraces) {
564 boolean same = true;
565 /*
566 * Checks if the experiment contains the same traces as when
567 * previously selected.
568 */
569 for (int i = 0; i < numTraces; i++) {
570 String traceName = trace[i].getName();
571 if (!experimentTreeNode.containsChild(traceName)) {
572 same = false;
573 break;
574 }
575 }
576
577 if (same) {
578 // No need to reload data, all traces are already loaded
579 fTreeViewer.setInput(experimentTreeNode);
580 return;
581 }
582 // Clears the old content to start over
583 experimentTreeNode.reset();
584 }
585 } else {
586 // Creates a new tree
587 experimentTreeNode = TmfStatisticsTreeRootFactory.addStatsTreeRoot(treeID, getStatisticData());
588 }
589
590 // Sets the input to a clean data model
591 fTreeViewer.setInput(experimentTreeNode);
592 resetUpdateSynchronization();
593 }
594
cfd22ad0 595 /**
05627bda 596 * Tells if the viewer is listening to a trace from the selected experiment.
cfd22ad0 597 *
05627bda
MD
598 * @param traceName
599 * The trace that the viewer may be listening
600 * @return true if the viewer is listening to the trace, false otherwise
cfd22ad0 601 */
05627bda
MD
602 protected boolean isListeningTo(String traceName) {
603 if (fProcessAll || traceName.equals(fTrace.getName())) {
604 return true;
cfd22ad0 605 }
05627bda 606 return false;
cfd22ad0
MD
607 }
608
609 /**
05627bda 610 * Called when an experiment request has been completed successfully.
cfd22ad0 611 *
05627bda
MD
612 * @param global
613 * Tells if the request is a global or time range (partial)
614 * request.
cfd22ad0 615 */
05627bda
MD
616 protected void modelComplete(boolean global) {
617 refresh();
618 waitCursor(false);
619 if (global) {
620 sendPendingUpdate();
621 }
cfd22ad0
MD
622 }
623
624 /**
05627bda 625 * Called when an experiment request has failed or has been cancelled.
cfd22ad0 626 *
05627bda
MD
627 * @param isGlobalRequest
628 * Tells if the request is a global or time range (partial)
629 * request.
cfd22ad0 630 */
05627bda
MD
631 protected void modelIncomplete(boolean isGlobalRequest) {
632 if (isGlobalRequest) { // Clean the global statistics
633 /*
763f4972
MD
634 * No need to reset the global number of events, since the index of
635 * the last requested event is known.
05627bda 636 */
05627bda
MD
637 resetUpdateSynchronization();
638 sendPendingUpdate();
639 } else { // Clean the partial statistics
640 resetTimeRangeValue();
641 }
642 refresh();
643 waitCursor(false);
cfd22ad0
MD
644 }
645
646 /**
05627bda 647 * Sends the request to the experiment for the whole trace
cfd22ad0 648 *
05627bda
MD
649 * @param experiment
650 * The experiment used to send the request
651 * @param range
652 * The range to request to the experiment
cfd22ad0 653 */
05627bda
MD
654 protected void requestData(TmfExperiment experiment, TmfTimeRange range) {
655 // Check if an update is already ongoing
656 if (checkUpdateBusy(range)) {
657 return;
658 }
659
660 long index = 0;
661 /*
662 * Sets the index to the last event retrieved from the experiment during
663 * the last request.
664 */
665 if (fRequest != null) {
666 index = fRequest.getLastEventIndex();
667 }
668
669 fRequest = new TmfStatisticsRequest(this, range, index, true);
670 waitCursor(true);
671 experiment.sendRequest(fRequest);
cfd22ad0
MD
672 }
673
674 /**
05627bda 675 * Sends the time range request from the experiment
cfd22ad0 676 *
05627bda
MD
677 * @param experiment
678 * The experiment used to send the request
679 * @param range
680 * The range to request to the experiment
cfd22ad0 681 */
05627bda
MD
682 protected void requestTimeRangeData(TmfExperiment experiment, TmfTimeRange range) {
683 resetTimeRangeValue();
684 fRequestRange = new TmfStatisticsRequest(this, range, 0, false);
685 waitCursor(true);
686 experiment.sendRequest(fRequestRange);
cfd22ad0
MD
687 }
688
689 /**
05627bda 690 * Resets the number of events within the time range
cfd22ad0 691 */
05627bda
MD
692 protected void resetTimeRangeValue() {
693 TmfStatisticsTreeNode treeModelRoot = TmfStatisticsTreeRootFactory.getStatTreeRoot(getTreeID());
694 if (treeModelRoot != null && treeModelRoot.hasChildren()) {
695 treeModelRoot.resetTimeRangeValue();
696 }
cfd22ad0
MD
697 }
698
699 /**
700 * When the experiment is loading the cursor will be different so the user
05627bda
MD
701 * knows that the processing is not finished yet.
702 *
703 * Calls to this method are stacked.
cfd22ad0 704 *
05627bda 705 * @param waitRequested
cfd22ad0 706 * Indicates if we need to show the waiting cursor, or the
05627bda 707 * default one.
cfd22ad0 708 */
05627bda 709 protected void waitCursor(final boolean waitRequested) {
cfd22ad0
MD
710 if ((fTreeViewer == null) || (fTreeViewer.getTree().isDisposed())) {
711 return;
712 }
713
05627bda 714 boolean needsUpdate = false;
cfd22ad0 715 Display display = fTreeViewer.getControl().getDisplay();
05627bda
MD
716 if (waitRequested) {
717 fWaitCursorCount++;
718 if (fWaitCursor == null) { // The cursor hasn't been initialized yet
719 fWaitCursor = new Cursor(display, SWT.CURSOR_WAIT);
720 }
721 if (fWaitCursorCount == 1) { // The cursor is not in waiting mode
722 needsUpdate = true;
723 }
724 } else {
725 if (fWaitCursorCount > 0) { // The cursor is in waiting mode
726 fWaitCursorCount--;
727 if (fWaitCursorCount == 0) { // No more reason to wait
728 // Put back the default cursor
729 needsUpdate = true;
730 }
731 }
cfd22ad0
MD
732 }
733
05627bda
MD
734 if (needsUpdate) {
735 // Performs the updates on the UI thread
736 display.asyncExec(new Runnable() {
737 @Override
738 public void run() {
739 if ((fTreeViewer != null)
740 && (!fTreeViewer.getTree().isDisposed())) {
741 Cursor cursor = null; // indicates default
742 if (waitRequested) {
743 cursor = fWaitCursor;
744 }
745 fTreeViewer.getControl().setCursor(cursor);
cfd22ad0 746 }
cfd22ad0 747 }
05627bda
MD
748 });
749 }
cfd22ad0
MD
750 }
751
05627bda
MD
752 // ------------------------------------------------------------------------
753 // Methods reserved for the streaming functionality
754 // ------------------------------------------------------------------------
755
cfd22ad0 756 /**
05627bda 757 * Resets update synchronization information
cfd22ad0 758 */
05627bda
MD
759 protected void resetUpdateSynchronization() {
760 synchronized (fStatisticsUpdateSyncObj) {
761 fStatisticsUpdateBusy = false;
762 fStatisticsUpdatePending = false;
763 fStatisticsUpdateRange = null;
764 }
cfd22ad0
MD
765 }
766
767 /**
05627bda
MD
768 * Checks if statistics update is ongoing. If it is ongoing, the new time
769 * range is stored as pending
cfd22ad0 770 *
05627bda
MD
771 * @param timeRange
772 * - new time range
773 * @return true if statistic update is ongoing else false
cfd22ad0 774 */
05627bda
MD
775 protected boolean checkUpdateBusy(TmfTimeRange timeRange) {
776 synchronized (fStatisticsUpdateSyncObj) {
777 if (fStatisticsUpdateBusy) {
778 fStatisticsUpdatePending = true;
779 if (fStatisticsUpdateRange == null
780 || timeRange.getEndTime().compareTo(fStatisticsUpdateRange.getEndTime()) > 0) {
781 fStatisticsUpdateRange = timeRange;
782 }
783 return true;
784 }
785 fStatisticsUpdateBusy = true;
786 return false;
787 }
788 }
789
790 /**
791 * Sends pending request (if any)
792 */
793 protected void sendPendingUpdate() {
794 synchronized (fStatisticsUpdateSyncObj) {
795 fStatisticsUpdateBusy = false;
796 if (fStatisticsUpdatePending) {
797 fStatisticsUpdatePending = false;
798 requestData(TmfExperiment.getCurrentExperiment(), fStatisticsUpdateRange);
799 fStatisticsUpdateRange = null;
800 }
801 }
cfd22ad0
MD
802 }
803}
This page took 0.058719 seconds and 5 git commands to generate.