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