piecharts: add tree selection when a piechart slice is selected
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / internal / tmf / ui / viewers / statistics / TmfStatisticsViewer.java
1 /*******************************************************************************
2 * Copyright (c) 2012, 2015 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 * Patrick Tasse - Support selection range
13 * Bernd Hufmann - Fix range selection updates
14 *******************************************************************************/
15
16 package org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics;
17
18 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
19
20 import java.util.Collection;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.eclipse.core.runtime.jobs.Job;
26 import org.eclipse.jface.viewers.StructuredSelection;
27 import org.eclipse.jface.viewers.TreeViewer;
28 import org.eclipse.jface.viewers.TreeViewerColumn;
29 import org.eclipse.jface.viewers.Viewer;
30 import org.eclipse.jface.viewers.ViewerComparator;
31 import org.eclipse.swt.SWT;
32 import org.eclipse.swt.custom.SashForm;
33 import org.eclipse.swt.events.SelectionAdapter;
34 import org.eclipse.swt.events.SelectionEvent;
35 import org.eclipse.swt.graphics.Color;
36 import org.eclipse.swt.graphics.Cursor;
37 import org.eclipse.swt.widgets.Composite;
38 import org.eclipse.swt.widgets.Control;
39 import org.eclipse.swt.widgets.Display;
40 import org.eclipse.swt.widgets.Event;
41 import org.eclipse.swt.widgets.Listener;
42 import org.eclipse.tracecompass.tmf.core.component.TmfComponent;
43 import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
44 import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
45 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
46 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceRangeUpdatedSignal;
47 import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsModule;
48 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
49 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
50 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
51 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
52 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
53 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
54 import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
55 import org.eclipse.tracecompass.tmf.ui.viewers.TmfViewer;
56 import org.eclipse.tracecompass.internal.tmf.ui.viewers.piecharts.TmfPieChartViewer;
57 import org.eclipse.tracecompass.internal.tmf.ui.viewers.piecharts.model.TmfPieChartStatisticsModel;
58 import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfBaseColumnData;
59 import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfBaseColumnDataProvider;
60 import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsFormatter;
61 import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTree;
62 import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTreeManager;
63 import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTreeNode;
64 import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfTreeContentProvider;
65
66 /**
67 * A basic viewer to display statistics in the statistics view.
68 *
69 * It is linked to a single ITmfTrace until its disposal.
70 *
71 * @author Mathieu Denis
72 */
73 public class TmfStatisticsViewer extends TmfViewer {
74
75 /** The actual tree viewer to display */
76 private TreeViewer fTreeViewer;
77
78 /** Update range synchronization object */
79 private final Object fStatisticsRangeUpdateSyncObj = new Object();
80
81 /** The statistics tree linked to this viewer */
82 private TmfStatisticsTree fStatisticsData;
83
84 /** The trace that is displayed by this viewer */
85 private ITmfTrace fTrace;
86
87 /** Indicates to process all events */
88 private boolean fProcessAll;
89
90 /** View instance counter (for multiple statistics views) */
91 private static int fCountInstance = 0;
92
93 /** Number of this instance. Used as an instance ID. */
94 private int fInstanceNb;
95
96 /** Object to store the cursor while waiting for the trace to load */
97 private Cursor fWaitCursor = null;
98
99 /**
100 * Counts the number of times waitCursor() has been called. It avoids
101 * removing the waiting cursor, since there may be multiple requests running
102 * at the same time.
103 */
104 private int fWaitCursorCount = 0;
105
106 /** Tells to send a time range request when the trace gets updated. */
107 private boolean fSendRangeRequest = true;
108
109 private final Map<ITmfTrace, Job> fUpdateJobsPartial = new HashMap<>();
110 private final Map<ITmfTrace, Job> fUpdateJobsGlobal = new HashMap<>();
111
112 private TmfPieChartViewer fPieChartViewer;
113
114 private SashForm fSash;
115
116 private TmfPieChartStatisticsModel fPieChartModel;
117
118 /**
119 * Create a basic statistics viewer. To be used in conjunction with
120 * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
121 *
122 * @param parent
123 * The parent composite that will hold the viewer
124 * @param viewerName
125 * The name that will be assigned to this viewer
126 * @param trace
127 * The trace that is displayed by this viewer
128 * @see TmfComponent
129 */
130 public TmfStatisticsViewer(Composite parent, String viewerName, ITmfTrace trace) {
131 init(parent, viewerName, trace);
132 }
133
134 /**
135 * Initialize the statistics viewer.
136 *
137 * @param parent
138 * The parent component of the viewer.
139 * @param viewerName
140 * The name to give to the viewer.
141 * @param trace
142 * The trace that will be displayed by the viewer.
143 */
144 public void init(Composite parent, String viewerName, ITmfTrace trace) {
145 super.init(parent, viewerName);
146 // Increment a counter to make sure the tree ID is unique.
147 fCountInstance++;
148 fInstanceNb = fCountInstance;
149 fTrace = trace;
150
151 // The viewer will process all events if he is assigned to an experiment
152 fProcessAll = (trace instanceof TmfExperiment);
153
154 initContent(parent);
155 initInput();
156 }
157
158 @Override
159 public void dispose() {
160 super.dispose();
161 if (fWaitCursor != null) {
162 fWaitCursor.dispose();
163 }
164
165 for (Job j : fUpdateJobsGlobal.values()) {
166 j.cancel();
167 }
168
169 for (Job j : fUpdateJobsPartial.values()) {
170 j.cancel();
171 }
172
173 // Clean the model for this viewer
174 TmfStatisticsTreeManager.removeStatTreeRoot(getTreeID());
175 fPieChartViewer.reinitializeCharts();
176 }
177
178 // ------------------------------------------------------------------------
179 // Signal handlers
180 // ------------------------------------------------------------------------
181
182 /**
183 * Handles the signal about new trace range.
184 *
185 * @param signal
186 * The trace range updated signal
187 */
188 @TmfSignalHandler
189 public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal) {
190 ITmfTrace trace = signal.getTrace();
191 // validate
192 if (!isListeningTo(trace)) {
193 return;
194 }
195
196 synchronized (fStatisticsRangeUpdateSyncObj) {
197 // Sends the time range request only once from this method.
198 if (fSendRangeRequest) {
199 fSendRangeRequest = false;
200
201 TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
202 TmfTimeRange timeRange = ctx.getSelectionRange();
203 requestTimeRangeData(trace, timeRange);
204 }
205 }
206 requestData(trace, signal.getRange());
207 }
208
209 /**
210 * Handles the time synch updated signal. It updates the time range
211 * statistics.
212 *
213 * @param signal
214 * Contains the information about the new selected time range.
215 * @since 1.0
216 */
217 @TmfSignalHandler
218 public void timeSynchUpdated(TmfSelectionRangeUpdatedSignal signal) {
219 if (fTrace == null) {
220 return;
221 }
222 ITmfTimestamp begin = signal.getBeginTime();
223 ITmfTimestamp end = signal.getEndTime();
224 TmfTimeRange timeRange = new TmfTimeRange(begin, end);
225 requestTimeRangeData(fTrace, timeRange);
226 }
227
228 // ------------------------------------------------------------------------
229 // Class methods
230 // ------------------------------------------------------------------------
231
232 /*
233 * Returns the primary control associated with this viewer.
234 *
235 * @return the SWT control which displays this viewer's content
236 */
237 @Override
238 public Control getControl() {
239 return fSash;
240 }
241
242 /**
243 * Get the input of the viewer.
244 *
245 * @return an object representing the input of the statistics viewer.
246 */
247 public Object getInput() {
248 return fTreeViewer.getInput();
249 }
250
251 /**
252 * This method can be overridden to implement another way of representing
253 * the statistics data and to retrieve the information for display.
254 *
255 * @return a TmfStatisticsData object.
256 */
257 public TmfStatisticsTree getStatisticData() {
258 if (fStatisticsData == null) {
259 fStatisticsData = new TmfStatisticsTree();
260 }
261 return fStatisticsData;
262 }
263
264 /**
265 * @return the model of the piecharts in this viewer
266 * @since 2.0
267 */
268 public TmfPieChartStatisticsModel getPieChartModel() {
269 if (fPieChartModel == null) {
270 fPieChartModel = new TmfPieChartStatisticsModel();
271 }
272 return fPieChartModel;
273 }
274
275 /**
276 * Returns a unique ID based on name to be associated with the statistics
277 * tree for this viewer. For a same name, it will always return the same ID.
278 *
279 * @return a unique statistics tree ID.
280 */
281 public String getTreeID() {
282 return getName() + fInstanceNb;
283 }
284
285 @Override
286 public void refresh() {
287 final Control viewerControl = getControl();
288 // Ignore update if disposed
289 if (viewerControl.isDisposed()) {
290 return;
291 }
292 refreshTree();
293 refreshPieCharts(true, true);
294 }
295
296 /**
297 * Only refreshes the Tree viewer
298 */
299 private void refreshTree() {
300 final Control viewerControl = getControl();
301 // Ignore update if disposed
302 if (viewerControl.isDisposed()) {
303 return;
304 }
305
306 Display.getDefault().asyncExec(new Runnable() {
307 @Override
308 public void run() {
309 if (!viewerControl.isDisposed()) {
310 fTreeViewer.refresh();
311 }
312 }
313 });
314 }
315
316 /**
317 * Only refreshes the piecharts depending on the parameters
318 *
319 * @param refreshGlobal
320 * if we have to refresh the global piechart
321 * @param refreshSelection
322 * if we have to refresh the selection piechart
323 * @since 2.0
324 */
325 protected void refreshPieCharts(final boolean refreshGlobal, final boolean refreshSelection) {
326 final Control viewerControl = getControl();
327 // Ignore update if disposed
328 if (viewerControl.isDisposed()) {
329 return;
330 }
331
332 Display.getDefault().asyncExec(new Runnable() {
333 @Override
334 public void run() {
335 if (!viewerControl.isDisposed()) {
336 fPieChartViewer.refresh(refreshGlobal, refreshSelection);
337 }
338 }
339 });
340 }
341
342 /**
343 * Will force a request on the partial event count if one is needed.
344 */
345 public void sendPartialRequestOnNextUpdate() {
346 synchronized (fStatisticsRangeUpdateSyncObj) {
347 fSendRangeRequest = true;
348 }
349 }
350
351 /**
352 * Focus on the statistics tree of the viewer
353 */
354 public void setFocus() {
355 fTreeViewer.getTree().setFocus();
356 }
357
358 /**
359 * Cancels the request if it is not already completed
360 *
361 * @param request
362 * The request to be canceled
363 */
364 protected void cancelOngoingRequest(ITmfEventRequest request) {
365 if (request != null && !request.isCompleted()) {
366 request.cancel();
367 }
368 }
369
370 /**
371 * This method can be overridden to change the representation of the data in
372 * the columns.
373 *
374 * @return An object of type {@link TmfBaseColumnDataProvider}.
375 */
376 protected TmfBaseColumnDataProvider getColumnDataProvider() {
377 return new TmfBaseColumnDataProvider();
378 }
379
380 /**
381 * Initialize the content that will be drawn in this viewer
382 *
383 * @param parent
384 * The parent of the control to create
385 */
386 protected void initContent(Composite parent) {
387
388 final List<TmfBaseColumnData> columnDataList = getColumnDataProvider().getColumnData();
389
390 fSash = new SashForm(parent, SWT.HORIZONTAL);
391
392 fTreeViewer = new TreeViewer(fSash, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
393 fPieChartViewer = new TmfPieChartViewer(fSash);
394 fPieChartViewer.addEventTypeSelectionListener(new Listener() {
395
396 @Override
397 public void handleEvent(Event event) {
398 String eventTypeName = event.text;
399 if (getStatisticData().getRootNode() == null ||
400 fTreeViewer == null ||
401 fTreeViewer.getTree() == null) {
402 return;
403 }
404 /* Get all the nodes corresponding to the event name */
405 List<TmfStatisticsTreeNode> nodes = (List<TmfStatisticsTreeNode>) getStatisticData().getRootNode().findChildren(eventTypeName, true);
406 if (nodes.isEmpty()) {
407 /* Shouldn't happen, except for when selecting "Others" */
408 return;
409 }
410 /* Only select the first in the collection */
411 fTreeViewer.setSelection(new StructuredSelection(nodes.get(0)), true);
412 }
413 });
414
415 /* Make sure the sash is split in 2 equal parts */
416 fSash.setWeights(new int[] { 100, 100 });
417
418 fTreeViewer.setContentProvider(new TmfTreeContentProvider());
419 fTreeViewer.getTree().setHeaderVisible(true);
420 fTreeViewer.setUseHashlookup(true);
421
422 // Creates the columns defined by the column data provider
423 for (final TmfBaseColumnData columnData : columnDataList) {
424 final TreeViewerColumn treeColumn = new TreeViewerColumn(fTreeViewer, columnData.getAlignment());
425 treeColumn.getColumn().setText(columnData.getHeader());
426 treeColumn.getColumn().setWidth(columnData.getWidth());
427 treeColumn.getColumn().setToolTipText(columnData.getTooltip());
428
429 // If is dummy column
430 if (columnData == columnDataList.get(TmfBaseColumnDataProvider.StatsColumn.DUMMY.getIndex())) {
431 treeColumn.getColumn().setResizable(false);
432 }
433
434 // A comparator is defined.
435 if (columnData.getComparator() != null) {
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 up
457 * 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 percentages and 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
482 TmfStatisticsTreeNode node = (TmfStatisticsTreeNode) event.item.getData();
483
484 // If node is hidden, exit immediately.
485 if (TmfBaseColumnDataProvider.HIDDEN_FOLDER_LEVELS.contains(node.getName())) {
486 return;
487 }
488
489 // Otherwise, get percentage and draw bar and text if
490 // applicable.
491 double percentage = columnDataList.get(event.index).getPercentageProvider().getPercentage(node);
492
493 // The item is selected.
494 if ((event.detail & SWT.SELECTED) > 0) {
495 // Draws our own background to avoid overwriting the
496 // bar.
497 event.gc.fillRectangle(event.x, event.y, event.width, event.height);
498 event.detail &= ~SWT.SELECTED;
499 }
500
501 // Drawing the percentage text
502 // if events are present in top node
503 // and the current node is not the top node
504 // and if is total or partial events column.
505 // If not, exit the method.
506 if (!((event.index == TmfBaseColumnDataProvider.StatsColumn.TOTAL.getIndex() || event.index == TmfBaseColumnDataProvider.StatsColumn.PARTIAL.getIndex())
507 && node != node.getTop())) {
508 return;
509 }
510
511 long eventValue = event.index == TmfBaseColumnDataProvider.StatsColumn.TOTAL.getIndex() ?
512 node.getTop().getValues().getTotal() : node.getTop().getValues().getPartial();
513
514 if (eventValue != 0) {
515
516 int oldAlpha = event.gc.getAlpha();
517 Color oldForeground = event.gc.getForeground();
518 Color oldBackground = event.gc.getBackground();
519
520 // Bar to draw
521 if (percentage != 0) {
522 /*
523 * Draws a transparent gradient rectangle from the
524 * color of foreground and background.
525 */
526 int barWidth = (int) ((fTreeViewer.getTree().getColumn(event.index).getWidth() - 8) * percentage);
527 event.gc.setAlpha(64);
528 event.gc.setForeground(event.item.getDisplay().getSystemColor(SWT.COLOR_BLUE));
529 event.gc.setBackground(event.item.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
530 event.gc.fillGradientRectangle(event.x, event.y, barWidth, event.height, true);
531 event.gc.drawRectangle(event.x, event.y, barWidth, event.height);
532
533 // Restore old values
534 event.gc.setBackground(oldBackground);
535 event.gc.setAlpha(oldAlpha);
536 event.detail &= ~SWT.BACKGROUND;
537
538 }
539
540 String percentageText = TmfStatisticsFormatter.toPercentageText(percentage);
541 String absoluteNumberText = TmfStatisticsFormatter.toColumnData(node, TmfBaseColumnDataProvider.StatsColumn.getColumn(event.index));
542
543 if (event.width > event.gc.stringExtent(percentageText).x + event.gc.stringExtent(absoluteNumberText).x) {
544 int textHeight = event.gc.stringExtent(percentageText).y;
545 event.gc.setForeground(event.item.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
546 event.gc.drawText(percentageText, event.x, event.y + (event.height - textHeight) / 2, true);
547 }
548
549 // Restores old values
550 event.gc.setForeground(oldForeground);
551
552 }
553 }
554 }
555
556 });
557
558 // Initializes the comparator parameters
559 fTreeViewer.setComparator(columnDataList.get(0).getComparator());
560 fTreeViewer.getTree().setSortColumn(fTreeViewer.getTree().getColumn(0));
561 fTreeViewer.getTree().setSortDirection(SWT.DOWN);
562 }
563
564 /**
565 * Initializes the input for the tree viewer.
566 */
567 protected void initInput() {
568 String treeID = getTreeID();
569 TmfStatisticsTreeNode statisticsTreeNode;
570 if (TmfStatisticsTreeManager.containsTreeRoot(treeID)) {
571 // The statistics root is already present
572 statisticsTreeNode = TmfStatisticsTreeManager.getStatTreeRoot(treeID);
573
574 // Checks if the trace is already in the statistics tree.
575 int numNodeTraces = statisticsTreeNode.getNbChildren();
576
577 Collection<ITmfTrace> traces = TmfTraceManager.getTraceSet(fTrace);
578 int numTraces = traces.size();
579
580 if (numTraces == numNodeTraces) {
581 boolean same = true;
582 /*
583 * Checks if the experiment contains the same traces as when
584 * previously selected.
585 */
586 for (ITmfTrace trace : traces) {
587 String traceName = trace.getName();
588 if (!statisticsTreeNode.containsChild(traceName)) {
589 same = false;
590 break;
591 }
592 }
593
594 if (same) {
595 // No need to reload data, all traces are already loaded
596 fTreeViewer.setInput(statisticsTreeNode);
597 return;
598 }
599 // Clears the old content to start over
600 statisticsTreeNode.reset();
601 }
602 } else {
603 // Creates a new tree
604 statisticsTreeNode = TmfStatisticsTreeManager.addStatsTreeRoot(treeID, getStatisticData());
605 }
606
607 // Sets the input to a clean data model
608 fTreeViewer.setInput(statisticsTreeNode);
609 /* Set a new model for the piecharts and keep a reference */
610 fPieChartViewer.setInput(getPieChartModel());
611 }
612
613 /**
614 * Tells if the viewer is listening to a trace.
615 *
616 * @param trace
617 * The trace that the viewer may be listening
618 * @return true if the viewer is listening to the trace, false otherwise
619 */
620 protected boolean isListeningTo(ITmfTrace trace) {
621 if (fProcessAll || trace == fTrace) {
622 return true;
623 }
624 return false;
625 }
626
627 /**
628 * Called when an trace request has been completed successfully.
629 *
630 * @param global
631 * Tells if the request is a global or time range (partial)
632 * request.
633 */
634 protected void modelComplete(boolean global) {
635 refreshTree();
636 waitCursor(false);
637 }
638
639 /**
640 * Sends the request to the trace for the whole trace
641 *
642 * @param trace
643 * The trace used to send the request
644 * @param timeRange
645 * The range to request to the trace
646 */
647 protected void requestData(final ITmfTrace trace, final TmfTimeRange timeRange) {
648 buildStatisticsTree(trace, timeRange, true);
649 }
650
651 /**
652 * Sends the time range request from the trace
653 *
654 * @param trace
655 * The trace used to send the request
656 * @param timeRange
657 * The range to request to the trace
658 */
659 protected void requestTimeRangeData(final ITmfTrace trace, final TmfTimeRange timeRange) {
660 buildStatisticsTree(trace, timeRange, false);
661 }
662
663 /**
664 * Requests all the data of the trace to the state system which contains
665 * information about the statistics.
666 *
667 * Since the viewer may be listening to multiple traces, it may receive an
668 * experiment rather than a single trace. The filtering is done with the
669 * method {@link #isListeningTo(String trace)}.
670 *
671 * @param trace
672 * The trace for which a request must be done
673 * @param timeRange
674 * The time range that will be requested to the state system
675 * @param isGlobal
676 * Tells if the request is for the global event count or the
677 * partial one.
678 */
679 private void buildStatisticsTree(final ITmfTrace trace, final TmfTimeRange timeRange, final boolean isGlobal) {
680 final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
681 if (statsData == null) {
682 return;
683 }
684
685 Map<ITmfTrace, Job> updateJobs;
686 if (isGlobal) {
687 updateJobs = fUpdateJobsGlobal;
688 } else {
689 updateJobs = fUpdateJobsPartial;
690 }
691
692 for (ITmfTrace aTrace : TmfTraceManager.getTraceSet(trace)) {
693 aTrace = checkNotNull(aTrace);
694 if (!isListeningTo(aTrace)) {
695 continue;
696 }
697
698 /* Retrieve the statistics object */
699 final TmfStatisticsModule statsMod = TmfTraceUtils.getAnalysisModuleOfClass(aTrace, TmfStatisticsModule.class, TmfStatisticsModule.ID);
700 if (statsMod == null) {
701 /* No statistics module available for this trace */
702 continue;
703 }
704
705 Job job = updateJobs.get(aTrace);
706 if (job == null) {
707 job = new StatisticsUpdateJob("Statistics update", aTrace, isGlobal, timeRange, statsMod, this); //$NON-NLS-1$
708 updateJobs.put(aTrace, job);
709 job.setSystem(true);
710 job.schedule();
711 }
712 }
713 }
714
715 /**
716 * Resets the number of events within the time range
717 */
718 protected void resetTimeRangeValue() {
719 TmfStatisticsTreeNode treeModelRoot = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID());
720 if (treeModelRoot != null && treeModelRoot.hasChildren()) {
721 treeModelRoot.resetTimeRangeValue();
722 }
723 }
724
725 /**
726 * When the trace is loading the cursor will be different so the user knows
727 * that the processing is not finished yet.
728 *
729 * Calls to this method are stacked.
730 *
731 * @param waitRequested
732 * Indicates if we need to show the waiting cursor, or the
733 * default one.
734 */
735 protected void waitCursor(final boolean waitRequested) {
736 if ((fTreeViewer == null) || (fTreeViewer.getTree().isDisposed())) {
737 return;
738 }
739
740 boolean needsUpdate = false;
741 Display display = fTreeViewer.getControl().getDisplay();
742 if (waitRequested) {
743 fWaitCursorCount++;
744 if (fWaitCursor == null) { // The cursor hasn't been initialized yet
745 fWaitCursor = new Cursor(display, SWT.CURSOR_WAIT);
746 }
747 if (fWaitCursorCount == 1) { // The cursor is not in waiting mode
748 needsUpdate = true;
749 }
750 } else {
751 if (fWaitCursorCount > 0) { // The cursor is in waiting mode
752 fWaitCursorCount--;
753 if (fWaitCursorCount == 0) { // No more reason to wait
754 // Put back the default cursor
755 needsUpdate = true;
756 }
757 }
758 }
759
760 if (needsUpdate) {
761 // Performs the updates on the UI thread
762 display.asyncExec(new Runnable() {
763 @Override
764 public void run() {
765 if ((fTreeViewer != null)
766 && (!fTreeViewer.getTree().isDisposed())) {
767 Cursor cursor = null; // indicates default
768 if (waitRequested) {
769 cursor = fWaitCursor;
770 }
771 fTreeViewer.getControl().setCursor(cursor);
772 }
773 }
774 });
775 }
776 }
777
778 /**
779 * @param isGlobal
780 * if the job to remove is global or partial
781 * @param jobTrace
782 * The trace
783 */
784 void removeFromJobs(boolean isGlobal, ITmfTrace jobTrace) {
785 Map<ITmfTrace, Job> updateJobs = isGlobal ? fUpdateJobsGlobal : fUpdateJobsPartial;
786 Job job = updateJobs.remove(jobTrace);
787 if (job != null) {
788 job.cancel();
789 }
790 }
791 }
This page took 0.051454 seconds and 6 git commands to generate.