analysis: support for sorting of control flow view columns
authorBernd Hufmann <Bernd.Hufmann@ericsson.com>
Tue, 12 Jan 2016 17:53:59 +0000 (12:53 -0500)
committerBernd Hufmann <bernd.hufmann@ericsson.com>
Fri, 22 Jan 2016 15:31:18 +0000 (10:31 -0500)
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 <Bernd.Hufmann@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/64403
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-by: Patrick Tasse <patrick.tasse@gmail.com>
Tested-by: Patrick Tasse <patrick.tasse@gmail.com>
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/META-INF/MANIFEST.MF
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/ControlFlowColumnComparators.java [new file with mode: 0644]
analysis/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/views/controlflow/IControlFlowEntryComparator.java [new file with mode: 0644]
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/AbstractTimeGraphView.java
tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/views/timegraph/ITimeGraphEntryComparator.java [new file with mode: 0644]

index 406fc3db691e96809a50fc2f245d439dc9a2acb3..183e7d86214048f811d4509670643786ca1916ef 100644 (file)
@@ -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"
index d4b36b38038f07294badc9a92b94d3a19b9c247d..99dc269f6f5caed7af99f1f4d8e835831d10cad6 100644 (file)
@@ -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<ITimeGraphEntry>[] COLUMN_COMPARATORS;
+
+    static {
+        ImmutableList.Builder<Comparator<ITimeGraphEntry>> 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<Comparator<ITimeGraphEntry>> 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<ITimeGraphEntry> {
-
-        @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 (file)
index 0000000..3bcc410
--- /dev/null
@@ -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<Comparator<ITimeGraphEntry>> 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<Comparator<ITimeGraphEntry>> init() {
+            ImmutableList.Builder<Comparator<ITimeGraphEntry>> 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<Comparator<ITimeGraphEntry>> 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<Comparator<ITimeGraphEntry>> init() {
+            ImmutableList.Builder<Comparator<ITimeGraphEntry>> 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<Comparator<ITimeGraphEntry>> 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<Comparator<ITimeGraphEntry>> init() {
+            ImmutableList.Builder<Comparator<ITimeGraphEntry>> 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<Comparator<ITimeGraphEntry>> 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<Comparator<ITimeGraphEntry>> init() {
+            ImmutableList.Builder<Comparator<ITimeGraphEntry>> 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<Comparator<ITimeGraphEntry>> 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<Comparator<ITimeGraphEntry>> init() {
+            ImmutableList.Builder<Comparator<ITimeGraphEntry>> 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<Comparator<ITimeGraphEntry>> comps, ITimeGraphEntry o1, ITimeGraphEntry o2) {
+        int result = prevResult;
+        for (Comparator<ITimeGraphEntry> 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 (file)
index 0000000..68424f3
--- /dev/null
@@ -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<ITimeGraphEntry> PROCESS_NAME_COMPARATOR = new Comparator<ITimeGraphEntry>() {
+        @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<ITimeGraphEntry> TID_COMPARATOR = new Comparator<ITimeGraphEntry>() {
+        @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<ITimeGraphEntry> PTID_COMPARATOR = new Comparator<ITimeGraphEntry>() {
+        @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<ITimeGraphEntry> BIRTH_TIME_COMPARATOR = new Comparator<ITimeGraphEntry>() {
+        @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<ITimeGraphEntry> TRACE_COMPARATOR = new Comparator<ITimeGraphEntry>() {
+        @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;
+        }
+    };
+
+}
index 204a184c847ab333406567287a68359a6e54f83c..cfb810cc2bf2dcdd226a2369bf6f78501d1848cc 100644 (file)
@@ -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<ITimeGraphEntry>[] 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<Color> 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.
+     * <p>
+     * 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<ITimeGraphEntry>[] 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<ITimeGraphEntry> comparator) {
+    private void sortChildren(ITimeGraphEntry entry, Comparator<ITimeGraphEntry> 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<ITimeGraphEntry> 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<ITimeGraphEntry> 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 (file)
index 0000000..2387dc0
--- /dev/null
@@ -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<ITimeGraphEntry> {
+
+    /**
+     * Sets the sort direction.
+     *
+     * @param direction
+     *            The sort direction
+     */
+    void setDirection(int direction);
+}
This page took 0.033645 seconds and 5 git commands to generate.