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