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