analysis: Add totals to latency statistics view
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.timing.ui / src / org / eclipse / tracecompass / analysis / timing / ui / views / segmentstore / statistics / AbstractSegmentStoreStatisticsViewer.java
1 /*******************************************************************************
2 * Copyright (c) 2015, 2016 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are made
5 * 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 * Bernd Hufmann - Initial API and implementation
11 *******************************************************************************/
12 package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics;
13
14 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
15
16 import java.text.Format;
17 import java.util.ArrayList;
18 import java.util.List;
19
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.eclipse.jface.action.Action;
22 import org.eclipse.jface.action.IAction;
23 import org.eclipse.jface.action.IMenuManager;
24 import org.eclipse.jface.action.MenuManager;
25 import org.eclipse.jface.viewers.ISelection;
26 import org.eclipse.jface.viewers.IStructuredSelection;
27 import org.eclipse.jface.viewers.TreeViewer;
28 import org.eclipse.jface.viewers.Viewer;
29 import org.eclipse.jface.viewers.ViewerComparator;
30 import org.eclipse.swt.SWT;
31 import org.eclipse.swt.widgets.Composite;
32 import org.eclipse.swt.widgets.Menu;
33 import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.SegmentStoreStatistics;
34 import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.SubSecondTimeWithUnitFormat;
35 import org.eclipse.tracecompass.internal.analysis.timing.ui.Activator;
36 import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.statistics.Messages;
37 import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
38 import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
39 import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
40 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
41 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
42 import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
43 import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeColumnDataProvider;
44 import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeColumnData;
45 import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeViewerEntry;
46
47 /**
48 * An abstract tree viewer implementation for displaying segment store
49 * statistics
50 *
51 * @author Bernd Hufmann
52 *
53 */
54 public abstract class AbstractSegmentStoreStatisticsViewer extends AbstractTmfTreeViewer {
55
56 private static final Format FORMATTER = new SubSecondTimeWithUnitFormat();
57
58 @Nullable
59 private TmfAbstractAnalysisModule fModule;
60 private MenuManager fTablePopupMenuManager;
61
62 private static final String[] COLUMN_NAMES = new String[] {
63 checkNotNull(Messages.SegmentStoreStatistics_LevelLabel),
64 checkNotNull(Messages.SegmentStoreStatistics_Statistics_MinLabel),
65 checkNotNull(Messages.SegmentStoreStatistics_MaxLabel),
66 checkNotNull(Messages.SegmentStoreStatistics_AverageLabel),
67 checkNotNull(Messages.SegmentStoreStatisticsViewer_StandardDeviation),
68 checkNotNull(Messages.SegmentStoreStatisticsViewer_Count),
69 checkNotNull(Messages.SegmentStoreStatisticsViewer_Total)
70 };
71
72 /**
73 * Constructor
74 *
75 * @param parent
76 * the parent composite
77 */
78 public AbstractSegmentStoreStatisticsViewer(Composite parent) {
79 super(parent, false);
80 setLabelProvider(new SegmentStoreStatisticsLabelProvider());
81 fTablePopupMenuManager = new MenuManager();
82 fTablePopupMenuManager.setRemoveAllWhenShown(true);
83 fTablePopupMenuManager.addMenuListener(manager -> {
84 TreeViewer viewer = getTreeViewer();
85 ISelection selection = viewer.getSelection();
86 if (selection instanceof IStructuredSelection) {
87 IStructuredSelection sel = (IStructuredSelection) selection;
88 if (manager != null) {
89 appendToTablePopupMenu(manager, sel);
90 }
91 }
92 });
93 Menu tablePopup = fTablePopupMenuManager.createContextMenu(getTreeViewer().getTree());
94 getTreeViewer().getTree().setMenu(tablePopup);
95 }
96
97 /** Provides label for the Segment Store tree viewer cells */
98 protected static class SegmentStoreStatisticsLabelProvider extends TreeLabelProvider {
99
100 @Override
101 public String getColumnText(@Nullable Object element, int columnIndex) {
102 String value = ""; //$NON-NLS-1$
103 if (element instanceof HiddenTreeViewerEntry) {
104 if (columnIndex == 0) {
105 value = ((HiddenTreeViewerEntry) element).getName();
106 }
107 } else if (element instanceof SegmentStoreStatisticsEntry) {
108 SegmentStoreStatisticsEntry entry = (SegmentStoreStatisticsEntry) element;
109 if (columnIndex == 0) {
110 return String.valueOf(entry.getName());
111 }
112 if (entry.getEntry().getNbSegments() > 0) {
113 if (columnIndex == 1) {
114 value = toFormattedString(entry.getEntry().getMin());
115 } else if (columnIndex == 2) {
116 value = String.valueOf(toFormattedString(entry.getEntry().getMax()));
117 } else if (columnIndex == 3) {
118 value = String.valueOf(toFormattedString(entry.getEntry().getAverage()));
119 } else if (columnIndex == 4) {
120 value = String.valueOf(toFormattedString(entry.getEntry().getStdDev()));
121 } else if (columnIndex == 5) {
122 value = String.valueOf(entry.getEntry().getNbSegments());
123 } else if (columnIndex == 6) {
124 value = String.valueOf(toFormattedString(entry.getEntry().getTotal()));
125 }
126 }
127 }
128 return checkNotNull(value);
129 }
130 }
131
132 /**
133 * Creates the statistics analysis module
134 *
135 * @return the statistics analysis module
136 */
137 @Nullable
138 protected abstract TmfAbstractAnalysisModule createStatisticsAnalysiModule();
139
140 /**
141 * Gets the statistics analysis module
142 *
143 * @return the statistics analysis module
144 */
145 @Nullable
146 public TmfAbstractAnalysisModule getStatisticsAnalysisModule() {
147 return fModule;
148 }
149
150 @Override
151 protected ITmfTreeColumnDataProvider getColumnDataProvider() {
152 return new ITmfTreeColumnDataProvider() {
153
154 @Override
155 public List<@Nullable TmfTreeColumnData> getColumnData() {
156 /* All columns are sortable */
157 List<@Nullable TmfTreeColumnData> columns = new ArrayList<>();
158 TmfTreeColumnData column = new TmfTreeColumnData(COLUMN_NAMES[0]);
159 column.setAlignment(SWT.RIGHT);
160 column.setComparator(new ViewerComparator() {
161 @Override
162 public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
163 if ((e1 == null) || (e2 == null)) {
164 return 0;
165 }
166
167 SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
168 SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
169
170 return n1.getName().compareTo(n2.getName());
171
172 }
173 });
174 columns.add(column);
175 column = new TmfTreeColumnData(COLUMN_NAMES[1]);
176 column.setAlignment(SWT.RIGHT);
177 column.setComparator(new ViewerComparator() {
178 @Override
179 public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
180 if ((e1 == null) || (e2 == null)) {
181 return 0;
182 }
183
184 SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
185 SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
186
187 return Long.compare(n1.getEntry().getMin(), n2.getEntry().getMin());
188
189 }
190 });
191 columns.add(column);
192 column = new TmfTreeColumnData(COLUMN_NAMES[2]);
193 column.setAlignment(SWT.RIGHT);
194 column.setComparator(new ViewerComparator() {
195 @Override
196 public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
197 if ((e1 == null) || (e2 == null)) {
198 return 0;
199 }
200
201 SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
202 SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
203
204 return Long.compare(n1.getEntry().getMax(), n2.getEntry().getMax());
205
206 }
207 });
208 columns.add(column);
209 column = new TmfTreeColumnData(COLUMN_NAMES[3]);
210 column.setAlignment(SWT.RIGHT);
211 column.setComparator(new ViewerComparator() {
212 @Override
213 public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
214 if ((e1 == null) || (e2 == null)) {
215 return 0;
216 }
217
218 SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
219 SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
220
221 return Double.compare(n1.getEntry().getAverage(), n2.getEntry().getAverage());
222
223 }
224 });
225 columns.add(column);
226 column = new TmfTreeColumnData(COLUMN_NAMES[4]);
227 column.setAlignment(SWT.RIGHT);
228 column.setComparator(new ViewerComparator() {
229 @Override
230 public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
231 if ((e1 == null) || (e2 == null)) {
232 return 0;
233 }
234
235 SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
236 SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
237
238 return Double.compare(n1.getEntry().getStdDev(), n2.getEntry().getStdDev());
239
240 }
241 });
242 columns.add(column);
243 column = new TmfTreeColumnData(COLUMN_NAMES[5]);
244 column.setAlignment(SWT.RIGHT);
245 column.setComparator(new ViewerComparator() {
246 @Override
247 public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
248 if ((e1 == null) || (e2 == null)) {
249 return 0;
250 }
251
252 SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
253 SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
254
255 return Long.compare(n1.getEntry().getNbSegments(), n2.getEntry().getNbSegments());
256
257 }
258 });
259 columns.add(column);
260 column = new TmfTreeColumnData(COLUMN_NAMES[6]);
261 column.setAlignment(SWT.RIGHT);
262 column.setComparator(new ViewerComparator() {
263 @Override
264 public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
265 if ((e1 == null) || (e2 == null)) {
266 return 0;
267 }
268
269 SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
270 SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
271
272 return Double.compare(n1.getEntry().getTotal(), n2.getEntry().getTotal());
273
274 }
275 });
276 columns.add(column);
277 column = new TmfTreeColumnData(""); //$NON-NLS-1$
278 columns.add(column);
279 return columns;
280 }
281
282 };
283 }
284
285 @Override
286 public void initializeDataSource() {
287 ITmfTrace trace = getTrace();
288 if (trace != null) {
289 TmfAbstractAnalysisModule module = createStatisticsAnalysiModule();
290 if (module == null) {
291 return;
292 }
293 try {
294 module.setTrace(trace);
295 module.schedule();
296 fModule = module;
297 } catch (TmfAnalysisException e) {
298 Activator.getDefault().logError("Error initializing statistics analysis module", e); //$NON-NLS-1$
299 }
300 }
301 }
302
303 /**
304 * Method to add commands to the context sensitive menu.
305 * @param manager
306 * the menu manager
307 * @param sel
308 * the current selection
309 */
310 protected void appendToTablePopupMenu(IMenuManager manager, IStructuredSelection sel) {
311 Object element = sel.getFirstElement();
312 if ((element instanceof SegmentStoreStatisticsEntry) && !(element instanceof HiddenTreeViewerEntry)) {
313 final SegmentStoreStatisticsEntry segment = (SegmentStoreStatisticsEntry) element;
314 IAction gotoStartTime = new Action(Messages.SegmentStoreStatisticsViewer_GotoMinAction) {
315 @Override
316 public void run() {
317 long start = segment.getEntry().getMinSegment().getStart();
318 long end = segment.getEntry().getMinSegment().getEnd();
319 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreStatisticsViewer.this, TmfTimestamp.fromNanos(start), TmfTimestamp.fromNanos(end)));
320 }
321 };
322
323 IAction gotoEndTime = new Action(Messages.SegmentStoreStatisticsViewer_GotoMaxAction) {
324 @Override
325 public void run() {
326 long start = segment.getEntry().getMaxSegment().getStart();
327 long end = segment.getEntry().getMaxSegment().getEnd();
328 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreStatisticsViewer.this, TmfTimestamp.fromNanos(start), TmfTimestamp.fromNanos(end)));
329 }
330 };
331
332 manager.add(gotoStartTime);
333 manager.add(gotoEndTime);
334 }
335 }
336
337 /**
338 * Formats a double value string
339 *
340 * @param value
341 * a value to format
342 * @return formatted value
343 */
344 protected static String toFormattedString(double value) {
345 // The cast to long is needed because the formatter cannot truncate the
346 // number.
347 String percentageString = String.format("%s", FORMATTER.format(value)); //$NON-NLS-1$
348 return percentageString;
349 }
350
351 /**
352 * Class for defining an entry in the statistics tree.
353 */
354 protected class SegmentStoreStatisticsEntry extends TmfTreeViewerEntry {
355
356 private final SegmentStoreStatistics fEntry;
357
358 /**
359 * Constructor
360 *
361 * @param name
362 * name of entry
363 *
364 * @param entry
365 * segment store statistics object
366 */
367 public SegmentStoreStatisticsEntry(String name, SegmentStoreStatistics entry) {
368 super(name);
369 fEntry = entry;
370 }
371
372 /**
373 * Gets the statistics object
374 *
375 * @return statistics object
376 */
377 public SegmentStoreStatistics getEntry() {
378 return fEntry;
379 }
380
381 }
382
383 /**
384 * Class to define a level in the tree that doesn't have any values.
385 */
386 protected class HiddenTreeViewerEntry extends SegmentStoreStatisticsEntry {
387 /**
388 * Constructor
389 *
390 * @param name
391 * the name of the level
392 */
393 public HiddenTreeViewerEntry(String name) {
394 super(name, new SegmentStoreStatistics());
395 }
396 }
397
398 }
This page took 0.071243 seconds and 6 git commands to generate.