1 /*******************************************************************************
2 * Copyright (c) 2015, 2016 Ericsson
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
10 * Bernd Hufmann - Initial API and implementation
11 *******************************************************************************/
12 package org
.eclipse
.tracecompass
.analysis
.timing
.ui
.views
.segmentstore
.statistics
;
14 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
16 import java
.text
.Format
;
17 import java
.util
.ArrayList
;
18 import java
.util
.List
;
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
;
48 * An abstract tree viewer implementation for displaying segment store
51 * @author Bernd Hufmann
54 public abstract class AbstractSegmentStoreStatisticsViewer
extends AbstractTmfTreeViewer
{
56 private static final Format FORMATTER
= new SubSecondTimeWithUnitFormat();
59 private TmfAbstractAnalysisModule fModule
;
60 private MenuManager fTablePopupMenuManager
;
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
)
75 * the parent composite
77 public AbstractSegmentStoreStatisticsViewer(Composite parent
) {
79 setLabelProvider(new SegmentStoreStatisticsLabelProvider());
80 fTablePopupMenuManager
= new MenuManager();
81 fTablePopupMenuManager
.setRemoveAllWhenShown(true);
82 fTablePopupMenuManager
.addMenuListener(manager
-> {
83 TreeViewer viewer
= getTreeViewer();
84 ISelection selection
= viewer
.getSelection();
85 if (selection
instanceof IStructuredSelection
) {
86 IStructuredSelection sel
= (IStructuredSelection
) selection
;
87 if (manager
!= null) {
88 appendToTablePopupMenu(manager
, sel
);
92 Menu tablePopup
= fTablePopupMenuManager
.createContextMenu(getTreeViewer().getTree());
93 getTreeViewer().getTree().setMenu(tablePopup
);
96 /** Provides label for the Segment Store tree viewer cells */
97 protected static class SegmentStoreStatisticsLabelProvider
extends TreeLabelProvider
{
100 public String
getColumnText(@Nullable Object element
, int columnIndex
) {
101 String value
= ""; //$NON-NLS-1$
102 if (element
instanceof HiddenTreeViewerEntry
) {
103 if (columnIndex
== 0) {
104 value
= ((HiddenTreeViewerEntry
) element
).getName();
106 } else if (element
instanceof SegmentStoreStatisticsEntry
) {
107 SegmentStoreStatisticsEntry entry
= (SegmentStoreStatisticsEntry
) element
;
108 if (columnIndex
== 0) {
109 return String
.valueOf(entry
.getName());
111 if (entry
.getEntry().getNbSegments() > 0) {
112 if (columnIndex
== 1) {
113 value
= toFormattedString(entry
.getEntry().getMin());
114 } else if (columnIndex
== 2) {
115 value
= String
.valueOf(toFormattedString(entry
.getEntry().getMax()));
116 } else if (columnIndex
== 3) {
117 value
= String
.valueOf(toFormattedString(entry
.getEntry().getAverage()));
118 } else if (columnIndex
== 4) {
119 value
= String
.valueOf(toFormattedString(entry
.getEntry().getStdDev()));
120 } else if (columnIndex
== 5) {
121 value
= String
.valueOf(entry
.getEntry().getNbSegments());
125 return checkNotNull(value
);
130 * Creates the statistics analysis module
132 * @return the statistics analysis module
135 protected abstract TmfAbstractAnalysisModule
createStatisticsAnalysiModule();
138 * Gets the statistics analysis module
140 * @return the statistics analysis module
143 public TmfAbstractAnalysisModule
getStatisticsAnalysisModule() {
148 protected ITmfTreeColumnDataProvider
getColumnDataProvider() {
149 return new ITmfTreeColumnDataProvider() {
152 public List
<@Nullable TmfTreeColumnData
> getColumnData() {
153 /* All columns are sortable */
154 List
<@Nullable TmfTreeColumnData
> columns
= new ArrayList
<>();
155 TmfTreeColumnData column
= new TmfTreeColumnData(COLUMN_NAMES
[0]);
156 column
.setAlignment(SWT
.RIGHT
);
157 column
.setComparator(new ViewerComparator() {
159 public int compare(@Nullable Viewer viewer
, @Nullable Object e1
, @Nullable Object e2
) {
160 if ((e1
== null) || (e2
== null)) {
164 SegmentStoreStatisticsEntry n1
= (SegmentStoreStatisticsEntry
) e1
;
165 SegmentStoreStatisticsEntry n2
= (SegmentStoreStatisticsEntry
) e2
;
167 return n1
.getName().compareTo(n2
.getName());
172 column
= new TmfTreeColumnData(COLUMN_NAMES
[1]);
173 column
.setAlignment(SWT
.RIGHT
);
174 column
.setComparator(new ViewerComparator() {
176 public int compare(@Nullable Viewer viewer
, @Nullable Object e1
, @Nullable Object e2
) {
177 if ((e1
== null) || (e2
== null)) {
181 SegmentStoreStatisticsEntry n1
= (SegmentStoreStatisticsEntry
) e1
;
182 SegmentStoreStatisticsEntry n2
= (SegmentStoreStatisticsEntry
) e2
;
184 return Long
.compare(n1
.getEntry().getMin(), n2
.getEntry().getMin());
189 column
= new TmfTreeColumnData(COLUMN_NAMES
[2]);
190 column
.setAlignment(SWT
.RIGHT
);
191 column
.setComparator(new ViewerComparator() {
193 public int compare(@Nullable Viewer viewer
, @Nullable Object e1
, @Nullable Object e2
) {
194 if ((e1
== null) || (e2
== null)) {
198 SegmentStoreStatisticsEntry n1
= (SegmentStoreStatisticsEntry
) e1
;
199 SegmentStoreStatisticsEntry n2
= (SegmentStoreStatisticsEntry
) e2
;
201 return Long
.compare(n1
.getEntry().getMax(), n2
.getEntry().getMax());
206 column
= new TmfTreeColumnData(COLUMN_NAMES
[3]);
207 column
.setAlignment(SWT
.RIGHT
);
208 column
.setComparator(new ViewerComparator() {
210 public int compare(@Nullable Viewer viewer
, @Nullable Object e1
, @Nullable Object e2
) {
211 if ((e1
== null) || (e2
== null)) {
215 SegmentStoreStatisticsEntry n1
= (SegmentStoreStatisticsEntry
) e1
;
216 SegmentStoreStatisticsEntry n2
= (SegmentStoreStatisticsEntry
) e2
;
218 return Double
.compare(n1
.getEntry().getAverage(), n2
.getEntry().getAverage());
223 column
= new TmfTreeColumnData(COLUMN_NAMES
[4]);
224 column
.setAlignment(SWT
.RIGHT
);
225 column
.setComparator(new ViewerComparator() {
227 public int compare(@Nullable Viewer viewer
, @Nullable Object e1
, @Nullable Object e2
) {
228 if ((e1
== null) || (e2
== null)) {
232 SegmentStoreStatisticsEntry n1
= (SegmentStoreStatisticsEntry
) e1
;
233 SegmentStoreStatisticsEntry n2
= (SegmentStoreStatisticsEntry
) e2
;
235 return Double
.compare(n1
.getEntry().getStdDev(), n2
.getEntry().getStdDev());
240 column
= new TmfTreeColumnData(COLUMN_NAMES
[5]);
241 column
.setAlignment(SWT
.RIGHT
);
242 column
.setComparator(new ViewerComparator() {
244 public int compare(@Nullable Viewer viewer
, @Nullable Object e1
, @Nullable Object e2
) {
245 if ((e1
== null) || (e2
== null)) {
249 SegmentStoreStatisticsEntry n1
= (SegmentStoreStatisticsEntry
) e1
;
250 SegmentStoreStatisticsEntry n2
= (SegmentStoreStatisticsEntry
) e2
;
252 return Long
.compare(n1
.getEntry().getNbSegments(), n2
.getEntry().getNbSegments());
257 column
= new TmfTreeColumnData(""); //$NON-NLS-1$
266 public void initializeDataSource() {
267 ITmfTrace trace
= getTrace();
269 TmfAbstractAnalysisModule module
= createStatisticsAnalysiModule();
270 if (module
== null) {
274 module
.setTrace(trace
);
277 } catch (TmfAnalysisException e
) {
278 Activator
.getDefault().logError("Error initializing statistics analysis module", e
); //$NON-NLS-1$
284 * Method to add commands to the context sensitive menu.
288 * the current selection
290 protected void appendToTablePopupMenu(IMenuManager manager
, IStructuredSelection sel
) {
291 Object element
= sel
.getFirstElement();
292 if ((element
instanceof SegmentStoreStatisticsEntry
) && !(element
instanceof HiddenTreeViewerEntry
)) {
293 final SegmentStoreStatisticsEntry segment
= (SegmentStoreStatisticsEntry
) element
;
294 IAction gotoStartTime
= new Action(Messages
.SegmentStoreStatisticsViewer_GotoMinAction
) {
297 long start
= segment
.getEntry().getMinSegment().getStart();
298 long end
= segment
.getEntry().getMinSegment().getEnd();
299 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreStatisticsViewer
.this, TmfTimestamp
.fromNanos(start
), TmfTimestamp
.fromNanos(end
)));
303 IAction gotoEndTime
= new Action(Messages
.SegmentStoreStatisticsViewer_GotoMaxAction
) {
306 long start
= segment
.getEntry().getMaxSegment().getStart();
307 long end
= segment
.getEntry().getMaxSegment().getEnd();
308 broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreStatisticsViewer
.this, TmfTimestamp
.fromNanos(start
), TmfTimestamp
.fromNanos(end
)));
312 manager
.add(gotoStartTime
);
313 manager
.add(gotoEndTime
);
318 * Formats a double value string
322 * @return formatted value
324 protected static String
toFormattedString(double value
) {
325 // The cast to long is needed because the formatter cannot truncate the
327 String percentageString
= String
.format("%s", FORMATTER
.format(value
)); //$NON-NLS-1$
328 return percentageString
;
332 * Class for defining an entry in the statistics tree.
334 protected class SegmentStoreStatisticsEntry
extends TmfTreeViewerEntry
{
336 private final SegmentStoreStatistics fEntry
;
345 * segment store statistics object
347 public SegmentStoreStatisticsEntry(String name
, SegmentStoreStatistics entry
) {
353 * Gets the statistics object
355 * @return statistics object
357 public SegmentStoreStatistics
getEntry() {
364 * Class to define a level in the tree that doesn't have any values.
366 protected class HiddenTreeViewerEntry
extends SegmentStoreStatisticsEntry
{
371 * the name of the level
373 public HiddenTreeViewerEntry(String name
) {
374 super(name
, new SegmentStoreStatistics());