From: Bernd Hufmann Date: Tue, 12 Jan 2016 17:53:59 +0000 (-0500) Subject: analysis: support for sorting of control flow view columns X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=a4cddcbc604bd211ac3e6f30d697de1677b068b4;p=deliverable%2Ftracecompass.git analysis: support for sorting of control flow view columns Each column in the control flow view can be now sorted by clicking on the column header. By default, it's sorted by birth time. For an experiment the traces are sorted independently. The tree hierarchy is kept, i.e. tree level is sorted separately. An API has been added to support sorting of time graph entries (ITimeGraphEntry) generically. Change-Id: I05631ca69ea5cd57cdd97b3815cc263e7de9e43e Signed-off-by: Bernd Hufmann Reviewed-on: https://git.eclipse.org/r/64403 Reviewed-by: Hudson CI Reviewed-by: Matthew Khouzam Reviewed-by: Patrick Tasse Tested-by: Patrick Tasse --- diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF index 406fc3db69..183e7d8621 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF @@ -26,6 +26,7 @@ Export-Package: org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow, org.eclipse.tracecompass.analysis.os.linux.ui.views.cpuusage, org.eclipse.tracecompass.analysis.os.linux.ui.views.resources, org.eclipse.tracecompass.internal.analysis.os.linux.ui;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests", + org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests", org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests", org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.statistics;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests", org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.resources;x-friends:="org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests" diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java index d4b36b3803..99dc269f6f 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java @@ -31,6 +31,7 @@ import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.Attributes import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.KernelAnalysisModule; import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Activator; import org.eclipse.tracecompass.internal.analysis.os.linux.ui.Messages; +import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow.ControlFlowColumnComparators; import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException; @@ -53,6 +54,8 @@ import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils; import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.Resolution; import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat; +import com.google.common.collect.ImmutableList; + /** * The Control Flow view main object * @@ -62,7 +65,6 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView { // ------------------------------------------------------------------------ // Constants // ------------------------------------------------------------------------ - /** * View ID. */ @@ -90,6 +92,19 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView { // Timeout between updates in the build thread in ms private static final long BUILD_UPDATE_TIMEOUT = 500; + private static final Comparator[] COLUMN_COMPARATORS; + + static { + ImmutableList.Builder> builder = ImmutableList.builder(); + builder.add(ControlFlowColumnComparators.PROCESS_NAME_COLUMN_COMPARATOR) + .add(ControlFlowColumnComparators.TID_COLUMN_COMPARATOR) + .add(ControlFlowColumnComparators.PTID_COLUMN_COMPARATOR) + .add(ControlFlowColumnComparators.BIRTH_TIME_COLUMN_COMPARATOR) + .add(ControlFlowColumnComparators.TRACE_COLUMN_COMPARATOR); + List> l = builder.build(); + COLUMN_COMPARATORS = l.toArray(new Comparator[l.size()]); + } + // ------------------------------------------------------------------------ // Constructors // ------------------------------------------------------------------------ @@ -99,11 +114,11 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView { */ public ControlFlowView() { super(ID, new ControlFlowPresentationProvider()); - setTreeColumns(COLUMN_NAMES); + setTreeColumns(COLUMN_NAMES, COLUMN_COMPARATORS, 3); setTreeLabelProvider(new ControlFlowTreeLabelProvider()); setFilterColumns(FILTER_COLUMN_NAMES); setFilterLabelProvider(new ControlFlowFilterLabelProvider()); - setEntryComparator(new ControlFlowEntryComparator()); + setEntryComparator(ControlFlowColumnComparators.BIRTH_TIME_COLUMN_COMPARATOR); } @Override @@ -160,43 +175,6 @@ public class ControlFlowView extends AbstractStateSystemTimeGraphView { return Messages.ControlFlowView_previousProcessActionToolTipText; } - private static class ControlFlowEntryComparator implements Comparator { - - @Override - public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) { - - if (o1.getParent() != null || o2.getParent() != null) { - /* Sort all child processes according to birth time. */ - return Long.compare(o1.getStartTime(), o2.getStartTime()); - } - - int result = 0; - - if ((o1 instanceof ControlFlowEntry) && (o2 instanceof ControlFlowEntry)) { - /* - * Sort root processes according to their trace's start time, - * then by trace name, then by the process thread id. - */ - ControlFlowEntry entry1 = (ControlFlowEntry) o1; - ControlFlowEntry entry2 = (ControlFlowEntry) o2; - result = entry1.getTrace().getStartTime().compareTo(entry2.getTrace().getStartTime()); - if (result == 0) { - result = entry1.getTrace().getName().compareTo(entry2.getTrace().getName()); - } - if (result == 0) { - result = Integer.compare(entry1.getThreadId(), entry2.getThreadId()); - } - } - - if (result == 0) { - /* Sort root processes with reused thread id by birth time. */ - result = Long.compare(o1.getStartTime(), o2.getStartTime()); - } - - return result; - } - } - /** * @author gbastien * diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowColumnComparators.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowColumnComparators.java new file mode 100644 index 0000000000..3bcc410567 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowColumnComparators.java @@ -0,0 +1,220 @@ +/******************************************************************************* + * Copyright (c) 2016 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow; + +import java.util.Comparator; +import java.util.List; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.swt.SWT; +import org.eclipse.tracecompass.tmf.ui.views.timegraph.ITimeGraphEntryComparator; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; + +import com.google.common.collect.ImmutableList; + +/** + * + * Class with comparators used for sorting the ControlFlowEntries based based on + * the column selection. + * + * @author Bernd Hufmann + * + */ +public final class ControlFlowColumnComparators { + + /** + * Process Name comparator. This compares first the trace, then the process name, then the + * birth time, then the TID finally the parent TID. + */ + public static ITimeGraphEntryComparator PROCESS_NAME_COLUMN_COMPARATOR = new ITimeGraphEntryComparator() { + private final List> SECONDARY_COMPARATORS = init(); + private int fDirection = SWT.DOWN; + + @Override + public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) { + /* First sort by trace */ + int result = compareTrace(fDirection, o1, o2); + + if (result == 0) { + /* Then sort by process name */ + result = IControlFlowEntryComparator.PROCESS_NAME_COMPARATOR.compare(o1, o2); + } + return compareList(result, fDirection, SECONDARY_COMPARATORS, o1, o2); + } + + @Override + public void setDirection(int direction) { + fDirection = direction; + } + + private List> init() { + ImmutableList.Builder> builder = ImmutableList.builder(); + builder.add(IControlFlowEntryComparator.BIRTH_TIME_COMPARATOR) + .add(IControlFlowEntryComparator.TID_COMPARATOR) + .add(IControlFlowEntryComparator.PTID_COMPARATOR); + return builder.build(); + } + }; + + /** + * Process TID comparator. This compares first the trace, then the process TID, then the + * birth time, then the process name finally the parent TID. + */ + public static ITimeGraphEntryComparator TID_COLUMN_COMPARATOR = new ITimeGraphEntryComparator() { + + private final List> SECONDARY_COMPARATORS = init(); + private int fDirection = SWT.DOWN; + + @Override + public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) { + /* First sort by trace */ + int result = compareTrace(fDirection, o1, o2); + + if (result == 0) { + /* Then sort by TID */ + result = IControlFlowEntryComparator.TID_COMPARATOR.compare(o1, o2); + } + return compareList(result, fDirection, SECONDARY_COMPARATORS, o1, o2); + } + + @Override + public void setDirection(int direction) { + fDirection = direction; + } + + private List> init() { + ImmutableList.Builder> builder = ImmutableList.builder(); + builder.add(IControlFlowEntryComparator.BIRTH_TIME_COMPARATOR) + .add(IControlFlowEntryComparator.PROCESS_NAME_COMPARATOR) + .add(IControlFlowEntryComparator.PTID_COMPARATOR); + return builder.build(); + } + + }; + + /** + * Process PTID comparator. This compares first the trace, then the process + * parent TID, then the birth time, then the process name finally the TID. + */ + public static ITimeGraphEntryComparator PTID_COLUMN_COMPARATOR = new ITimeGraphEntryComparator() { + + private final List> SECONDARY_COMPARATORS = init(); + private int fDirection = SWT.DOWN; + + @Override + public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) { + /* First sort by trace */ + int result = compareTrace(fDirection, o1, o2); + if (result == 0) { + /* Then sort by PTID */ + result = IControlFlowEntryComparator.PTID_COMPARATOR.compare(o1, o2); + } + return compareList(result, fDirection, SECONDARY_COMPARATORS, o1, o2); + } + + @Override + public void setDirection(int direction) { + fDirection = direction; + } + + private List> init() { + ImmutableList.Builder> builder = ImmutableList.builder(); + builder.add(IControlFlowEntryComparator.BIRTH_TIME_COMPARATOR) + .add(IControlFlowEntryComparator.PROCESS_NAME_COMPARATOR) + .add(IControlFlowEntryComparator.TID_COMPARATOR); + return builder.build(); + } + }; + + /** + * Process birth time comparator. This compares first the trace, then the + * birth time, then the process name, then the TID finally the parent TID. + */ + public static ITimeGraphEntryComparator BIRTH_TIME_COLUMN_COMPARATOR = new ITimeGraphEntryComparator() { + private final List> SECONDARY_COMPARATORS = init(); + private int fDirection = SWT.DOWN; + + @Override + public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) { + + int result = compareTrace(fDirection, o1, o2); + + if (result == 0) { + /* Sort all child processes according to birth time. */ + result = IControlFlowEntryComparator.BIRTH_TIME_COMPARATOR.compare(o1, o2); + } + return compareList(result, fDirection, SECONDARY_COMPARATORS, o1, o2); + } + + @Override + public void setDirection(int direction) { + fDirection = direction; + } + + private List> init() { + ImmutableList.Builder> builder = ImmutableList.builder(); + builder.add(IControlFlowEntryComparator.PROCESS_NAME_COMPARATOR) + .add(IControlFlowEntryComparator.TID_COMPARATOR) + .add(IControlFlowEntryComparator.PTID_COMPARATOR); + return builder.build(); + } + }; + + /** + * Trace comparator. This compares first the trace, then the process birth + * time, the process name, the process TID and finally the process's parent + * TID. + */ + public static ITimeGraphEntryComparator TRACE_COLUMN_COMPARATOR = new ITimeGraphEntryComparator() { + private final List> SECONDARY_COMPARATORS = init(); + private int fDirection = SWT.DOWN; + + @Override + public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) { + int result = IControlFlowEntryComparator.TRACE_COMPARATOR.compare(o1, o2); + return compareList(result, fDirection, SECONDARY_COMPARATORS, o1, o2); + } + + @Override + public void setDirection(int direction) { + fDirection = direction; + } + + private List> init() { + ImmutableList.Builder> builder = ImmutableList.builder(); + builder.add(IControlFlowEntryComparator.BIRTH_TIME_COMPARATOR) + .add(IControlFlowEntryComparator.PROCESS_NAME_COMPARATOR) + .add(IControlFlowEntryComparator.TID_COMPARATOR) + .add(IControlFlowEntryComparator.PTID_COMPARATOR); + return builder.build(); + } + }; + + private static int compareTrace(int direction, ITimeGraphEntry o1, ITimeGraphEntry o2) { + int result = IControlFlowEntryComparator.TRACE_COMPARATOR.compare(o1, o2); + if (direction == SWT.UP) { + result = -result; + } + return result; + } + + private static int compareList(int prevResult, int direction, List> comps, ITimeGraphEntry o1, ITimeGraphEntry o2) { + int result = prevResult; + for (Comparator comparator : comps) { + if (result == 0) { + result = comparator.compare(o1, o2); + if (direction == SWT.UP) { + result = -result; + } + } + } + return result; + } + +} diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/IControlFlowEntryComparator.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/IControlFlowEntryComparator.java new file mode 100644 index 0000000000..68424f33ad --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/IControlFlowEntryComparator.java @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2016 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.controlflow; + +import java.util.Comparator; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow.ControlFlowEntry; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; + +/** + * ControlFlowEntry comparators. These do not allow for null arguments. + * + * @author Bernd Hufmann + * @noimplement This interface only contains static definitions. + */ +public interface IControlFlowEntryComparator { + + /** + * Process Name Comparator + */ + Comparator PROCESS_NAME_COMPARATOR = new Comparator() { + @Override + public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) { + if (o1 == null || o2 == null || o1.getName() == null || o2.getName() == null) { + throw new IllegalArgumentException(); + } + return o1.getName().compareTo(o2.getName()); + } + }; + + /** + * TreadID Comparator + */ + Comparator TID_COMPARATOR = new Comparator() { + @Override + public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) { + if (o1 == null || o2 == null) { + throw new IllegalArgumentException(); + } + int result = 0; + if ((o1 instanceof ControlFlowEntry) && (o2 instanceof ControlFlowEntry)) { + ControlFlowEntry entry1 = (ControlFlowEntry) o1; + ControlFlowEntry entry2 = (ControlFlowEntry) o2; + result = Integer.compare(entry1.getThreadId(), entry2.getThreadId()); + } + return result; + } + }; + + /** + * Parent ThreadID Comparator + */ + Comparator PTID_COMPARATOR = new Comparator() { + @Override + public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) { + if (o1 == null || o2 == null) { + throw new IllegalArgumentException(); + } + int result = 0; + if ((o1 instanceof ControlFlowEntry) && (o2 instanceof ControlFlowEntry)) { + ControlFlowEntry entry1 = (ControlFlowEntry) o1; + ControlFlowEntry entry2 = (ControlFlowEntry) o2; + result = Integer.compare(entry1.getParentThreadId(), entry2.getParentThreadId()); + } + return result; + } + }; + + /** + * Birth time Comparator + */ + Comparator BIRTH_TIME_COMPARATOR = new Comparator() { + @Override + public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) { + if (o1 == null || o2 == null) { + throw new IllegalArgumentException(); + } + return Long.compare(o1.getStartTime(), o2.getStartTime()); + } + }; + + /** + * Trace Comparator (uses trace start time and name) + */ + Comparator TRACE_COMPARATOR = new Comparator() { + @Override + public int compare(@Nullable ITimeGraphEntry o1, @Nullable ITimeGraphEntry o2) { + if (o1 == null || o2 == null) { + throw new IllegalArgumentException(); + } + int result = 0; + if ((o1 instanceof ControlFlowEntry) && (o2 instanceof ControlFlowEntry)) { + ITmfTrace trace1 = ((ControlFlowEntry) o1).getTrace(); + ITmfTrace trace2 = ((ControlFlowEntry) o2).getTrace(); + result = trace1.getStartTime().compareTo(trace2.getStartTime()); + if (result == 0) { + result = trace1.getName().compareTo(trace2.getName()); + } + } + return result; + } + }; + +} diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java index 204a184c84..cfb810cc2b 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java @@ -60,10 +60,13 @@ import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; import org.eclipse.tracecompass.internal.tmf.ui.Activator; import org.eclipse.tracecompass.tmf.core.resources.ITmfMarker; @@ -191,6 +194,11 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA /** The tree column label array, or null if combo is not used */ private String[] fColumns; + private Comparator[] fColumnComparators; + + /** The sort direction */ + private int fDirection = SWT.DOWN; + /** The tree label provider, or null if combo is not used */ private TreeLabelProvider fLabelProvider = null; @@ -217,6 +225,12 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA /** The list of color resources created by this view */ private final List fColors = new ArrayList<>(); + /** The default column index for sorting */ + private int fInitialSortColumn = 0; + + /** Flag to indicate to reveal selection */ + private volatile boolean fIsRevealSelection = false; + // ------------------------------------------------------------------------ // Classes // ------------------------------------------------------------------------ @@ -785,8 +799,28 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA * The array of tree column labels */ protected void setTreeColumns(final String[] columns) { + setTreeColumns(columns, null, 0); + } + + /** + * Sets the tree column labels. + *

