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