timing.core: Add local statistics to the latency statistics
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.timing.ui / src / org / eclipse / tracecompass / analysis / timing / ui / views / segmentstore / statistics / AbstractSegmentStoreStatisticsViewer.java
index 775fd3f3691405de3870459a12c8c1dc1fc77413..4bf0f3a4608c89fb429a2e16678418112d99aa1c 100644 (file)
@@ -16,20 +16,40 @@ import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
 import java.text.Format;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.TreeViewer;
 import org.eclipse.jface.viewers.Viewer;
 import org.eclipse.jface.viewers.ViewerComparator;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.AbstractSegmentStatisticsAnalysis;
 import org.eclipse.tracecompass.analysis.timing.core.segmentstore.statistics.SegmentStoreStatistics;
 import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.SubSecondTimeWithUnitFormat;
 import org.eclipse.tracecompass.internal.analysis.timing.ui.Activator;
+import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.statistics.Messages;
 import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule;
 import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
 import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeColumnDataProvider;
+import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeViewerEntry;
 import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeColumnData;
 import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeViewerEntry;
 
@@ -44,8 +64,8 @@ public abstract class AbstractSegmentStoreStatisticsViewer extends AbstractTmfTr
 
     private static final Format FORMATTER = new SubSecondTimeWithUnitFormat();
 
-    @Nullable
-    private TmfAbstractAnalysisModule fModule;
+    private @Nullable TmfAbstractAnalysisModule fModule;
+    private MenuManager fTablePopupMenuManager;
 
     private static final String[] COLUMN_NAMES = new String[] {
             checkNotNull(Messages.SegmentStoreStatistics_LevelLabel),
@@ -53,7 +73,8 @@ public abstract class AbstractSegmentStoreStatisticsViewer extends AbstractTmfTr
             checkNotNull(Messages.SegmentStoreStatistics_MaxLabel),
             checkNotNull(Messages.SegmentStoreStatistics_AverageLabel),
             checkNotNull(Messages.SegmentStoreStatisticsViewer_StandardDeviation),
-            checkNotNull(Messages.SegmentStoreStatisticsViewer_Count)
+            checkNotNull(Messages.SegmentStoreStatisticsViewer_Count),
+            checkNotNull(Messages.SegmentStoreStatisticsViewer_Total)
     };
 
     /**
@@ -65,6 +86,20 @@ public abstract class AbstractSegmentStoreStatisticsViewer extends AbstractTmfTr
     public AbstractSegmentStoreStatisticsViewer(Composite parent) {
         super(parent, false);
         setLabelProvider(new SegmentStoreStatisticsLabelProvider());
+        fTablePopupMenuManager = new MenuManager();
+        fTablePopupMenuManager.setRemoveAllWhenShown(true);
+        fTablePopupMenuManager.addMenuListener(manager -> {
+            TreeViewer viewer = getTreeViewer();
+            ISelection selection = viewer.getSelection();
+            if (selection instanceof IStructuredSelection) {
+                IStructuredSelection sel = (IStructuredSelection) selection;
+                if (manager != null) {
+                    appendToTablePopupMenu(manager, sel);
+                }
+            }
+        });
+        Menu tablePopup = fTablePopupMenuManager.createContextMenu(getTreeViewer().getTree());
+        getTreeViewer().getTree().setMenu(tablePopup);
     }
 
     /** Provides label for the Segment Store tree viewer cells */
@@ -93,6 +128,8 @@ public abstract class AbstractSegmentStoreStatisticsViewer extends AbstractTmfTr
                         value = String.valueOf(toFormattedString(entry.getEntry().getStdDev()));
                     } else if (columnIndex == 5) {
                         value = String.valueOf(entry.getEntry().getNbSegments());
+                    } else if (columnIndex == 6) {
+                        value = String.valueOf(toFormattedString(entry.getEntry().getTotal()));
                     }
                 }
             }
@@ -228,6 +265,23 @@ public abstract class AbstractSegmentStoreStatisticsViewer extends AbstractTmfTr
                     }
                 });
                 columns.add(column);
+                column = new TmfTreeColumnData(COLUMN_NAMES[6]);
+                column.setAlignment(SWT.RIGHT);
+                column.setComparator(new ViewerComparator() {
+                    @Override
+                    public int compare(@Nullable Viewer viewer, @Nullable Object e1, @Nullable Object e2) {
+                        if ((e1 == null) || (e2 == null)) {
+                            return 0;
+                        }
+
+                        SegmentStoreStatisticsEntry n1 = (SegmentStoreStatisticsEntry) e1;
+                        SegmentStoreStatisticsEntry n2 = (SegmentStoreStatisticsEntry) e2;
+
+                        return Double.compare(n1.getEntry().getTotal(), n2.getEntry().getTotal());
+
+                    }
+                });
+                columns.add(column);
                 column = new TmfTreeColumnData(""); //$NON-NLS-1$
                 columns.add(column);
                 return columns;
@@ -254,6 +308,43 @@ public abstract class AbstractSegmentStoreStatisticsViewer extends AbstractTmfTr
         }
     }
 
