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