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