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;
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),
checkNotNull(Messages.SegmentStoreStatistics_MaxLabel),
checkNotNull(Messages.SegmentStoreStatistics_AverageLabel),
checkNotNull(Messages.SegmentStoreStatisticsViewer_StandardDeviation),
- checkNotNull(Messages.SegmentStoreStatisticsViewer_Count)
+ checkNotNull(Messages.SegmentStoreStatisticsViewer_Count),
+ checkNotNull(Messages.SegmentStoreStatisticsViewer_Total)
};
/**
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 */
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()));
}
}
}
}
});
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;
}
}
+ /**
+ * 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
*
}
+ @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.
*/