+ * This should be called from the constructor. + * + * @param columns + * The array of tree column labels + * @param comparators + * An array of column comparators for sorting of columns when + * clicking on column header + * @param initialSortColumn + * Index of column to sort initially + * @since 2.0 + */ + protected void setTreeColumns(final String[] columns, final Comparator[] comparators, int initialSortColumn) { checkPartNotCreated(); fColumns = columns; + fColumnComparators = comparators; + fInitialSortColumn = initialSortColumn; } /** @@ -1091,6 +1125,9 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA combo.setTreeContentProvider(fTimeGraphContentProvider); combo.setTreeLabelProvider(fLabelProvider); combo.setTreeColumns(fColumns); + if (fColumnComparators != null) { + createColumnSelectionListener(combo.getTreeViewer()); + } } fTimeGraphWrapper.setTimeGraphContentProvider(fTimeGraphContentProvider); fTimeGraphWrapper.setFilterContentProvider(fFilterContentProvider != null ? fFilterContentProvider : fTimeGraphContentProvider); @@ -1254,6 +1291,8 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA return bookmarks; } + + // ------------------------------------------------------------------------ // Signal handlers // ------------------------------------------------------------------------ @@ -1642,6 +1681,7 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA fTimeGraphWrapper.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile)); fTimeGraphWrapper.getTimeGraphViewer().setMarkerCategories(getMarkerCategories()); fTimeGraphWrapper.getTimeGraphViewer().setMarkers(null); + resetColumnSorting(); } else { fTimeGraphWrapper.refresh(); } @@ -1672,9 +1712,17 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA } } + // reveal selection + if (fIsRevealSelection && fTimeGraphWrapper instanceof TimeGraphComboWrapper) { + fIsRevealSelection = false; + ITimeGraphEntry entry1 = fTimeGraphWrapper.getTimeGraphViewer().getSelection(); + fTimeGraphWrapper.getTimeGraphViewer().setSelection(entry1); + } + if (!zoomThread) { startZoomThread(startTime, endTime); } + } }); } @@ -1711,7 +1759,7 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA }); } - private static void sortChildren(ITimeGraphEntry entry, Comparator comparator) { + private void sortChildren(ITimeGraphEntry entry, Comparator comparator) { if (entry instanceof TimeGraphEntry) { ((TimeGraphEntry) entry).sortChildren(comparator); } @@ -1867,4 +1915,54 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA return fDirty.get() != 0 || fZoomThread.getZoomStartTime() != fTimeGraphWrapper.getTimeGraphViewer().getTime0() || fZoomThread.getZoomEndTime() != fTimeGraphWrapper.getTimeGraphViewer().getTime1(); } + private void createColumnSelectionListener(TreeViewer treeViewer) { + for (int i = 0; i < fColumnComparators.length; i++) { + final Comparator comp = fColumnComparators[i]; + final Tree tree = treeViewer.getTree(); + final TreeColumn column = tree.getColumn(i); + + if (comp != null) { + column.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + TreeColumn prevSortcolumn = tree.getSortColumn(); + if (prevSortcolumn == column) { + fDirection = (fDirection == SWT.DOWN) ? SWT.UP : SWT.DOWN; + } else { + fDirection = SWT.DOWN; + } + tree.setSortColumn(column); + tree.setSortDirection(fDirection); + Comparator comparator = comp; + if (comparator instanceof ITimeGraphEntryComparator) { + ((ITimeGraphEntryComparator) comparator).setDirection(fDirection); + } + if (fDirection != SWT.DOWN) { + comparator = checkNotNull(Collections.reverseOrder(comparator)); + } + setEntryComparator(comparator); + fIsRevealSelection = true; + if (fTimeGraphWrapper instanceof TimeGraphComboWrapper) { + ((TimeGraphComboWrapper) fTimeGraphWrapper).getTreeViewer().getControl().setFocus(); + } + refresh(); + } + }); + } + } + } + + private void resetColumnSorting() { + if ((fTimeGraphWrapper instanceof TimeGraphComboWrapper) && (fColumnComparators != null)) { + TreeViewer treeViewer = ((TimeGraphComboWrapper) fTimeGraphWrapper).getTreeViewer(); + fDirection = SWT.DOWN; + if ((fInitialSortColumn < fColumnComparators.length) && (fColumnComparators[fInitialSortColumn] != null)) { + setEntryComparator(fColumnComparators[fInitialSortColumn]); + } + final Tree tree = treeViewer.getTree(); + final TreeColumn column = tree.getColumn(fInitialSortColumn); + tree.setSortDirection(fDirection); + tree.setSortColumn(column); + } + } } diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/ITimeGraphEntryComparator.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/ITimeGraphEntryComparator.java new file mode 100644 index 0000000000..2387dc003c --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/ITimeGraphEntryComparator.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2016 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.tracecompass.tmf.ui.views.timegraph; + +import java.util.Comparator; + +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; + +/** + * Comparator interface for for sorting of time graph entries. + * + * Use this comparator interface for sorting of time graph entries where a different + * behavior is required depending on the sort direction. + * + * @author Bernd Hufmann + * @since 2.0 + * + */ +public interface ITimeGraphEntryComparator extends Comparator { + + /** + * Sets the sort direction. + * + * @param direction + * The sort direction + */ + void setDirection(int direction); +}