34c9718ab23d7b84d41c59c57aeb12849e317f14
[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 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
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 TmfPieChartStatisticsModel pieChartModel = getPieChartModel();
333 if (pieChartModel == null || pieChartModel.getPieChartGlobalModel() == null) {
334 return;
335 }
336 /* If there's only one event type, don't show any piechart */
337 boolean moreThanOne = false;
338 for (Entry<ITmfTrace, Map<String, Long>> entry : pieChartModel.getPieChartGlobalModel().entrySet()) {
339 if(entry.getValue() != null && entry.getValue().size() > 1) {
340 moreThanOne = true;
341 break;
342 }
343 }
344
345 setPieChartsVisible(moreThanOne);
346
347 Display.getDefault().asyncExec(new Runnable() {
348 @Override
349 public void run() {
350 if (!viewerControl.isDisposed()) {
351 fPieChartViewer.refresh(refreshGlobal, refreshSelection);
352 }
353 }
354 });
355 }
356
357 /**
358 * Will force a request on the partial event count if one is needed.
359 */
360 public void sendPartialRequestOnNextUpdate() {
361 synchronized (fStatisticsRangeUpdateSyncObj) {
362 fSendRangeRequest = true;
363 }
364 }
365
366 /**
367 * Focus on the statistics tree of the viewer
368 */
369 public void setFocus() {
370 fTreeViewer.getTree().setFocus();
371 }
372
373 /**
374 * Cancels the request if it is not already completed
375 *
376 * @param request
377 * The request to be canceled
378 */
379 protected void cancelOngoingRequest(ITmfEventRequest request) {
380 if (request != null && !request.isCompleted()) {
381 request.cancel();
382 }
383 }
384
385 /**
386 * This method can be overridden to change the representation of the data in
387 * the columns.
388 *
389 * @return An object of type {@link TmfBaseColumnDataProvider}.
390 */
391 protected TmfBaseColumnDataProvider getColumnDataProvider() {
392 return new TmfBaseColumnDataProvider();
393 }
394
395 /**
396 * Initialize the content that will be drawn in this viewer
397 *
398 * @param parent
399 * The parent of the control to create
400 */
401 protected void initContent(Composite parent) {
402
403 final List<TmfBaseColumnData> columnDataList = getColumnDataProvider().getColumnData();
404
405 fSash = new SashForm(parent, SWT.HORIZONTAL);
406
407 fTreeViewer = new TreeViewer(fSash, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
408 fPieChartViewer = new TmfPieChartViewer(fSash);
409 fPieChartViewer.addEventTypeSelectionListener(new Listener() {
410
411 @Override
412 public void handleEvent(Event event) {
413 String eventTypeName = event.text;
414 if (getStatisticData().getRootNode() == null ||
415 fTreeViewer.getTree() == null) {
416 return;
417 }
418 /* Get all the nodes corresponding to the event name */
419 List<TmfStatisticsTreeNode> nodes = (List<TmfStatisticsTreeNode>) getStatisticData().getRootNode().findChildren(eventTypeName, true);
420 if (nodes.isEmpty()) {
421 /* Shouldn't happen, except for when selecting "Others" */
422 return;
423 }
424 /* Only select the first in the collection */
425 fTreeViewer.setSelection(new StructuredSelection(nodes.get(0)), true);
426 }
427 });
428
429 /* Make sure the sash is split in 2 equal parts */
430 fSash.setWeights(new int[] { 100, 100 });
431
432 fTreeViewer.setContentProvider(new TmfTreeContentProvider());
433 fTreeViewer.getTree().setHeaderVisible(true);
434 fTreeViewer.setUseHashlookup(true);
435
436 // Creates the columns defined by the column data provider
437 for (final TmfBaseColumnData columnData : columnDataList) {
438 final TreeViewerColumn treeColumn = new TreeViewerColumn(fTreeViewer, columnData.getAlignment());
439 treeColumn.getColumn().setText(columnData.getHeader());
440 treeColumn.getColumn().setWidth(columnData.getWidth());
441 treeColumn.getColumn().setToolTipText(columnData.getTooltip());
442
443 // If is dummy column
444 if (columnData == columnDataList.get(TmfBaseColumnDataProvider.StatsColumn.DUMMY.getIndex())) {
445 treeColumn.getColumn().setResizable(false);
446 }
447
448 // A comparator is defined.
449 if (columnData.getComparator() != null) {
450 // Adds a listener on the columns header for sorting purpose.
451 treeColumn.getColumn().addSelectionListener(new SelectionAdapter() {
452
453 private ViewerComparator reverseComparator;
454
455 @Override
456 public void widgetSelected(SelectionEvent e) {
457 // Initializes the reverse comparator once.
458 if (reverseComparator == null) {
459 reverseComparator = new ViewerComparator() {
460 @Override
461 public int compare(Viewer viewer, Object e1, Object e2) {
462 return -1 * columnData.getComparator().compare(viewer, e1, e2);
463 }
464 };
465 }
466
467 if (fTreeViewer.getTree().getSortDirection() == SWT.UP
468 || fTreeViewer.getTree().getSortColumn() != treeColumn.getColumn()) {
469 /*
470 * Puts the descendant order if the old order was up
471 * or if the selected column has changed.
472 */
473 fTreeViewer.setComparator(columnData.getComparator());
474 fTreeViewer.getTree().setSortDirection(SWT.DOWN);
475 } else {
476 /*
477 * Puts the ascendant ordering if the selected
478 * column hasn't changed.
479 */
480 fTreeViewer.setComparator(reverseComparator);
481 fTreeViewer.getTree().setSortDirection(SWT.UP);
482 }
483 fTreeViewer.getTree().setSortColumn(treeColumn.getColumn());
484 }
485 });
486 }
487 treeColumn.setLabelProvider(columnData.getLabelProvider());
488 }
489
490 // Handler that will draw the percentages and the bar charts.
491 fTreeViewer.getTree().addListener(SWT.EraseItem, new Listener() {
492 @Override
493 public void handleEvent(Event event) {
494 if (columnDataList.get(event.index).getPercentageProvider() != null) {
495
496 TmfStatisticsTreeNode node = (TmfStatisticsTreeNode) event.item.getData();
497
498 // If node is hidden, exit immediately.
499 if (TmfBaseColumnDataProvider.HIDDEN_FOLDER_LEVELS.contains(node.getName())) {
500 return;
501 }
502
503 // Otherwise, get percentage and draw bar and text if
504 // applicable.
505 double percentage = columnDataList.get(event.index).getPercentageProvider().getPercentage(node);
506
507 // The item is selected.
508 if ((event.detail & SWT.SELECTED) > 0) {
509 // Draws our own background to avoid overwriting the
510 // bar.
511 event.gc.fillRectangle(event.x, event.y, event.width, event.height);
512 event.detail &= ~SWT.SELECTED;
513 }
514
515 // Drawing the percentage text
516 // if events are present in top node
517 // and the current node is not the top node
518 // and if is total or partial events column.
519 // If not, exit the method.
520 if (!((event.index == TmfBaseColumnDataProvider.StatsColumn.TOTAL.getIndex() || event.index == TmfBaseColumnDataProvider.StatsColumn.PARTIAL.getIndex())
521 && node != node.getTop())) {
522 return;
523 }
524
525 long eventValue = event.index == TmfBaseColumnDataProvider.StatsColumn.TOTAL.getIndex() ?
526 node.getTop().getValues().getTotal() : node.getTop().getValues().getPartial();
527
528 if (eventValue != 0) {
529
530 int oldAlpha = event.gc.getAlpha();
531 Color oldForeground = event.gc.getForeground();
532 Color oldBackground = event.gc.getBackground();
533
534 // Bar to draw
535 if (percentage != 0) {
536 /*
537 * Draws a transparent gradient rectangle from the
538 * color of foreground and background.
539 */
540 int barWidth = (int) ((fTreeViewer.getTree().getColumn(event.index).getWidth() - 8) * percentage);
541 event.gc.setAlpha(64);
542 event.gc.setForeground(event.item.getDisplay().getSystemColor(SWT.COLOR_BLUE));
543 event.gc.setBackground(event.item.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
544 event.gc.fillGradientRectangle(event.x, event.y, barWidth, event.height, true);
545 event.gc.drawRectangle(event.x, event.y, barWidth, event.height);
546
547 // Restore old values
548 event.gc.setBackground(oldBackground);
549 event.gc.setAlpha(oldAlpha);
550 event.detail &= ~SWT.BACKGROUND;
551
552 }
553
554 String percentageText = TmfStatisticsFormatter.toPercentageText(percentage);
555 String absoluteNumberText = TmfStatisticsFormatter.toColumnData(node, TmfBaseColumnDataProvider.StatsColumn.getColumn(event.index));
556
557 if (event.width > event.gc.stringExtent(percentageText).x + event.gc.stringExtent(absoluteNumberText).x) {
558 int textHeight = event.gc.stringExtent(percentageText).y;
559 event.gc.setForeground(event.item.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
560 event.gc.drawText(percentageText, event.x, event.y + (event.height - textHeight) / 2, true);
561 }
562
563 // Restores old values
564 event.gc.setForeground(oldForeground);
565
566 }
567 }
568 }
569
570 });
571
572 // Initializes the comparator parameters
573 fTreeViewer.setComparator(columnDataList.get(0).getComparator());
574 fTreeViewer.getTree().setSortColumn(fTreeViewer.getTree().getColumn(0));
575 fTreeViewer.getTree().setSortDirection(SWT.DOWN);
576 }
577
578 /**
579 * Initializes the input for the tree viewer.
580 */
581 protected void initInput() {
582 String treeID = getTreeID();
583 TmfStatisticsTreeNode statisticsTreeNode;
584 if (TmfStatisticsTreeManager.containsTreeRoot(treeID)) {
585 // The statistics root is already present
586 statisticsTreeNode = TmfStatisticsTreeManager.getStatTreeRoot(treeID);
587
588 // Checks if the trace is already in the statistics tree.
589 int numNodeTraces = statisticsTreeNode.getNbChildren();
590
591 Collection<ITmfTrace> traces = TmfTraceManager.getTraceSet(fTrace);
592 int numTraces = traces.size();
593
594 if (numTraces == numNodeTraces) {
595 boolean same = true;
596 /*
597 * Checks if the experiment contains the same traces as when
598 * previously selected.
599 */
600 for (ITmfTrace trace : traces) {
601 String traceName = trace.getName();
602 if (!statisticsTreeNode.containsChild(traceName)) {
603 same = false;
604 break;
605 }
606 }
607
608 if (same) {
609 // No need to reload data, all traces are already loaded
610 fTreeViewer.setInput(statisticsTreeNode);
611 return;
612 }
613 // Clears the old content to start over
614 statisticsTreeNode.reset();
615 }
616 } else {
617 // Creates a new tree
618 statisticsTreeNode = TmfStatisticsTreeManager.addStatsTreeRoot(treeID, getStatisticData());
619 }
620
621 // Sets the input to a clean data model
622 fTreeViewer.setInput(statisticsTreeNode);
623 /* Set a new model for the piecharts and keep a reference */
624 fPieChartViewer.setInput(getPieChartModel());
625 }
626
627 /**
628 * Tells if the viewer is listening to a trace.
629 *
630 * @param trace
631 * The trace that the viewer may be listening
632 * @return true if the viewer is listening to the trace, false otherwise
633 */
634 protected boolean isListeningTo(ITmfTrace trace) {
635 if (fProcessAll || trace == fTrace) {
636 return true;
637 }
638 return false;
639 }
640
641 /**
642 * Called when an trace request has been completed successfully.
643 *
644 * @param global
645 * Tells if the request is a global or time range (partial)
646 * request.
647 */
648 protected void modelComplete(boolean global) {
649 refreshTree();
650 waitCursor(false);
651 }
652
653 /**
654 * Sends the request to the trace for the whole trace
655 *
656 * @param trace
657 * The trace used to send the request
658 * @param timeRange
659 * The range to request to the trace
660 */
661 protected void requestData(final ITmfTrace trace, final TmfTimeRange timeRange) {
662 buildStatisticsTree(trace, timeRange, true);
663 }
664
665 /**
666 * Sends the time range request from the trace
667 *
668 * @param trace
669 * The trace used to send the request
670 * @param timeRange
671 * The range to request to the trace
672 */
673 protected void requestTimeRangeData(final ITmfTrace trace, final TmfTimeRange timeRange) {
674 buildStatisticsTree(trace, timeRange, false);
675 }
676
677 /**
678 * Requests all the data of the trace to the state system which contains
679 * information about the statistics.
680 *
681 * Since the viewer may be listening to multiple traces, it may receive an
682 * experiment rather than a single trace. The filtering is done with the
683 * method {@link #isListeningTo(String trace)}.
684 *
685 * @param trace
686 * The trace for which a request must be done
687 * @param timeRange
688 * The time range that will be requested to the state system
689 * @param isGlobal
690 * Tells if the request is for the global event count or the
691 * partial one.
692 */
693 private void buildStatisticsTree(final ITmfTrace trace, final TmfTimeRange timeRange, final boolean isGlobal) {
694 final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
695 if (statsData == null) {
696 return;
697 }
698
699 Map<ITmfTrace, Job> updateJobs;
700 if (isGlobal) {
701 updateJobs = fUpdateJobsGlobal;
702 } else {
703 updateJobs = fUpdateJobsPartial;
704 }
705
706 for (ITmfTrace aTrace : TmfTraceManager.getTraceSet(trace)) {
707 if (!isListeningTo(aTrace)) {
708 continue;
709 }
710
711 /* Retrieve the statistics object */
712 final TmfStatisticsModule statsMod = TmfTraceUtils.getAnalysisModuleOfClass(aTrace, TmfStatisticsModule.class, TmfStatisticsModule.ID);
713 if (statsMod == null) {
714 /* No statistics module available for this trace */
715 continue;
716 }
717
718 Job job = updateJobs.get(aTrace);
719 if (job == null) {
720 job = new StatisticsUpdateJob("Statistics update", aTrace, isGlobal, timeRange, statsMod, this); //$NON-NLS-1$
721 updateJobs.put(aTrace, job);
722 job.setSystem(true);
723 job.schedule();
724 }
725 }
726 }
727
728 private void setPieChartsVisible(final boolean visible) {
729 if (fPieChartViewer.isDisposed()) {
730 return;
731 }
732 TmfUiRefreshHandler.getInstance().queueUpdate(fPieChartViewer, new Runnable() {
733 @Override
734 public void run() {
735 if (!fPieChartViewer.isDisposed()) {
736 fPieChartViewer.setVisible(visible);
737 fPieChartViewer.getParent().layout();
738 }
739 }
740 });
741 }
742
743 /**
744 * Resets the number of events within the time range
745 */
746 protected void resetTimeRangeValue() {
747 TmfStatisticsTreeNode treeModelRoot = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID());
748 if (treeModelRoot != null && treeModelRoot.hasChildren()) {
749 treeModelRoot.resetTimeRangeValue();
750 }
751 }
752
753 /**
754 * When the trace is loading the cursor will be different so the user knows
755 * that the processing is not finished yet.
756 *
757 * Calls to this method are stacked.
758 *
759 * @param waitRequested
760 * Indicates if we need to show the waiting cursor, or the
761 * default one.
762 */
763 protected void waitCursor(final boolean waitRequested) {
764 if ((fTreeViewer == null) || (fTreeViewer.getTree().isDisposed())) {
765 return;
766 }
767
768 boolean needsUpdate = false;
769 Display display = fTreeViewer.getControl().getDisplay();
770 if (waitRequested) {
771 fWaitCursorCount++;
772 if (fWaitCursor == null) { // The cursor hasn't been initialized yet
773 fWaitCursor = new Cursor(display, SWT.CURSOR_WAIT);
774 }
775 if (fWaitCursorCount == 1) { // The cursor is not in waiting mode
776 needsUpdate = true;
777 }
778 } else {
779 if (fWaitCursorCount > 0) { // The cursor is in waiting mode
780 fWaitCursorCount--;
781 if (fWaitCursorCount == 0) { // No more reason to wait
782 // Put back the default cursor
783 needsUpdate = true;
784 }
785 }
786 }
787
788 if (needsUpdate) {
789 // Performs the updates on the UI thread
790 display.asyncExec(new Runnable() {
791 @Override
792 public void run() {
793 if ((fTreeViewer != null)
794 && (!fTreeViewer.getTree().isDisposed())) {
795 Cursor cursor = null; // indicates default
796 if (waitRequested) {
797 cursor = fWaitCursor;
798 }
799 fTreeViewer.getControl().setCursor(cursor);
800 }
801 }
802 });
803 }
804 }
805
806 /**
807 * @param isGlobal
808 * if the job to remove is global or partial
809 * @param jobTrace
810 * The trace
811 */
812 void removeFromJobs(boolean isGlobal, ITmfTrace jobTrace) {
813 Map<ITmfTrace, Job> updateJobs = isGlobal ? fUpdateJobsGlobal : fUpdateJobsPartial;
814 Job job = updateJobs.remove(jobTrace);
815 if (job != null) {
816 job.cancel();
817 }
818 }
819 }
This page took 0.075735 seconds and 5 git commands to generate.