Implement MultiLineInputDialog for Add Bookmark action.
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / viewers / statistics / TmfStatisticsViewer.java
CommitLineData
cfd22ad0
MD
1/*******************************************************************************
2 * Copyright (c) 2012 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
89c06060 11 * Alexandre Montplaisir - Port to ITmfStatistics provider
cfd22ad0
MD
12 *******************************************************************************/
13
14package org.eclipse.linuxtools.tmf.ui.viewers.statistics;
15
16import java.util.List;
89c06060 17import java.util.Map;
cfd22ad0
MD
18
19import org.eclipse.jface.viewers.TreeViewer;
20import org.eclipse.jface.viewers.TreeViewerColumn;
21import org.eclipse.jface.viewers.Viewer;
22import org.eclipse.jface.viewers.ViewerComparator;
23import org.eclipse.linuxtools.tmf.core.component.TmfComponent;
89c06060 24import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
05627bda
MD
25import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
26import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
27import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
28import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentRangeUpdatedSignal;
05627bda
MD
29import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
30import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
89c06060 31import org.eclipse.linuxtools.tmf.core.signal.TmfStateSystemBuildCompleted;
1c0de632 32import org.eclipse.linuxtools.tmf.core.signal.TmfStatsUpdatedSignal;
89c06060 33import org.eclipse.linuxtools.tmf.core.statistics.ITmfStatistics;
1c0de632 34import org.eclipse.linuxtools.tmf.core.statistics.TmfStateStatistics;
05627bda
MD
35import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
36import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
37import org.eclipse.linuxtools.tmf.ui.viewers.TmfViewer;
cfd22ad0
MD
38import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.ITmfColumnDataProvider;
39import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseColumnData;
40import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfBaseColumnDataProvider;
36033ff0
AM
41import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTree;
42import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeManager;
cfd22ad0 43import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfStatisticsTreeNode;
cfd22ad0
MD
44import org.eclipse.linuxtools.tmf.ui.viewers.statistics.model.TmfTreeContentProvider;
45import org.eclipse.swt.SWT;
46import org.eclipse.swt.events.SelectionAdapter;
47import org.eclipse.swt.events.SelectionEvent;
48import org.eclipse.swt.graphics.Color;
49import org.eclipse.swt.graphics.Cursor;
cfd22ad0
MD
50import org.eclipse.swt.widgets.Composite;
51import org.eclipse.swt.widgets.Control;
52import org.eclipse.swt.widgets.Display;
53import org.eclipse.swt.widgets.Event;
54import org.eclipse.swt.widgets.Listener;
55
56/**
57 * A basic viewer to display statistics in the statistics view.
58 *
8b60cb37
MD
59 * It is linked to a single ITmfTrace until its disposal.
60 *
cfd22ad0
MD
61 * @author Mathieu Denis
62 * @version 2.0
63 * @since 2.0
64 */
05627bda 65public class TmfStatisticsViewer extends TmfViewer {
cfd22ad0
MD
66
67 /**
05627bda 68 * The initial window span (in nanoseconds)
cfd22ad0 69 */
05627bda
MD
70 public static final long INITIAL_WINDOW_SPAN = (1L * 100 * 1000 * 1000); // .1sec
71
72 /**
73 * Timestamp scale (nanosecond)
74 */
75 public static final byte TIME_SCALE = -9;
76
77 /**
78 * Default PAGE_SIZE for background requests.
79 */
80 protected static final int PAGE_SIZE = 50000;
81
82 /**
83 * Refresh frequency.
84 */
85 protected final Long STATS_INPUT_CHANGED_REFRESH = 5000L;
86
cfd22ad0
MD
87 /**
88 * The actual tree viewer to display
89 */
90 protected TreeViewer fTreeViewer;
91
92 /**
05627bda
MD
93 * The statistics tree linked to this viewer
94 */
36033ff0 95 protected TmfStatisticsTree fStatisticsData;
05627bda
MD
96
97 /**
98 * Update synchronization parameter (used for streaming): Update busy
99 * indicator.
100 */
101 protected boolean fStatisticsUpdateBusy = false;
102
103 /**
104 * Update synchronization parameter (used for streaming): Update pending
105 * indicator.
106 */
107 protected boolean fStatisticsUpdatePending = false;
108
109 /**
110 * Update synchronization parameter (used for streaming): Pending Update
111 * time range.
112 */
113 protected TmfTimeRange fStatisticsUpdateRange = null;
114
115 /**
116 * Update synchronization object.
117 */
118 protected final Object fStatisticsUpdateSyncObj = new Object();
119
3c934968
MD
120 /**
121 * Update range synchronization object.
122 */
123 protected final Object fStatisticsRangeUpdateSyncObj = new Object();
124
89c06060 125 /**
73fbf6be
MD
126 * The trace that is displayed by this viewer
127 */
128 protected ITmfTrace fTrace;
129
89c06060
AM
130 /**
131 * Stores the requested time range.
132 */
133 protected TmfTimeRange fRequestedTimerange;
134
05627bda
MD
135 /**
136 * Indicates to process all events
137 */
138 private boolean fProcessAll;
139
140 /**
141 * View instance counter (for multiple statistics views)
cfd22ad0
MD
142 */
143 private static int fCountInstance = 0;
144
145 /**
146 * Number of this instance. Used as an instance ID.
147 */
148 private int fInstanceNb;
149
150 /**
151 * Object to store the cursor while waiting for the experiment to load
152 */
153 private Cursor fWaitCursor = null;
154
155 /**
05627bda
MD
156 * Counts the number of times waitCursor() has been called. It avoids
157 * removing the waiting cursor, since there may be multiple requests running
158 * at the same time.
159 */
160 private int fWaitCursorCount = 0;
161
162 /**
163 * Tells to send a time range request when the experiment gets updated.
164 */
165 private boolean fSendRangeRequest = true;
166
167 /**
168 * Empty constructor. To be used in conjunction with
169 * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
170 */
171 public TmfStatisticsViewer() {
172 super();
173 }
174
175 /**
176 * Create a basic statistics viewer. To be used in conjunction with
177 * {@link TmfStatisticsViewer#init(Composite, String, ITmfTrace)}
178 *
179 * @param parent
180 * The parent composite that will hold the viewer
181 * @param viewerName
182 * The name that will be assigned to this viewer
183 * @param trace
184 * The trace that is displayed by this viewer
185 * @see TmfComponent
186 */
187 public TmfStatisticsViewer(Composite parent, String viewerName, ITmfTrace trace) {
188 init(parent, viewerName, trace);
189 }
190
191 /**
192 * Initialize the statistics viewer.
cfd22ad0
MD
193 *
194 * @param parent
05627bda
MD
195 * The parent component of the viewer.
196 * @param viewerName
197 * The name to give to the viewer.
198 * @param trace
199 * The trace that will be displayed by the viewer.
cfd22ad0 200 */
05627bda
MD
201 public void init(Composite parent, String viewerName, ITmfTrace trace) {
202 super.init(parent, viewerName);
cfd22ad0
MD
203 // Increment a counter to make sure the tree ID is unique.
204 fCountInstance++;
205 fInstanceNb = fCountInstance;
05627bda
MD
206 fTrace = trace;
207
208 // The viewer will process all events if he is assigned to the experiment
209 fProcessAll = (trace instanceof TmfExperiment);
210
211 initContent(parent);
8b60cb37 212 initInput();
05627bda
MD
213 }
214
215 /*
216 * (non-Javadoc)
217 *
218 * @see org.eclipse.linuxtools.tmf.core.component.TmfComponent#dispose()
219 */
220 @Override
221 public void dispose() {
222 super.dispose();
223 if (fWaitCursor != null) {
224 fWaitCursor.dispose();
225 }
8b60cb37 226
66792052 227 // Clean the model for this viewer
36033ff0 228 TmfStatisticsTreeManager.removeStatTreeRoot(getTreeID());
05627bda
MD
229 }
230
1c0de632
AM
231 // ------------------------------------------------------------------------
232 // Signal handlers
233 // ------------------------------------------------------------------------
89c06060 234
05627bda
MD
235 /**
236 * Handles the signal about new experiment range.
237 *
238 * @param signal
239 * The experiment range updated signal
240 */
241 @TmfSignalHandler
242 public void experimentRangeUpdated(TmfExperimentRangeUpdatedSignal signal) {
243 TmfExperiment experiment = signal.getExperiment();
244 // validate
245 if (!experiment.equals(TmfExperiment.getCurrentExperiment())) {
246 return;
247 }
248
3c934968
MD
249 synchronized (fStatisticsRangeUpdateSyncObj) {
250 // Sends the time range request only once from this method.
251 if (fSendRangeRequest) {
252 fSendRangeRequest = false;
253 // Calculate the selected time range to request
254 long startTime = signal.getRange().getStartTime().normalize(0, TIME_SCALE).getValue();
255 TmfTimestamp startTS = new TmfTimestamp(startTime, TIME_SCALE);
256 TmfTimestamp endTS = new TmfTimestamp(startTime + INITIAL_WINDOW_SPAN, TIME_SCALE);
257 TmfTimeRange timeRange = new TmfTimeRange(startTS, endTS);
258
259 requestTimeRangeData(experiment, timeRange);
260 }
05627bda
MD
261 }
262 requestData(experiment, signal.getRange());
263 }
264
265 /**
89c06060 266 * Handles the time range updated signal. It updates the time range
05627bda
MD
267 * statistics.
268 *
269 * @param signal
270 * Contains the information about the new selected time range.
271 */
272 @TmfSignalHandler
273 public void timeRangeUpdated(TmfRangeSynchSignal signal) {
05627bda
MD
274 requestTimeRangeData(TmfExperiment.getCurrentExperiment(), signal.getCurrentRange());
275 }
276
1c0de632
AM
277 /**
278 * Whenever a trace's statistics back-end finishes computing the statistics
279 * for a given interval, it will send the StatsUpdated signal. This method
280 * will receive this signal and update the statistics view accordingly.
281 *
282 * @param sig
283 * The signal that is received
284 */
285 @TmfSignalHandler
286 public void statsUpdated(TmfStatsUpdatedSignal sig) {
287 /* Only handle this signal if it's about the trace we represent. */
288 if (!isListeningTo(sig.getTrace())) {
289 return;
290 }
291
292 final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
293 Map<String, Long> map = sig.getEventsPerType();
294 String name = sig.getTrace().getName();
295 boolean isGlobal = sig.isGlobal();
296
297 /*
298 * "Global", "partial", "total", etc., it's all very confusing...
299 *
300 * The base view shows the total count for the trace and for
301 * each even types, organized in columns like this:
302 *
303 * | Global | Time range |
304 * trace name | A | B |
305 * Event Type | | |
306 * <event 1> | C | D |
307 * <event 2> | ... | ... |
308 * ... | | |
309 *
310 * Here, we called the cells like this:
311 * A : GlobalTotal
312 * B : TimeRangeTotal
313 * C : GlobalTypeCount(s)
314 * D : TimeRangeTypeCount(s)
315 */
316
317 /* Fill in an the event counts (either cells C or D) */
318 for (Map.Entry<String, Long> entry : map.entrySet()) {
319 statsData.setTypeCount(name, entry.getKey(), isGlobal, entry.getValue());
320 }
321
322 /*
323 * Calculate the totals (cell A or B, depending if isGlobal). We will
324 * use the results of the previous request instead of sending another
325 * one.
326 */
327 long globalTotal = 0;
328 for (long val : map.values()) {
329 globalTotal += val;
330 }
331 statsData.setTotal(name, isGlobal, globalTotal);
332
333 modelComplete(isGlobal);
334 }
335
336 // ------------------------------------------------------------------------
337 // Class methods
338 // ------------------------------------------------------------------------
339
05627bda
MD
340 /*
341 * Returns the primary control associated with this viewer.
342 *
343 * @return the SWT control which displays this viewer's content
344 */
345 @Override
346 public Control getControl() {
347 return fTreeViewer.getControl();
348 }
349
350 /**
351 * Get the input of the viewer.
352 *
353 * @return an object representing the input of the statistics viewer.
354 */
355 public Object getInput() {
356 return fTreeViewer.getInput();
357 }
358
359 /**
360 * Return the size of the request when performing background request.
361 *
362 * @return the block size for background request.
363 */
364 public int getPageSize() {
365 return PAGE_SIZE;
366 }
367
368 /**
369 * Return the number of events to receive before a refresh of the viewer is
370 * performed.
371 *
372 * @return the input refresh rate
373 */
374 public long getRefreshRate() {
375 return STATS_INPUT_CHANGED_REFRESH;
376 }
377
378 /**
379 * This method can be overridden to implement another way of representing
380 * the statistics data and to retrieve the information for display.
381 *
382 * @return a TmfStatisticsData object.
383 */
36033ff0 384 public TmfStatisticsTree getStatisticData() {
05627bda 385 if (fStatisticsData == null) {
36033ff0 386 fStatisticsData = new TmfStatisticsTree();
05627bda
MD
387 }
388 return fStatisticsData;
389 }
390
391 /**
392 * Returns a unique ID based on name to be associated with the statistics
393 * tree for this viewer. For a same name, it will always return the same ID.
394 *
395 * @return a unique statistics tree ID.
396 */
397 public String getTreeID() {
398 return getName() + fInstanceNb;
399 }
400
401 @Override
402 public void refresh() {
403 final Control viewerControl = getControl();
404 // Ignore update if disposed
405 if (viewerControl.isDisposed()) {
406 return;
407 }
408
409 viewerControl.getDisplay().asyncExec(new Runnable() {
410 @Override
411 public void run() {
412 if (!viewerControl.isDisposed()) {
413 fTreeViewer.refresh();
414 }
415 }
416 });
417 }
418
3c934968
MD
419 /**
420 * Will force a request on the partial event count if one is needed.
421 */
422 public void sendPartialRequestOnNextUpdate() {
423 synchronized (fStatisticsRangeUpdateSyncObj) {
424 fSendRangeRequest = true;
425 }
426 }
427
05627bda
MD
428 /**
429 * Focus on the statistics tree of the viewer
430 */
431 public void setFocus() {
432 fTreeViewer.getTree().setFocus();
433 }
434
05627bda
MD
435 /**
436 * Cancels the request if it is not already completed
437 *
438 * @param request
439 * The request to be canceled
440 */
441 protected void cancelOngoingRequest(ITmfDataRequest request) {
442 if (request != null && !request.isCompleted()) {
443 request.cancel();
444 }
445 }
446
447 /**
448 * This method can be overridden to change the representation of the data in
449 * the columns.
450 *
451 * @return an object implementing ITmfBaseColumnDataProvider.
452 */
453 protected ITmfColumnDataProvider getColumnDataProvider() {
454 return new TmfBaseColumnDataProvider();
455 }
cfd22ad0 456
05627bda
MD
457 /**
458 * Initialize the content that will be drawn in this viewer
459 *
460 * @param parent
461 * The parent of the control to create
462 */
463 protected void initContent(Composite parent) {
cfd22ad0 464 final List<TmfBaseColumnData> columnDataList = getColumnDataProvider().getColumnData();
cfd22ad0
MD
465
466 fTreeViewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
467 fTreeViewer.setContentProvider(new TmfTreeContentProvider());
468 fTreeViewer.getTree().setHeaderVisible(true);
469 fTreeViewer.setUseHashlookup(true);
470
471 // Creates the columns defined by the column data provider
472 for (final TmfBaseColumnData columnData : columnDataList) {
473 final TreeViewerColumn treeColumn = new TreeViewerColumn(fTreeViewer, columnData.getAlignment());
474 treeColumn.getColumn().setText(columnData.getHeader());
475 treeColumn.getColumn().setWidth(columnData.getWidth());
476 treeColumn.getColumn().setToolTipText(columnData.getTooltip());
477
478 if (columnData.getComparator() != null) { // A comparator is defined.
479 // Adds a listener on the columns header for sorting purpose.
480 treeColumn.getColumn().addSelectionListener(new SelectionAdapter() {
481
482 private ViewerComparator reverseComparator;
483
484 @Override
485 public void widgetSelected(SelectionEvent e) {
486 // Initializes the reverse comparator once.
487 if (reverseComparator == null) {
488 reverseComparator = new ViewerComparator() {
489 @Override
490 public int compare(Viewer viewer, Object e1, Object e2) {
491 return -1 * columnData.getComparator().compare(viewer, e1, e2);
492 }
493 };
494 }
495
496 if (fTreeViewer.getTree().getSortDirection() == SWT.UP
497 || fTreeViewer.getTree().getSortColumn() != treeColumn.getColumn()) {
498 /*
499 * Puts the descendant order if the old order was
500 * up or if the selected column has changed.
501 */
502 fTreeViewer.setComparator(columnData.getComparator());
503 fTreeViewer.getTree().setSortDirection(SWT.DOWN);
504 } else {
505 /*
506 * Puts the ascendant ordering if the selected
507 * column hasn't changed.
508 */
509 fTreeViewer.setComparator(reverseComparator);
510 fTreeViewer.getTree().setSortDirection(SWT.UP);
511 }
512 fTreeViewer.getTree().setSortColumn(treeColumn.getColumn());
513 }
514 });
515 }
516 treeColumn.setLabelProvider(columnData.getLabelProvider());
517 }
518
519 // Handler that will draw the bar charts.
520 fTreeViewer.getTree().addListener(SWT.EraseItem, new Listener() {
521 @Override
522 public void handleEvent(Event event) {
523 if (columnDataList.get(event.index).getPercentageProvider() != null) {
524 TmfStatisticsTreeNode node = (TmfStatisticsTreeNode) event.item.getData();
525
526 double percentage = columnDataList.get(event.index).getPercentageProvider().getPercentage(node);
527 if (percentage == 0) { // No bar to draw
528 return;
529 }
530
531 if ((event.detail & SWT.SELECTED) > 0) { // The item is selected.
532 // Draws our own background to avoid overwritten the bar.
533 event.gc.fillRectangle(event.x, event.y, event.width, event.height);
534 event.detail &= ~SWT.SELECTED;
535 }
536
537 int barWidth = (int) ((fTreeViewer.getTree().getColumn(event.index).getWidth() - 8) * percentage);
538 int oldAlpha = event.gc.getAlpha();
539 Color oldForeground = event.gc.getForeground();
540 Color oldBackground = event.gc.getBackground();
541 /*
542 * Draws a transparent gradient rectangle from the color of
543 * foreground and background.
544 */
545 event.gc.setAlpha(64);
546 event.gc.setForeground(event.item.getDisplay().getSystemColor(SWT.COLOR_BLUE));
547 event.gc.setBackground(event.item.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
548 event.gc.fillGradientRectangle(event.x, event.y, barWidth, event.height, true);
549 event.gc.drawRectangle(event.x, event.y, barWidth, event.height);
550 // Restores old values
551 event.gc.setForeground(oldForeground);
552 event.gc.setBackground(oldBackground);
553 event.gc.setAlpha(oldAlpha);
554 event.detail &= ~SWT.BACKGROUND;
555 }
556 }
557 });
558
559 // Initializes the comparator parameters
560 fTreeViewer.setComparator(columnDataList.get(0).getComparator());
561 fTreeViewer.getTree().setSortColumn(fTreeViewer.getTree().getColumn(0));
562 fTreeViewer.getTree().setSortDirection(SWT.DOWN);
563 }
564
8b60cb37
MD
565 /**
566 * Initializes the input for the tree viewer.
567 *
568 * @param input
569 * The input of this viewer, or <code>null</code> if none
570 */
571 protected void initInput() {
572 String treeID = getTreeID();
573 TmfStatisticsTreeNode experimentTreeNode;
36033ff0 574 if (TmfStatisticsTreeManager.containsTreeRoot(treeID)) {
8b60cb37 575 // The experiment root is already present
36033ff0 576 experimentTreeNode = TmfStatisticsTreeManager.getStatTreeRoot(treeID);
8b60cb37
MD
577
578 // Checks if the trace is already in the statistics tree.
579 int numNodeTraces = experimentTreeNode.getNbChildren();
580
581 int numTraces = 1;
582 ITmfTrace[] trace = { fTrace };
583 // For experiment, gets all the traces within it
584 if (fTrace instanceof TmfExperiment) {
585 TmfExperiment experiment = (TmfExperiment) fTrace;
586 numTraces = experiment.getTraces().length;
587 trace = experiment.getTraces();
588 }
589
590 if (numTraces == numNodeTraces) {
591 boolean same = true;
592 /*
593 * Checks if the experiment contains the same traces as when
594 * previously selected.
595 */
596 for (int i = 0; i < numTraces; i++) {
597 String traceName = trace[i].getName();
598 if (!experimentTreeNode.containsChild(traceName)) {
599 same = false;
600 break;
601 }
602 }
603
604 if (same) {
605 // No need to reload data, all traces are already loaded
606 fTreeViewer.setInput(experimentTreeNode);
607 return;
608 }
609 // Clears the old content to start over
610 experimentTreeNode.reset();
611 }
612 } else {
613 // Creates a new tree
36033ff0 614 experimentTreeNode = TmfStatisticsTreeManager.addStatsTreeRoot(treeID, getStatisticData());
8b60cb37
MD
615 }
616
617 // Sets the input to a clean data model
618 fTreeViewer.setInput(experimentTreeNode);
619 resetUpdateSynchronization();
620 }
621
cfd22ad0 622 /**
05627bda 623 * Tells if the viewer is listening to a trace from the selected experiment.
cfd22ad0 624 *
1c0de632 625 * @param trace
05627bda
MD
626 * The trace that the viewer may be listening
627 * @return true if the viewer is listening to the trace, false otherwise
cfd22ad0 628 */
1c0de632
AM
629 protected boolean isListeningTo(ITmfTrace trace) {
630 if (fProcessAll || trace == fTrace) {
05627bda 631 return true;
cfd22ad0 632 }
05627bda 633 return false;
cfd22ad0
MD
634 }
635
636 /**
05627bda 637 * Called when an experiment request has been completed successfully.
cfd22ad0 638 *
05627bda
MD
639 * @param global
640 * Tells if the request is a global or time range (partial)
641 * request.
cfd22ad0 642 */
05627bda
MD
643 protected void modelComplete(boolean global) {
644 refresh();
645 waitCursor(false);
646 if (global) {
647 sendPendingUpdate();
648 }
cfd22ad0
MD
649 }
650
651 /**
05627bda 652 * Called when an experiment request has failed or has been cancelled.
cfd22ad0 653 *
05627bda
MD
654 * @param isGlobalRequest
655 * Tells if the request is a global or time range (partial)
656 * request.
cfd22ad0 657 */
05627bda
MD
658 protected void modelIncomplete(boolean isGlobalRequest) {
659 if (isGlobalRequest) { // Clean the global statistics
660 /*
763f4972
MD
661 * No need to reset the global number of events, since the index of
662 * the last requested event is known.
05627bda 663 */
05627bda
MD
664 resetUpdateSynchronization();
665 sendPendingUpdate();
666 } else { // Clean the partial statistics
667 resetTimeRangeValue();
668 }
669 refresh();
670 waitCursor(false);
cfd22ad0
MD
671 }
672
673 /**
05627bda 674 * Sends the request to the experiment for the whole trace
cfd22ad0 675 *
05627bda
MD
676 * @param experiment
677 * The experiment used to send the request
678 * @param range
679 * The range to request to the experiment
cfd22ad0 680 */
89c06060 681 protected void requestData(final TmfExperiment experiment, final TmfTimeRange timeRange) {
1c0de632 682 buildStatisticsTree(experiment, timeRange, true);
cfd22ad0
MD
683 }
684
685 /**
05627bda 686 * Sends the time range request from the experiment
cfd22ad0 687 *
05627bda
MD
688 * @param experiment
689 * The experiment used to send the request
690 * @param range
691 * The range to request to the experiment
cfd22ad0 692 */
89c06060
AM
693 protected void requestTimeRangeData(final TmfExperiment experiment, final TmfTimeRange timeRange) {
694 fRequestedTimerange = timeRange;
1c0de632 695 buildStatisticsTree(experiment, timeRange, false);
89c06060
AM
696 }
697
698 /**
699 * Requests all the data of the experiment to the state system which
700 * contains information about the statistics.
701 *
702 * Since the viewer may be listening to multiple traces, it have to receive
703 * the experiment rather than a single trace. The filtering is done with the
704 * method {@link #isListeningTo(String trace)}.
705 *
706 * @param experiment
707 * The experiment for which a request must be done
708 * @param timeRange
709 * The time range that will be requested to the state system
710 * @param isGlobal
711 * Tells if the request is for the global event count or the
712 * partial one.
713 */
714 private void buildStatisticsTree(final TmfExperiment experiment, TmfTimeRange timeRange, boolean isGlobal) {
36033ff0
AM
715 final TmfStatisticsTreeNode statTree = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID());
716 final TmfStatisticsTree statsData = TmfStatisticsTreeManager.getStatTree(getTreeID());
89c06060
AM
717 if (statsData == null) {
718 return;
719 }
720
721 synchronized (statsData) {
722 if (isGlobal) {
723 statTree.resetGlobalValue();
724 } else {
725 statTree.resetTimeRangeValue();
726 }
727
728 /*
729 * Checks each trace in the experiment, since the viewer may be
730 * listening to multiple traces.
731 */
732 for (final ITmfTrace trace : experiment.getTraces()) {
1c0de632 733 if (!isListeningTo(trace)) {
89c06060
AM
734 continue;
735 }
736
737 /* Retrieves the statistics object */
738 final ITmfStatistics stats = trace.getStatistics();
739 if (stats == null) {
740 /*
1c0de632
AM
741 * The statistics provider for this trace is not accessible
742 * (yet?). Try the next one.
89c06060
AM
743 */
744 continue;
745 }
746
1c0de632
AM
747 /* The generic statistics are stored in nanoseconds, so we must make
748 * sure the time range is scaled correctly. */
749 ITmfTimestamp start = timeRange.getStartTime().normalize(0, TIME_SCALE);
750 ITmfTimestamp end = timeRange.getEndTime().normalize(0, TIME_SCALE);
89c06060 751
1c0de632
AM
752 /*
753 * Send a request to update the statistics view. The result will
754 * be sent through a {@link TmfStatsUpdatedSignal}, and will be
755 * processed by the signal handler.
756 */
757 trace.getStatistics().updateStats(isGlobal, start, end);
89c06060 758 }
89c06060 759 }
cfd22ad0
MD
760 }
761
762 /**
05627bda 763 * Resets the number of events within the time range
cfd22ad0 764 */
05627bda 765 protected void resetTimeRangeValue() {
36033ff0 766 TmfStatisticsTreeNode treeModelRoot = TmfStatisticsTreeManager.getStatTreeRoot(getTreeID());
05627bda
MD
767 if (treeModelRoot != null && treeModelRoot.hasChildren()) {
768 treeModelRoot.resetTimeRangeValue();
769 }
cfd22ad0
MD
770 }
771
772 /**
773 * When the experiment is loading the cursor will be different so the user
05627bda
MD
774 * knows that the processing is not finished yet.
775 *
776 * Calls to this method are stacked.
cfd22ad0 777 *
05627bda 778 * @param waitRequested
cfd22ad0 779 * Indicates if we need to show the waiting cursor, or the
05627bda 780 * default one.
cfd22ad0 781 */
05627bda 782 protected void waitCursor(final boolean waitRequested) {
cfd22ad0
MD
783 if ((fTreeViewer == null) || (fTreeViewer.getTree().isDisposed())) {
784 return;
785 }
786
05627bda 787 boolean needsUpdate = false;
cfd22ad0 788 Display display = fTreeViewer.getControl().getDisplay();
05627bda
MD
789 if (waitRequested) {
790 fWaitCursorCount++;
791 if (fWaitCursor == null) { // The cursor hasn't been initialized yet
792 fWaitCursor = new Cursor(display, SWT.CURSOR_WAIT);
793 }
794 if (fWaitCursorCount == 1) { // The cursor is not in waiting mode
795 needsUpdate = true;
796 }
797 } else {
798 if (fWaitCursorCount > 0) { // The cursor is in waiting mode
799 fWaitCursorCount--;
800 if (fWaitCursorCount == 0) { // No more reason to wait
801 // Put back the default cursor
802 needsUpdate = true;
803 }
804 }
cfd22ad0
MD
805 }
806
05627bda
MD
807 if (needsUpdate) {
808 // Performs the updates on the UI thread
809 display.asyncExec(new Runnable() {
810 @Override
811 public void run() {
812 if ((fTreeViewer != null)
813 && (!fTreeViewer.getTree().isDisposed())) {
814 Cursor cursor = null; // indicates default
815 if (waitRequested) {
816 cursor = fWaitCursor;
817 }
818 fTreeViewer.getControl().setCursor(cursor);
cfd22ad0 819 }
cfd22ad0 820 }
05627bda
MD
821 });
822 }
cfd22ad0
MD
823 }
824
05627bda
MD
825 // ------------------------------------------------------------------------
826 // Methods reserved for the streaming functionality
827 // ------------------------------------------------------------------------
828
cfd22ad0 829 /**
05627bda 830 * Resets update synchronization information
cfd22ad0 831 */
05627bda
MD
832 protected void resetUpdateSynchronization() {
833 synchronized (fStatisticsUpdateSyncObj) {
834 fStatisticsUpdateBusy = false;
835 fStatisticsUpdatePending = false;
836 fStatisticsUpdateRange = null;
837 }
cfd22ad0
MD
838 }
839
840 /**
05627bda
MD
841 * Checks if statistics update is ongoing. If it is ongoing, the new time
842 * range is stored as pending
cfd22ad0 843 *
05627bda
MD
844 * @param timeRange
845 * - new time range
846 * @return true if statistic update is ongoing else false
cfd22ad0 847 */
05627bda
MD
848 protected boolean checkUpdateBusy(TmfTimeRange timeRange) {
849 synchronized (fStatisticsUpdateSyncObj) {
850 if (fStatisticsUpdateBusy) {
851 fStatisticsUpdatePending = true;
852 if (fStatisticsUpdateRange == null
853 || timeRange.getEndTime().compareTo(fStatisticsUpdateRange.getEndTime()) > 0) {
854 fStatisticsUpdateRange = timeRange;
855 }
856 return true;
857 }
858 fStatisticsUpdateBusy = true;
859 return false;
860 }
861 }
862
863 /**
864 * Sends pending request (if any)
865 */
866 protected void sendPendingUpdate() {
867 synchronized (fStatisticsUpdateSyncObj) {
868 fStatisticsUpdateBusy = false;
869 if (fStatisticsUpdatePending) {
870 fStatisticsUpdatePending = false;
871 requestData(TmfExperiment.getCurrentExperiment(), fStatisticsUpdateRange);
872 fStatisticsUpdateRange = null;
873 }
874 }
cfd22ad0
MD
875 }
876}
This page took 0.064837 seconds and 5 git commands to generate.