+    /**
+     * Method to add commands to the context sensitive menu.
+     *
+     * @param manager
+     *            the menu manager
+     * @param sel
+     *            the current selection
+     */
+    protected void appendToTablePopupMenu(IMenuManager manager, IStructuredSelection sel) {
+        Object element = sel.getFirstElement();
+        if ((element instanceof SegmentStoreStatisticsEntry) && !(element instanceof HiddenTreeViewerEntry)) {
+            final SegmentStoreStatisticsEntry segment = (SegmentStoreStatisticsEntry) element;
+            IAction gotoStartTime = new Action(Messages.SegmentStoreStatisticsViewer_GotoMinAction) {
+                @Override
+                public void run() {
+                    long start = segment.getEntry().getMinSegment().getStart();
+                    long end = segment.getEntry().getMinSegment().getEnd();
+                    broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreStatisticsViewer.this, TmfTimestamp.fromNanos(start), TmfTimestamp.fromNanos(end)));
+                    updateContent(start, end, true);
+                }
+            };
+
+            IAction gotoEndTime = new Action(Messages.SegmentStoreStatisticsViewer_GotoMaxAction) {
+                @Override
+                public void run() {
+                    long start = segment.getEntry().getMaxSegment().getStart();
+                    long end = segment.getEntry().getMaxSegment().getEnd();
+                    broadcast(new TmfSelectionRangeUpdatedSignal(AbstractSegmentStoreStatisticsViewer.this, TmfTimestamp.fromNanos(start), TmfTimestamp.fromNanos(end)));
+                    updateContent(start, end, true);
+                }
+            };
+
+            manager.add(gotoStartTime);
+            manager.add(gotoEndTime);
+        }
+    }
+
     /**
      * Formats a double value string
      *
@@ -300,6 +391,87 @@ public abstract class AbstractSegmentStoreStatisticsViewer extends AbstractTmfTr
 
     }
 
+    @Override
+    protected @Nullable ITmfTreeViewerEntry updateElements(long start, long end, boolean isSelection) {
+
+        TmfAbstractAnalysisModule analysisModule = getStatisticsAnalysisModule();
+
+        if (getTrace() == null || !(analysisModule instanceof AbstractSegmentStatisticsAnalysis)) {
+            return null;
+        }
+
+        AbstractSegmentStatisticsAnalysis module = (AbstractSegmentStatisticsAnalysis) analysisModule;
+
+        module.waitForCompletion();
+
+        TmfTreeViewerEntry root = new TmfTreeViewerEntry(""); //$NON-NLS-1$
+        List<ITmfTreeViewerEntry> entryList = root.getChildren();
+
+        if (isSelection) {
+            setStats(start, end, entryList, module, true, new NullProgressMonitor());
+        }
+        setStats(start, end, entryList, module, false, new NullProgressMonitor());
+        return root;
+    }
+
+    private void setStats(long start, long end, List<ITmfTreeViewerEntry> entryList, AbstractSegmentStatisticsAnalysis module, boolean isSelection, IProgressMonitor monitor) {
+        String label = isSelection ? getSelectionLabel() : getTotalLabel();
+        final SegmentStoreStatistics entry = isSelection ? module.getTotalStatsForRange(start, end, monitor) : module.getTotalStats();
+        if (entry != null) {
+
+            if (entry.getNbSegments() == 0) {
+                return;
+            }
+            TmfTreeViewerEntry child = new SegmentStoreStatisticsEntry(checkNotNull(label), entry);
+            entryList.add(child);
+
+            final Map<@NonNull String, @NonNull SegmentStoreStatistics> perTypeStats = isSelection? module.getPerSegmentTypeStatsForRange(start, end, monitor) : module.getPerSegmentTypeStats();
+            if (perTypeStats != null) {
+                for (Entry<@NonNull String, @NonNull SegmentStoreStatistics> statsEntry : perTypeStats.entrySet()) {
+                    child.addChild(new SegmentStoreStatisticsEntry(statsEntry.getKey(), statsEntry.getValue()));
+                }
+            }
+        }
+    }
+
+    @Override
+    @TmfSignalHandler
+    public void windowRangeUpdated(@Nullable TmfWindowRangeUpdatedSignal signal) {
+        // Do nothing. We do not want to update the view and lose the selection
+        // if the window range is updated with current selection outside of this
+        // new range.
+    }
+
+    /**
+     * Get the type label
+     *
+     * @return the label
+     * @since 1.2
+     */
+    protected String getTypeLabel() {
+        return checkNotNull(Messages.AbstractSegmentStoreStatisticsViewer_types);
+    }
+
+    /**
+     * Get the total column label
+     *
+     * @return the totals column label
+     * @since 1.2
+     */
+    protected String getTotalLabel() {
+        return checkNotNull(Messages.AbstractSegmentStoreStatisticsViewer_total);
+    }
+
+    /**
+     * Get the selection column label
+     *
+     * @return The selection column label
+     * @since 1.2
+     */
+    protected String getSelectionLabel() {
+        return checkNotNull(Messages.AbstractSegmentStoreStatisticsViewer_selection);
+    }
+
     /**
      * Class to define a level in the tree that doesn't have any values.
      */
This page took 0.027861 seconds and 5 git commands to generate.