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
CommitLineData
cfd22ad0 1/*******************************************************************************
ed902a2b 2 * Copyright (c) 2012, 2015 Ericsson
cfd22ad0
MD
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
89c06060 11 * Alexandre Montplaisir - Port to ITmfStatistics provider
0fcf3b09 12 * Patrick Tasse - Support selection range
12d85f6c 13 * Bernd Hufmann - Fix range selection updates
cfd22ad0
MD
14 *******************************************************************************/
15
1743f395 16package org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics;
cfd22ad0 17
1d83ed07
AM
18import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
19
c14c0757 20import java.util.Collection;
de83d1ab 21import java.util.HashMap;
cfd22ad0 22import java.util.List;
89c06060 23import java.util.Map;
cfd22ad0 24
de83d1ab 25import org.eclipse.core.runtime.jobs.Job;
378e6b92 26import org.eclipse.jface.viewers.StructuredSelection;
cfd22ad0
MD
27import org.eclipse.jface.viewers.TreeViewer;
28import org.eclipse.jface.viewers.TreeViewerColumn;
29import org.eclipse.jface.viewers.Viewer;
30import org.eclipse.jface.viewers.ViewerComparator;
cfd22ad0 31import org.eclipse.swt.SWT;
cdf994ef 32import org.eclipse.swt.custom.SashForm;
cfd22ad0
MD
33import org.eclipse.swt.events.SelectionAdapter;
34import org.eclipse.swt.events.SelectionEvent;
35import org.eclipse.swt.graphics.Color;
36import org.eclipse.swt.graphics.Cursor;
cfd22ad0
MD
37import org.eclipse.swt.widgets.Composite;
38import org.eclipse.swt.widgets.Control;
39import org.eclipse.swt.widgets.Display;
40import org.eclipse.swt.widgets.Event;
41import org.eclipse.swt.widgets.Listener;
2bdf0193
AM
42import org.eclipse.tracecompass.tmf.core.component.TmfComponent;
43import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
97c71024 44import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
cdf994ef 45import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
2bdf0193 46import org.eclipse.tracecompass.tmf.core.signal.TmfTraceRangeUpdatedSignal;
2bdf0193
AM
47import org.eclipse.tracecompass.tmf.core.statistics.TmfStatisticsModule;
48import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
49import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
50import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
21852dfa 51import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
2bdf0193 52import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
b8585c7c 53import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
5c5fa260 54import org.eclipse.tracecompass.tmf.core.trace.experiment.TmfExperiment;
2bdf0193 55import org.eclipse.tracecompass.tmf.ui.viewers.TmfViewer;
378e6b92
ACL
56import org.eclipse.tracecompass.internal.tmf.ui.viewers.piecharts.TmfPieChartViewer;
57import org.eclipse.tracecompass.internal.tmf.ui.viewers.piecharts.model.TmfPieChartStatisticsModel;
58import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfBaseColumnData;
59import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfBaseColumnDataProvider;
60import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsFormatter;
61import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTree;
62import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTreeManager;
63import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfStatisticsTreeNode;
64import org.eclipse.tracecompass.internal.tmf.ui.viewers.statistics.model.TmfTreeContentProvider;
cfd22ad0
MD
65
66/**
67 * A basic viewer to display statistics in the statistics view.
68 *
8b60cb37
MD
69 * It is linked to a single ITmfTrace until its disposal.
70 *
cfd22ad0 71 * @author Mathieu Denis
cfd22ad0 72 */
05627bda 73public class TmfStatisticsViewer extends TmfViewer {
cfd22ad0 74
87f83123
AM
75 /** The actual tree viewer to display */
76 private TreeViewer fTreeViewer;
05627bda 77
87f83123
AM
78 /** Update range synchronization object */
79 private final Object fStatisticsRangeUpdateSyncObj = new Object();
73fbf6be 80
cdf994ef
ACL
81 /** The statistics tree linked to this viewer */
82 private TmfStatisticsTree fStatisticsData;
83
87f83123
AM
84 /** The trace that is displayed by this viewer */
85 private ITmfTrace fTrace;
89c06060 86
87f83123 87 /** Indicates to process all events */
05627bda
MD
88 private boolean fProcessAll;
89
87f83123 90 /** View instance counter (for multiple statistics views) */
cfd22ad0
MD
91 private static int fCountInstance = 0;
92
87f83123 93 /** Number of this instance. Used as an instance ID. */
cfd22ad0
MD
94 private int fInstanceNb;
95
87f83123 96 /** Object to store the cursor while waiting for the trace to load */
cfd22ad0
MD
97 private Cursor fWaitCursor = null;
98
99 /**
05627bda
MD
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
87f83123 106 /** Tells to send a time range request when the trace gets updated. */
05627bda
MD
107 private boolean fSendRangeRequest = true;
108
de83d1ab
MAL
109 private final Map<ITmfTrace, Job> fUpdateJobsPartial = new HashMap<>();
110 private final Map<ITmfTrace, Job> fUpdateJobsGlobal = new HashMap<>();
111
cdf994ef
ACL
112 private TmfPieChartViewer fPieChartViewer;
113
114 private SashForm fSash;
de83d1ab 115
cdf994ef 116 private TmfPieChartStatisticsModel fPieChartModel;
de83d1ab 117
05627bda
MD
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.
cfd22ad0
MD
136 *
137 * @param parent
05627bda
MD
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.
cfd22ad0 143 */
05627bda
MD
144 public void init(Composite parent, String viewerName, ITmfTrace trace) {
145 super.init(parent, viewerName);
cfd22ad0
MD
146 // Increment a counter to make sure the tree ID is unique.
147 fCountInstance++;
148 fInstanceNb = fCountInstance;
05627bda
MD
149 fTrace = trace;
150
faa38350 151 // The viewer will process all events if he is assigned to an experiment
05627bda
MD
152 fProcessAll = (trace instanceof TmfExperiment);
153
154 initContent(parent);
8b60cb37 155 initInput();
05627bda
MD
156 }
157
05627bda
MD
158 @Override
159 public void dispose() {
160 super.dispose();
161 if (fWaitCursor != null) {
162 fWaitCursor.dispose();
163 }
8b60cb37 164
de83d1ab
MAL
165 for (Job j : fUpdateJobsGlobal.values()) {
166 j.cancel();
167 }
168
169 for (Job j : fUpdateJobsPartial.values()) {
170 j.cancel();
171 }
172
66792052 173 // Clean the model for this viewer
36033ff0 174 TmfStatisticsTreeManager.removeStatTreeRoot(getTreeID());
cdf994ef 175 fPieChartViewer.reinitializeCharts();
05627bda
MD
176 }
177
1c0de632
AM
178 // ------------------------------------------------------------------------
179 // Signal handlers
180 // ------------------------------------------------------------------------
89c06060 181
05627bda 182 /**
faa38350 183 * Handles the signal about new trace range.
05627bda
MD
184 *
185 * @param signal
faa38350 186 * The trace range updated signal
05627bda
MD
187 */
188 @TmfSignalHandler
faa38350
PT
189 public void traceRangeUpdated(TmfTraceRangeUpdatedSignal signal) {
190 ITmfTrace trace = signal.getTrace();
05627bda 191 // validate
faa38350 192 if (!isListeningTo(trace)) {
05627bda
MD
193 return;
194 }
195
3c934968
MD
196 synchronized (fStatisticsRangeUpdateSyncObj) {
197 // Sends the time range request only once from this method.
198 if (fSendRangeRequest) {
199 fSendRangeRequest = false;
21852dfa
AM
200
201 TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
202 TmfTimeRange timeRange = ctx.getSelectionRange();
0fcf3b09 203 requestTimeRangeData(trace, timeRange);
3c934968 204 }
05627bda 205 }
faa38350 206 requestData(trace, signal.getRange());
05627bda
MD
207 }
208
0fcf3b09
PT
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.
97c71024 215 * @since 1.0
0fcf3b09
PT
216 */
217 @TmfSignalHandler
97c71024 218 public void timeSynchUpdated(TmfSelectionRangeUpdatedSignal signal) {
faa38350
PT
219 if (fTrace == null) {
220 return;
221 }
0fcf3b09
PT
222 ITmfTimestamp begin = signal.getBeginTime();
223 ITmfTimestamp end = signal.getEndTime();
224 TmfTimeRange timeRange = new TmfTimeRange(begin, end);
225 requestTimeRangeData(fTrace, timeRange);
05627bda
MD
226 }
227
1c0de632
AM
228 // ------------------------------------------------------------------------
229 // Class methods
230 // ------------------------------------------------------------------------
231
05627bda
MD
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() {
cdf994ef 239 return fSash;
05627bda
MD
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
05627bda
MD
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 */
36033ff0 257 public TmfStatisticsTree getStatisticData() {
05627bda 258 if (fStatisticsData == null) {
36033ff0 259 fStatisticsData = new TmfStatisticsTree();
05627bda
MD
260 }
261 return fStatisticsData;
262 }
263
cdf994ef
ACL
264 /**
265 * @return the model of the piecharts in this viewer
266 * @since 2.0
267 */
1904e6a4 268 public TmfPieChartStatisticsModel getPieChartModel() {
cdf994ef
ACL
269 if (fPieChartModel == null) {
270 fPieChartModel = new TmfPieChartStatisticsModel();
1904e6a4
ACL
271 }
272 return fPieChartModel;
cdf994ef
ACL
273 }
274
05627bda
MD
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 }
cdf994ef
ACL
292 refreshTree();
293 refreshPieCharts(true, true);
294 }
295
296 /**
297 * Only refreshes the Tree viewer
298 */
1904e6a4 299 private void refreshTree() {
cdf994ef
ACL
300 final Control viewerControl = getControl();
301 // Ignore update if disposed
302 if (viewerControl.isDisposed()) {
303 return;
304 }
05627bda 305
cdf994ef 306 Display.getDefault().asyncExec(new Runnable() {
05627bda
MD
307 @Override
308 public void run() {
309 if (!viewerControl.isDisposed()) {
310 fTreeViewer.refresh();
311 }
312 }
313 });
314 }
315
cdf994ef
ACL
316 /**
317 * Only refreshes the piecharts depending on the parameters
1904e6a4
ACL
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
cdf994ef
ACL
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
3c934968
MD
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
05627bda
MD
351 /**
352 * Focus on the statistics tree of the viewer
353 */
354 public void setFocus() {
355 fTreeViewer.getTree().setFocus();
356 }
357
05627bda
MD
358 /**
359 * Cancels the request if it is not already completed
360 *
361 * @param request
362 * The request to be canceled
363 */
fd3f1eff 364 protected void cancelOngoingRequest(ITmfEventRequest request) {
05627bda
MD
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 *
b3a26928 374 * @return An object of type {@link TmfBaseColumnDataProvider}.
05627bda 375 */
b3a26928 376 protected TmfBaseColumnDataProvider getColumnDataProvider() {
05627bda
MD
377 return new TmfBaseColumnDataProvider();
378 }
cfd22ad0 379
05627bda
MD
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) {
cdf994ef 387
cfd22ad0 388 final List<TmfBaseColumnData> columnDataList = getColumnDataProvider().getColumnData();
cfd22ad0 389
1904e6a4 390 fSash = new SashForm(parent, SWT.HORIZONTAL);
cdf994ef
ACL
391
392 fTreeViewer = new TreeViewer(fSash, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
393 fPieChartViewer = new TmfPieChartViewer(fSash);
378e6b92
ACL
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 });
cdf994ef 417
cfd22ad0
MD
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
df2b3dbb
VP
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) {
cfd22ad0
MD
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 /*
df2b3dbb
VP
456 * Puts the descendant order if the old order was up
457 * or if the selected column has changed.
cfd22ad0
MD
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
df2b3dbb 476 // Handler that will draw the percentages and the bar charts.
cfd22ad0
MD
477 fTreeViewer.getTree().addListener(SWT.EraseItem, new Listener() {
478 @Override
479 public void handleEvent(Event event) {
480 if (columnDataList.get(event.index).getPercentageProvider() != null) {
df2b3dbb 481
cfd22ad0
MD
482 TmfStatisticsTreeNode node = (TmfStatisticsTreeNode) event.item.getData();
483
df2b3dbb
VP
484 // If node is hidden, exit immediately.
485 if (TmfBaseColumnDataProvider.HIDDEN_FOLDER_LEVELS.contains(node.getName())) {
cfd22ad0
MD
486 return;
487 }
488
1904e6a4
ACL
489 // Otherwise, get percentage and draw bar and text if
490 // applicable.
df2b3dbb
VP
491 double percentage = columnDataList.get(event.index).getPercentageProvider().getPercentage(node);
492
493 // The item is selected.
494 if ((event.detail & SWT.SELECTED) > 0) {
1904e6a4
ACL
495 // Draws our own background to avoid overwriting the
496 // bar.
cfd22ad0
MD
497 event.gc.fillRectangle(event.x, event.y, event.width, event.height);
498 event.detail &= ~SWT.SELECTED;
499 }
500
df2b3dbb
VP
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 }
cfd22ad0
MD
553 }
554 }
df2b3dbb 555
cfd22ad0
MD
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
8b60cb37
MD
564 /**
565 * Initializes the input for the tree viewer.
8b60cb37
MD
566 */
567 protected void initInput() {
568 String treeID = getTreeID();
faa38350 569 TmfStatisticsTreeNode statisticsTreeNode;
36033ff0 570 if (TmfStatisticsTreeManager.containsTreeRoot(treeID)) {
faa38350
PT
571 // The statistics root is already present
572 statisticsTreeNode = TmfStatisticsTreeManager.getStatTreeRoot(treeID);
8b60cb37
MD
573
574 // Checks if the trace is already in the statistics tree.
faa38350 575 int numNodeTraces = statisticsTreeNode.getNbChildren();
8b60cb37 576
c14c0757
GB
577 Collection<ITmfTrace> traces = TmfTraceManager.getTraceSet(fTrace);
578 int numTraces = traces.size();
8b60cb37
MD
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 */
c14c0757
GB
586 for (ITmfTrace trace : traces) {
587 String traceName = trace.getName();
faa38350 588 if (!statisticsTreeNode.containsChild(traceName)) {
8b60cb37
MD
589 same = false;
590 break;
591 }
592 }
593
594 if (same) {
595 // No need to reload data, all traces are already loaded
faa38350 596 fTreeViewer.setInput(statisticsTreeNode);
8b60cb37
MD
597 return;
598 }
599 // Clears the old content to start over
faa38350 600 statisticsTreeNode.reset();
8b60cb37
MD
601 }
602 } else {
603 // Creates a new tree
faa38350 604 statisticsTreeNode = TmfStatisticsTreeManager.addStatsTreeRoot(treeID, getStatisticData());
8b60cb37
MD
605 }
606
607 // Sets the input to a clean data model
faa38350 608 fTreeViewer.setInput(statisticsTreeNode);
cdf994ef
ACL
609 /* Set a new model for the piecharts and keep a reference */
610 fPieChartViewer.setInput(getPieChartModel());
8b60cb37
MD
611 }
612
cfd22ad0 613 /**
faa38350 614 * Tells if the viewer is listening to a trace.
cfd22ad0 615 *
1c0de632 616 * @param trace
05627bda
MD
617 * The trace that the viewer may be listening
618 * @return true if the viewer is listening to the trace, false otherwise
cfd22ad0 619 */
1c0de632
AM
620 protected boolean isListeningTo(ITmfTrace trace) {
621 if (fProcessAll || trace == fTrace) {
05627bda 622 return true;
cfd22ad0 623 }
05627bda 624 return false;
cfd22ad0
MD
625 }
626
627 /**
faa38350 628 * Called when an trace request has been completed successfully.
cfd22ad0 629 *
05627bda
MD
630 * @param global
631 * Tells if the request is a global or time range (partial)
632 * request.
cfd22ad0 633 */
05627bda 634 protected void modelComplete(boolean global) {
cdf994ef 635 refreshTree();
05627bda 636 waitCursor(false);
cfd22ad0
MD
637 }
638
639 /**
faa38350 640 * Sends the request to the trace for the whole trace
cfd22ad0 641 *
faa38350
PT
642 * @param trace
643 * The trace used to send the request
8b260d9f 644 * @param timeRange
faa38350 645 * The range to request to the trace
cfd22ad0 646 */
faa38350
PT
647 protected void requestData(final ITmfTrace trace, final TmfTimeRange timeRange) {
648 buildStatisticsTree(trace, timeRange, true);
cfd22ad0
MD
649 }
650
651 /**
faa38350 652 * Sends the time range request from the trace
cfd22ad0 653 *
faa38350
PT
654 * @param trace
655 * The trace used to send the request
8b260d9f 656 * @param timeRange
faa38350 657 * The range to request to the trace
cfd22ad0 658 */
faa38350 659 protected void requestTimeRangeData(final ITmfTrace trace, final TmfTimeRange timeRange) {
faa38350 660 buildStatisticsTree(trace, timeRange, false);
89c06060
AM
661 }
662
663 /**
df2b3dbb
VP
664 * Requests all the data of the trace to the state system which contains
665 * information about the statistics.
89c06060 666 *
df2b3dbb
VP
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
89c06060
AM
669 * method {@link #isListeningTo(String trace)}.
670 *
faa38350
PT
671 * @param trace
672 * The trace for which a request must be done
89c06060
AM
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 */
d6b46913 679 private void buildStatisticsTree(final ITmfTrace trace, final TmfTimeRange timeRange, final boolean isGlobal) {
36033ff0 680 final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
89c06060
AM
681 if (statsData == null) {
682 return;
683 }
684
de83d1ab
MAL
685 Map<ITmfTrace, Job> updateJobs;
686 if (isGlobal) {
687 updateJobs = fUpdateJobsGlobal;
de83d1ab
MAL
688 } else {
689 updateJobs = fUpdateJobsPartial;
de83d1ab 690 }
89c06060 691
1d83ed07
AM
692 for (ITmfTrace aTrace : TmfTraceManager.getTraceSet(trace)) {
693 aTrace = checkNotNull(aTrace);
de83d1ab
MAL
694 if (!isListeningTo(aTrace)) {
695 continue;
696 }
d6b46913 697
de83d1ab 698 /* Retrieve the statistics object */
b8585c7c 699 final TmfStatisticsModule statsMod = TmfTraceUtils.getAnalysisModuleOfClass(aTrace, TmfStatisticsModule.class, TmfStatisticsModule.ID);
de83d1ab
MAL
700 if (statsMod == null) {
701 /* No statistics module available for this trace */
702 continue;
703 }
55954069 704
de83d1ab
MAL
705 Job job = updateJobs.get(aTrace);
706 if (job == null) {
cdf994ef 707 job = new StatisticsUpdateJob("Statistics update", aTrace, isGlobal, timeRange, statsMod, this); //$NON-NLS-1$
de83d1ab
MAL
708 updateJobs.put(aTrace, job);
709 job.setSystem(true);
710 job.schedule();
89c06060 711 }
89c06060 712 }
cfd22ad0
MD
713 }
714
715 /**
05627bda 716 * Resets the number of events within the time range
cfd22ad0 717 */
05627bda 718 protected void resetTimeRangeValue() {
36033ff0 719 TmfStatisticsTreeNode treeModelRoot = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID());
05627bda
MD
720 if (treeModelRoot != null && treeModelRoot.hasChildren()) {
721 treeModelRoot.resetTimeRangeValue();
722 }
cfd22ad0
MD
723 }
724
725 /**
df2b3dbb
VP
726 * When the trace is loading the cursor will be different so the user knows
727 * that the processing is not finished yet.
05627bda
MD
728 *
729 * Calls to this method are stacked.
cfd22ad0 730 *
05627bda 731 * @param waitRequested
cfd22ad0 732 * Indicates if we need to show the waiting cursor, or the
05627bda 733 * default one.
cfd22ad0 734 */
05627bda 735 protected void waitCursor(final boolean waitRequested) {
cfd22ad0
MD
736 if ((fTreeViewer == null) || (fTreeViewer.getTree().isDisposed())) {
737 return;
738 }
739
05627bda 740 boolean needsUpdate = false;
cfd22ad0 741 Display display = fTreeViewer.getControl().getDisplay();
05627bda
MD
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 }
cfd22ad0
MD
758 }
759
05627bda
MD
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);
cfd22ad0 772 }
cfd22ad0 773 }
05627bda
MD
774 });
775 }
cfd22ad0 776 }
cdf994ef
ACL
777
778 /**
1904e6a4
ACL
779 * @param isGlobal
780 * if the job to remove is global or partial
781 * @param jobTrace
782 * The trace
cdf994ef
ACL
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 }
cfd22ad0 791}
This page took 0.118206 seconds and 5 git commands to generate.