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