[Bug292967] Implemented items [1] and [2] of of request coalescing. Augmented unit...
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng.ui / src / org / eclipse / linuxtools / lttng / ui / views / statistics / StatisticsView.java
CommitLineData
6e512b93
ASL
1/*******************************************************************************
2 * Copyright (c) 2009 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:
dfaf8391
FC
10 * Yann N. Dauphin (dhaemon@gmail.com) - Implementation
11 * Francois Chouinard (fchouinard@gmail.com) - Initial API
6e512b93
ASL
12 *******************************************************************************/
13
14package org.eclipse.linuxtools.lttng.ui.views.statistics;
15
dfaf8391
FC
16import java.text.DecimalFormat;
17import java.util.Arrays;
18import java.util.HashSet;
19import java.util.Set;
20
21import org.eclipse.jface.viewers.ColumnLabelProvider;
22import org.eclipse.jface.viewers.ITreeContentProvider;
23import org.eclipse.jface.viewers.TreeViewer;
24import org.eclipse.jface.viewers.TreeViewerColumn;
25import org.eclipse.jface.viewers.Viewer;
26import org.eclipse.jface.viewers.ViewerComparator;
27import org.eclipse.linuxtools.lttng.state.IStateDataRequestListener;
28import org.eclipse.linuxtools.lttng.state.RequestCompletedSignal;
29import org.eclipse.linuxtools.lttng.state.RequestStartedSignal;
30import org.eclipse.linuxtools.lttng.state.evProcessor.EventProcessorProxy;
31import org.eclipse.linuxtools.lttng.state.experiment.StateExperimentManager;
32import org.eclipse.linuxtools.lttng.state.experiment.StateManagerFactory;
33import org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor.StatsEventCountHandlerFactory;
34import org.eclipse.linuxtools.lttng.ui.views.statistics.evProcessor.StatsTimeCountHandlerFactory;
35import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeFactory;
36import org.eclipse.linuxtools.lttng.ui.views.statistics.model.StatisticsTreeNode;
37import org.eclipse.linuxtools.tmf.signal.TmfSignalHandler;
38import org.eclipse.linuxtools.tmf.ui.views.TmfView;
39import org.eclipse.swt.SWT;
40import org.eclipse.swt.events.SelectionAdapter;
41import org.eclipse.swt.events.SelectionEvent;
42import org.eclipse.swt.graphics.Color;
43import org.eclipse.swt.graphics.Image;
44import org.eclipse.swt.layout.FillLayout;
6e512b93 45import org.eclipse.swt.widgets.Composite;
dfaf8391
FC
46import org.eclipse.swt.widgets.Event;
47import org.eclipse.swt.widgets.Listener;
48import org.eclipse.ui.ISharedImages;
49import org.eclipse.ui.PlatformUI;
6e512b93
ASL
50
51/**
52 * <b><u>StatisticsView</u></b>
53 * <p>
dfaf8391
FC
54 * The Statistics View displays statistics for traces.
55 *
56 * It is implemented according to the MVC pattern. - The model is a
57 * StatisticsTreeNode built by the State Manager. - The view is built with a
58 * TreeViewer. - The controller that keeps model and view synchronised is an
59 * observer of the model.
6e512b93 60 */
fc6ccf6f 61public class StatisticsView extends TmfView implements IStateDataRequestListener {
dfaf8391
FC
62
63 public static final String ID = "org.eclipse.linuxtools.lttng.ui.views.statistics";
64
65 private TreeViewer treeViewer;
66
67 // Table column names
68 private final String LEVEL_COLUMN = "Level";
69 private final String EVENTS_COUNT_COLUMN = "Number of Events";
70 private final String CPU_TIME_COLUMN = "CPU Time";
71 private final String CUMULATIVE_CPU_TIME_COLUMN = "Cumulative CPU Time";
72 private final String ELAPSED_TIME_COLUMN = "Elapsed Time";
73
74 // Table column tooltips
75 private final String LEVEL_COLUMN_TIP = "Level at which statistics apply.";
76 private final String EVENTS_COUNT_COLUMN_TIP = "Total amount of events that are tied to given resource.";
77 private final String CPU_TIME_COLUMN_TIP = "Total amount of time the CPU was used excluding wait times(I/O, etc.) at that level.";
78 private final String CUMULATIVE_CPU_TIME_COLUMN_TIP = "Total amount of time between the first and last event excluding wait times in a level.";
79 private final String ELAPSED_TIME_COLUMN_TIP = "Total amount of time the CPU was used including wait times(I/O, etc.) at that level.";
6e512b93 80
dfaf8391
FC
81 // Level for which statistics should not be displayed.
82 private Set<String> folderLevels = new HashSet<String>(Arrays
83 .asList(new String[] { "Event Types", "Modes", "Submodes", "CPUs",
84 "Processes", "Functions" }));
6e512b93 85
dfaf8391
FC
86 // Levels for which sub-levels should not contain time-related statistics.
87 private Set<String> levelsWithEmptyTime = new HashSet<String>(Arrays
88 .asList(new String[] { "Event Types" }));
89
90 private DecimalFormat decimalFormat = new DecimalFormat("0.#########");
91
92 // Used to draw bar charts in columns.
93 private interface ColumnPercentageProvider {
94 public double getPercentage(StatisticsTreeNode node);
95 }
96
97 /**
98 * Contains all the information necessary to build a column of the table.
99 */
100 private class ColumnData {
101 // Name of the column.
102 public final String header;
103 // Width of the column.
104 public final int width;
105 // Alignment of the column.
106 public final int alignment;
107 // Tooltip of the column.
108 public final String tooltip;
109 // Adapts a StatisticsTreeNode into the content of it's corresponding
110 // cell for that column.
111 public final ColumnLabelProvider labelProvider;
112 // Used to sort elements of this column. Can be null.
113 public final ViewerComparator comparator;
114 // Used to draw bar charts in this column. Can be null.
115 public final ColumnPercentageProvider percentageProvider;
116
117 public ColumnData(String h, int w, int a, String t,
118 ColumnLabelProvider l, ViewerComparator c,
119 ColumnPercentageProvider p) {
120 header = h;
121 width = w;
122 alignment = a;
123 tooltip = t;
124 labelProvider = l;
125 comparator = c;
126 percentageProvider = p;
127 }
128 };
129
130 // List that will be used to create the table.
131 private ColumnData[] columnDataList = new ColumnData[] {
132 new ColumnData(LEVEL_COLUMN, 200, SWT.LEFT, LEVEL_COLUMN_TIP,
133 new ColumnLabelProvider() {
134 @Override
135 public String getText(Object element) {
136 return ((StatisticsTreeNode) element).getKey();
137 }
138
139 @Override
140 public Image getImage(Object element) {
141 StatisticsTreeNode node = (StatisticsTreeNode) element;
142 if (folderLevels.contains(node.getKey())) {
143 return PlatformUI.getWorkbench()
144 .getSharedImages().getImage(
145 ISharedImages.IMG_OBJ_FOLDER);
146 } else {
147 return PlatformUI.getWorkbench()
148 .getSharedImages().getImage(
149 ISharedImages.IMG_OBJ_ELEMENT);
150 }
151 }
152 }, new ViewerComparator() {
153 @Override
154 public int compare(Viewer viewer, Object e1, Object e2) {
155 StatisticsTreeNode n1 = (StatisticsTreeNode) e1;
156 StatisticsTreeNode n2 = (StatisticsTreeNode) e2;
157
158 return n1.getKey().compareTo(n2.getKey());
159 }
160 }, null),
161 new ColumnData(EVENTS_COUNT_COLUMN, 125, SWT.LEFT,
162 EVENTS_COUNT_COLUMN_TIP, new ColumnLabelProvider() {
163 @Override
164 public String getText(Object element) {
165 StatisticsTreeNode node = (StatisticsTreeNode) element;
166 if (!folderLevels.contains(node.getKey())) {
167 return Long.toString(node.getValue().nbEvents);
168 } else {
169 return "";
170 }
171 }
172 }, new ViewerComparator() {
173 @Override
174 public int compare(Viewer viewer, Object e1, Object e2) {
175 StatisticsTreeNode n1 = (StatisticsTreeNode) e1;
176 StatisticsTreeNode n2 = (StatisticsTreeNode) e2;
177
178 return (int) (n1.getValue().nbEvents - n2
179 .getValue().nbEvents);
180 }
181 }, new ColumnPercentageProvider() {
182 public double getPercentage(StatisticsTreeNode node) {
183 StatisticsTreeNode parent = node;
184 do {
185 parent = parent.getParent();
186 } while (parent != null
187 && parent.getValue().nbEvents == 0);
188
189 if (parent == null) {
190 return 0;
191 } else {
192 return (double) node.getValue().nbEvents
193 / parent.getValue().nbEvents;
194 }
195 }
196 }),
197 new ColumnData(CPU_TIME_COLUMN, 125, SWT.LEFT, CPU_TIME_COLUMN_TIP,
198 new ColumnLabelProvider() {
199 @Override
200 public String getText(Object element) {
201 StatisticsTreeNode node = (StatisticsTreeNode) element;
202
203 if (folderLevels.contains(node.getKey())) {
204 return "";
205 } else if (node.getParent() != null
206 && levelsWithEmptyTime.contains(node
207 .getParent().getKey())) {
208 return "";
209 } else {
210 return decimalFormat
211 .format(node.getValue().cpuTime
212 / Math.pow(10, 9));
213 }
214 }
215 }, null, null),
216 new ColumnData(CUMULATIVE_CPU_TIME_COLUMN, 155, SWT.LEFT,
217 CUMULATIVE_CPU_TIME_COLUMN_TIP, new ColumnLabelProvider() {
218 @Override
219 public String getText(Object element) {
220 StatisticsTreeNode node = (StatisticsTreeNode) element;
221 if (folderLevels.contains(node.getKey())) {
222 return "";
223 } else if (node.getParent() != null
224 && levelsWithEmptyTime.contains(node
225 .getParent().getKey())) {
226 return "";
227 } else {
228 return decimalFormat
229 .format(node.getValue().cumulativeCpuTime
230 / Math.pow(10, 9));
231 }
232 }
233 }, null, null),
234 new ColumnData(ELAPSED_TIME_COLUMN, 100, SWT.LEFT,
235 ELAPSED_TIME_COLUMN_TIP, new ColumnLabelProvider() {
236 @Override
237 public String getText(Object element) {
238 StatisticsTreeNode node = (StatisticsTreeNode) element;
239 if (folderLevels.contains(node.getKey())) {
240 return "";
241 } else if (node.getParent() != null
242 && levelsWithEmptyTime.contains(node
243 .getParent().getKey())) {
244 return "";
245 } else {
246 return decimalFormat
247 .format(node.getValue().elapsedTime
248 / Math.pow(10, 9));
249 }
250 }
251 }, null, null) };
252
253 /**
254 * Adapter TreeViewers can use to interact with StatisticsTreeNode objects.
6e512b93 255 *
dfaf8391 256 * @see org.eclipse.jface.viewers.ITreeContentProvider
6e512b93 257 */
dfaf8391
FC
258 class TreeContentProvider implements ITreeContentProvider {
259 /*
260 * (non-Javadoc)
261 *
262 * @see
263 * org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang
264 * .Object)
265 */
266 public Object[] getChildren(Object parentElement) {
267 return ((StatisticsTreeNode) parentElement).getChildren().toArray();
268 }
269
270 /*
271 * (non-Javadoc)
272 *
273 * @see
274 * org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang
275 * .Object)
276 */
277 public Object getParent(Object element) {
278 return ((StatisticsTreeNode) element).getParent();
279 }
280
281 /*
282 * (non-Javadoc)
283 *
284 * @see
285 * org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang
286 * .Object)
287 */
288 public boolean hasChildren(Object element) {
289 return ((StatisticsTreeNode) element).hasChildren();
290 }
291
292 /*
293 * (non-Javadoc)
294 *
295 * @see
296 * org.eclipse.jface.viewers.IStructuredContentProvider#getElements(
297 * java.lang.Object)
298 */
299 public Object[] getElements(Object inputElement) {
300 return getChildren(inputElement);
301 }
302
303 /*
304 * (non-Javadoc)
305 *
306 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
307 */
308 public void dispose() {
309 }
310
311 /*
312 * (non-Javadoc)
313 *
314 * @see
315 * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse
316 * .jface.viewers.Viewer, java.lang.Object, java.lang.Object)
317 */
318 // @Override
319 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
320 }
6e512b93
ASL
321 }
322
fc6ccf6f
FC
323 public StatisticsView(String viewName) {
324 super("StatisticsView");
325 }
326
dfaf8391
FC
327 /*
328 * (non-Javadoc)
329 *
330 * @see
331 * org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets
332 * .Composite)
6e512b93
ASL
333 */
334 @Override
335 public void createPartControl(Composite parent) {
dfaf8391
FC
336 EventProcessorProxy.getInstance().addEventProcessorFactory(
337 StatsTimeCountHandlerFactory.getInstance());
338 EventProcessorProxy.getInstance().addEventProcessorFactory(
339 StatsEventCountHandlerFactory.getInstance());
340
341 parent.setLayout(new FillLayout());
342
343 treeViewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL
344 | SWT.V_SCROLL);
345 treeViewer.setContentProvider(new TreeContentProvider());
346 treeViewer.getTree().setHeaderVisible(true);
347 treeViewer.setUseHashlookup(true);
348
349 for (final ColumnData columnData : columnDataList) {
350 final TreeViewerColumn treeColumn = new TreeViewerColumn(
351 treeViewer, columnData.alignment);
352 treeColumn.getColumn().setText(columnData.header);
353 treeColumn.getColumn().setWidth(columnData.width);
354 treeColumn.getColumn().setToolTipText(columnData.tooltip);
355 if (columnData.comparator != null) {
356 treeColumn.getColumn().addSelectionListener(
357 new SelectionAdapter() {
358 @Override
359 public void widgetSelected(SelectionEvent e) {
360 if (treeViewer.getTree().getSortDirection() == SWT.UP
361 || treeViewer.getTree().getSortColumn() != treeColumn
362 .getColumn()) {
363 treeViewer
364 .setComparator(columnData.comparator);
365 treeViewer.getTree().setSortDirection(
366 SWT.DOWN);
367 } else {
368 treeViewer
369 .setComparator(new ViewerComparator() {
370 @Override
371 public int compare(
372 Viewer viewer,
373 Object e1, Object e2) {
374 return -1
375 * columnData.comparator
376 .compare(
377 viewer,
378 e1,
379 e2);
380 }
381 });
382 treeViewer.getTree().setSortDirection(
383 SWT.UP);
384 }
385 treeViewer.getTree().setSortColumn(
386 treeColumn.getColumn());
387 }
388 });
389 }
390 treeColumn.setLabelProvider(columnData.labelProvider);
391 }
392
393 // Handler that will draw the bar charts.
394 treeViewer.getTree().addListener(SWT.EraseItem, new Listener() {
395 // @Override
396 public void handleEvent(Event event) {
397 if (columnDataList[event.index].percentageProvider != null) {
398 StatisticsTreeNode node = (StatisticsTreeNode) event.item
399 .getData();
400
401 double percentage = columnDataList[event.index].percentageProvider
402 .getPercentage(node);
403 if (percentage == 0) {
404 return;
405 }
406
407 if ((event.detail & SWT.SELECTED) > 0) {
408 Color oldForeground = event.gc.getForeground();
409 event.gc.setForeground(event.item.getDisplay()
410 .getSystemColor(SWT.COLOR_LIST_SELECTION));
411 event.gc.fillRectangle(event.x, event.y, event.width,
412 event.height);
413 event.gc.setForeground(oldForeground);
414 event.detail &= ~SWT.SELECTED;
415 }
416
417 int barWidth = (int) ((treeViewer.getTree().getColumn(1)
418 .getWidth() - 8) * percentage);
419 int oldAlpha = event.gc.getAlpha();
420 Color oldForeground = event.gc.getForeground();
421 Color oldBackground = event.gc.getBackground();
422 event.gc.setAlpha(64);
423 event.gc.setForeground(event.item.getDisplay()
424 .getSystemColor(SWT.COLOR_BLUE));
425 event.gc.setBackground(event.item.getDisplay()
426 .getSystemColor(SWT.COLOR_LIST_BACKGROUND));
427 event.gc.fillGradientRectangle(event.x, event.y, barWidth,
428 event.height, true);
429 event.gc.drawRectangle(event.x, event.y, barWidth,
430 event.height);
431 event.gc.setForeground(oldForeground);
432 event.gc.setBackground(oldBackground);
433 event.gc.setAlpha(oldAlpha);
434 event.detail &= ~SWT.BACKGROUND;
435 }
436 }
437 });
438
439 treeViewer.setComparator(columnDataList[0].comparator);
440 treeViewer.getTree().setSortColumn(treeViewer.getTree().getColumn(0));
441 treeViewer.getTree().setSortDirection(SWT.DOWN);
442
443 treeViewer.setInput(StatisticsTreeFactory
444 .getStatisticsTree("Experiment"));
445
446 // Read current data if any available
447 StateExperimentManager experimentManger = StateManagerFactory
448 .getExperimentManager();
449 experimentManger.readExperiment("statisticsView", this);
450
451 }
452 @Override
453 public void dispose() {
454 super.dispose();
455 EventProcessorProxy.getInstance().removeEventProcessorFactory(
456 StatsTimeCountHandlerFactory.getInstance());
457 EventProcessorProxy.getInstance().removeEventProcessorFactory(
458 StatsEventCountHandlerFactory.getInstance());
6e512b93 459
6e512b93
ASL
460 }
461
dfaf8391
FC
462 /*
463 * (non-Javadoc)
464 *
6e512b93
ASL
465 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
466 */
467 @Override
468 public void setFocus() {
dfaf8391
FC
469 treeViewer.getTree().setFocus();
470 }
471
472 @TmfSignalHandler
473 public void processingStarted(RequestStartedSignal request) {
474 // Nothing to do for the time being
6e512b93 475
6e512b93
ASL
476 }
477
dfaf8391
FC
478 @TmfSignalHandler
479 public void processingCompleted(RequestCompletedSignal signal) {
480 treeViewer.getTree().getDisplay().asyncExec(new Runnable() {
481 // @Override
482 public void run() {
483 treeViewer.refresh();
484 }
485 });
486 }
6e512b93 487}
This page took 0.046294 seconds and 5 git commands to generate.