tmf: Preserve order of marker categories
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / timegraph / AbstractTimeGraphView.java
index 7475a289d1e22475f4f023ed9cf04c1c78ff5323..6ad0a95602a4e20798a41925963f7a8e36107e27 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012, 2015 Ericsson, École Polytechnique de Montréal
+ * Copyright (c) 2012, 2016 Ericsson, École Polytechnique de Montréal
  *
  * All rights reserved. This program and the accompanying materials are
  * made available under the terms of the Eclipse Public License v1.0 which
@@ -22,11 +22,12 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -59,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.graphics.Color;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.RGBA;
 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;
@@ -134,6 +138,8 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
     /** The timegraph wrapper */
     private ITimeGraphWrapper fTimeGraphWrapper;
 
+    private AtomicInteger fDirty = new AtomicInteger();
+
     /** The selected trace */
     private ITmfTrace fTrace;
 
@@ -147,7 +153,10 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
     private final Map<ITmfTrace, List<TimeGraphEntry>> fEntryListMap = new HashMap<>();
 
     /** The trace to filters hash map */
-    private final Map<ITmfTrace, ViewerFilter[]> fFiltersMap = new HashMap<>();
+    private final Map<ITmfTrace, @NonNull ViewerFilter[]> fFiltersMap = new HashMap<>();
+
+    /** The trace to view context hash map */
+    private final Map<ITmfTrace, ViewContext> fViewContext = new HashMap<>();
 
     /** The trace to marker event sources hash map */
     private final Map<ITmfTrace, List<IMarkerEventSource>> fMarkerEventSourcesMap = new HashMap<>();
@@ -188,6 +197,8 @@ 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 tree label provider, or null if combo is not used */
     private TreeLabelProvider fLabelProvider = null;
 
@@ -203,13 +214,25 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
     /** The pack done flag */
     private boolean fPackDone = false;
 
+    /** The filter content provider, or null if filter is not used */
+    private ITreeContentProvider fFilterContentProvider;
+
     /** The filter label provider, or null if filter is not used */
     private TreeLabelProvider fFilterLabelProvider;
 
     private int fAutoExpandLevel = ALL_LEVELS;
 
-    /** 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;
+
+    /** The default column index for sorting */
+    private int fCurrentSortColumn = 0;
+
+    /** The current sort direction */
+    private int fSortDirection = SWT.DOWN;
+
+    /** Flag to indicate to reveal selection */
+    private volatile boolean fIsRevealSelection = false;
 
     // ------------------------------------------------------------------------
     // Classes
@@ -237,9 +260,9 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
 
         Object getInput();
 
-        void setFilters(ViewerFilter[] filters);
+        void setFilters(@NonNull ViewerFilter[] filters);
 
-        ViewerFilter[] getFilters();
+        @NonNull ViewerFilter[] getFilters();
 
         void redraw();
 
@@ -260,6 +283,10 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
         TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo();
 
         int getAvailableWidth(int requestedOffset);
+
+        ITimeGraphEntry getSelection();
+
+        void setSelection(ITimeGraphEntry selection);
     }
 
     private class TimeGraphViewerWrapper implements ITimeGraphWrapper {
@@ -330,12 +357,12 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
         }
 
         @Override
-        public void setFilters(ViewerFilter[] filters) {
+        public void setFilters(@NonNull ViewerFilter[] filters) {
             viewer.setFilters(filters);
         }
 
         @Override
-        public ViewerFilter[] getFilters() {
+        public @NonNull ViewerFilter[] getFilters() {
             return viewer.getFilters();
         }
 
@@ -378,6 +405,16 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
         public int getAvailableWidth(int requestedOffset) {
             return viewer.getAvailableWidth(requestedOffset);
         }
+
+        @Override
+        public ITimeGraphEntry getSelection() {
+            return viewer.getSelection();
+        }
+
+        @Override
+        public void setSelection(ITimeGraphEntry selection) {
+            viewer.setSelection(selection);
+        }
     }
 
     private class TimeGraphComboWrapper implements ITimeGraphWrapper {
@@ -448,12 +485,12 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
         }
 
         @Override
-        public void setFilters(ViewerFilter[] filters) {
+        public void setFilters(@NonNull ViewerFilter[] filters) {
             combo.setFilters(filters);
         }
 
         @Override
-        public ViewerFilter[] getFilters() {
+        public @NonNull ViewerFilter[] getFilters() {
             return combo.getFilters();
         }
 
@@ -504,6 +541,16 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
         public int getAvailableWidth(int requestedOffset) {
             return combo.getAvailableWidth(requestedOffset);
         }
+
+        @Override
+        public ITimeGraphEntry getSelection() {
+            return combo.getTimeGraphViewer().getSelection();
+        }
+
+        @Override
+        public void setSelection(ITimeGraphEntry selection) {
+            combo.setSelection(selection);
+        }
     }
 
     /**
@@ -644,6 +691,18 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
         public void cancel() {
             fMonitor.setCanceled(true);
         }
+
+        @Override
+        public final void run() {
+            doRun();
+            fDirty.decrementAndGet();
+        }
+
+        /**
+         * Run the zoom operation.
+         * @since 2.0
+         */
+        public abstract void doRun();
     }
 
     private class ZoomThreadByEntry extends ZoomThread {
@@ -655,7 +714,7 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
         }
 
         @Override
-        public void run() {
+        public void doRun() {
             for (TimeGraphEntry entry : fZoomEntryList) {
                 if (getMonitor().isCanceled()) {
                     return;
@@ -760,71 +819,123 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
 
     /**
      * Sets the tree column labels.
+     * <p>
      * This should be called from the constructor.
      *
      * @param columns
      *            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;
     }
 
     /**
      * Sets the tree label provider.
+     * <p>
      * This should be called from the constructor.
      *
      * @param tlp
      *            The tree label provider
      */
     protected void setTreeLabelProvider(final TreeLabelProvider tlp) {
+        checkPartNotCreated();
         fLabelProvider = tlp;
     }
 
     /**
-     * Sets the time graph content provider. This should be called from the
-     * constructor.
+     * Sets the time graph content provider.
+     * <p>
+     * This should be called from the constructor.
      *
      * @param tgcp
      *            The time graph content provider
      * @since 1.0
      */
     protected void setTimeGraphContentProvider(final @NonNull ITimeGraphContentProvider tgcp) {
+        checkPartNotCreated();
         fTimeGraphContentProvider = tgcp;
     }
 
     /**
      * Sets the relative weight of each part of the time graph combo.
+     * <p>
      * This should be called from the constructor.
      *
      * @param weights
      *            The array (length 2) of relative weights of each part of the combo
      */
     protected void setWeight(final int[] weights) {
+        checkPartNotCreated();
         fWeight = weights;
     }
 
     /**
      * Sets the filter column labels.
+     * <p>
      * This should be called from the constructor.
      *
      * @param filterColumns
      *            The array of filter column labels
      */
     protected void setFilterColumns(final String[] filterColumns) {
+        checkPartNotCreated();
         fFilterColumns = filterColumns;
     }
 
+    /**
+     * Sets the filter content provider.
+     * <p>
+     * This should be called from the constructor.
+     *
+     * @param contentProvider
+     *            The filter content provider
+     * @since 2.0
+     */
+    protected void setFilterContentProvider(final ITreeContentProvider contentProvider) {
+        checkPartNotCreated();
+        fFilterContentProvider = contentProvider;
+    }
+
     /**
      * Sets the filter label provider.
+     * <p>
      * This should be called from the constructor.
      *
      * @param labelProvider
      *            The filter label provider
      */
     protected void setFilterLabelProvider(final TreeLabelProvider labelProvider) {
+        checkPartNotCreated();
         fFilterLabelProvider = labelProvider;
     }
 
+    private void checkPartNotCreated() {
+        if (getParentComposite() != null) {
+            throw new IllegalStateException("This method must be called before createPartControl."); //$NON-NLS-1$
+        }
+    }
+
     /**
      * Gets the display width
      *
@@ -844,7 +955,10 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
     }
 
     /**
-     * Sets the comparator class for the entries
+     * Sets the comparator class for the entries.
+     * <p>
+     * This comparator will apply recursively to entries that implement
+     * {@link TimeGraphEntry#sortChildren(Comparator)}.
      *
      * @param comparator
      *            A comparator object
@@ -1038,9 +1152,12 @@ 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(fTimeGraphContentProvider);
+        fTimeGraphWrapper.setFilterContentProvider(fFilterContentProvider != null ? fFilterContentProvider : fTimeGraphContentProvider);
         fTimeGraphWrapper.setFilterLabelProvider(fFilterLabelProvider);
         fTimeGraphWrapper.setFilterColumns(fFilterColumns);
 
@@ -1089,7 +1206,7 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
                                         NLS.bind(org.eclipse.tracecompass.internal.tmf.ui.Messages.TmfMarker_LocationTime,
                                                 new TmfNanoTimestamp(bookmark.getTime())));
                             }
-                            marker.setAttribute(ITmfMarker.MARKER_COLOR, bookmark.getColor().getRGBA().toString());
+                            marker.setAttribute(ITmfMarker.MARKER_COLOR, bookmark.getColor().toString());
                         }
                     }, null);
                 } catch (CoreException e) {
@@ -1106,7 +1223,7 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
                         if (bookmark.getLabel().equals(marker.getAttribute(IMarker.MESSAGE)) &&
                                 Long.toString(bookmark.getTime()).equals(marker.getAttribute(ITmfMarker.MARKER_TIME, (String) null)) &&
                                 Long.toString(bookmark.getDuration()).equals(marker.getAttribute(ITmfMarker.MARKER_DURATION, Long.toString(0))) &&
-                                bookmark.getColor().getRGBA().toString().equals(marker.getAttribute(ITmfMarker.MARKER_COLOR))) {
+                                bookmark.getColor().toString().equals(marker.getAttribute(ITmfMarker.MARKER_COLOR))) {
                             marker.delete();
                             break;
                         }
@@ -1162,12 +1279,8 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
         }
     }
 
-    private List<IMarkerEvent> refreshBookmarks(final IFile editorFile) {
+    private static List<IMarkerEvent> refreshBookmarks(final IFile editorFile) {
         List<IMarkerEvent> bookmarks = new ArrayList<>();
-        for (Color color : fColors) {
-            color.dispose();
-        }
-        fColors.clear();
         if (editorFile == null || !editorFile.exists()) {
             return bookmarks;
         }
@@ -1186,8 +1299,7 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
                             int green = Integer.valueOf(matcher.group(2));
                             int blue = Integer.valueOf(matcher.group(3));
                             int alpha = Integer.valueOf(matcher.group(4));
-                            Color color = new Color(Display.getDefault(), red, green, blue, alpha);
-                            fColors.add(color);
+                            RGBA color = new RGBA(red, green, blue, alpha);
                             bookmarks.add(new MarkerEvent(null, Long.valueOf(time), Long.valueOf(duration), IMarkerEvent.BOOKMARKS, color, label, true));
                         } catch (NumberFormatException e) {
                             Activator.getDefault().logError(e.getMessage());
@@ -1201,6 +1313,8 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
         return bookmarks;
     }
 
+
+
     // ------------------------------------------------------------------------
     // Signal handlers
     // ------------------------------------------------------------------------
@@ -1244,13 +1358,14 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
                 if (buildThread != null) {
                     buildThread.cancel();
                 }
-                fMarkerEventSourcesMap.remove(trace);
             }
         }
+        fMarkerEventSourcesMap.remove(signal.getTrace());
         synchronized (fEntryListMap) {
             fEntryListMap.remove(signal.getTrace());
         }
         fFiltersMap.remove(signal.getTrace());
+        fViewContext.remove(signal.getTrace());
         if (signal.getTrace() == fTrace) {
             fTrace = null;
             fEditorFile = null;
@@ -1288,9 +1403,9 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
                 if (beginTime == endTime) {
                     fTimeGraphWrapper.getTimeGraphViewer().setSelectedTime(beginTime, true);
                 } else {
-                    fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(beginTime, endTime);
+                    fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(beginTime, endTime, true);
                 }
-                synchingToTime(fTimeGraphWrapper.getTimeGraphViewer().getTime0());
+                synchingToTime(fTimeGraphWrapper.getTimeGraphViewer().getSelectionBegin());
             }
         });
     }
@@ -1344,8 +1459,10 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
         if (fTrace != null) {
             /* save the filters of the previous trace */
             fFiltersMap.put(fTrace, fTimeGraphWrapper.getFilters());
+            fViewContext.put(fTrace, new ViewContext(fCurrentSortColumn, fSortDirection, fTimeGraphWrapper.getSelection()));
         }
         fTrace = trace;
+        restoreViewContext();
         fEditorFile = TmfTraceManager.getInstance().getTraceEditorFile(trace);
         synchronized (fEntryListMap) {
             fEntryList = fEntryListMap.get(fTrace);
@@ -1370,17 +1487,19 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
         if (viewTrace == null) {
             return;
         }
+        List<IMarkerEventSource> markerEventSources = new ArrayList<>();
         synchronized (fBuildThreadMap) {
             for (ITmfTrace trace : getTracesToBuild(viewTrace)) {
                 if (trace == null) {
                     break;
                 }
-                fMarkerEventSourcesMap.put(trace, TmfTraceAdapterManager.getAdapters(trace, IMarkerEventSource.class));
+                markerEventSources.addAll(TmfTraceAdapterManager.getAdapters(trace, IMarkerEventSource.class));
                 BuildThread buildThread = new BuildThread(trace, viewTrace, getName());
                 fBuildThreadMap.put(trace, buildThread);
                 buildThread.start();
             }
         }
+        fMarkerEventSourcesMap.put(viewTrace, markerEventSources);
     }
 
     /**
@@ -1439,7 +1558,7 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
      *            The progress monitor object
      * @return The list of events for the entry
      */
-    protected abstract @Nullable List<ITimeEvent> getEventList(@NonNull TimeGraphEntry entry,
+    protected abstract @Nullable List<@NonNull ITimeEvent> getEventList(@NonNull TimeGraphEntry entry,
             long startTime, long endTime, long resolution,
             @NonNull IProgressMonitor monitor);
 
@@ -1457,7 +1576,7 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
      *            The progress monitor object
      * @return The list of link events
      */
-    protected @Nullable List<ILinkEvent> getLinkList(long startTime, long endTime,
+    protected @Nullable List<@NonNull ILinkEvent> getLinkList(long startTime, long endTime,
             long resolution, @NonNull IProgressMonitor monitor) {
         return new ArrayList<>();
     }
@@ -1510,7 +1629,7 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
     protected @NonNull List<IMarkerEvent> getTraceMarkerList(long startTime, long endTime,
             long resolution, @NonNull IProgressMonitor monitor) {
         List<IMarkerEvent> markers = new ArrayList<>();
-        for (IMarkerEventSource markerEventSource : getMarkerEventSources(getTrace())) {
+        for (IMarkerEventSource markerEventSource : getMarkerEventSources(fTrace)) {
             for (String category : markerEventSource.getMarkerCategories()) {
                 if (monitor.isCanceled()) {
                     break;
@@ -1528,7 +1647,7 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
      * @since 2.0
      */
     private @NonNull List<String> getMarkerCategories() {
-        Set<String> categories = new HashSet<>(getViewMarkerCategories());
+        Set<String> categories = new LinkedHashSet<>(getViewMarkerCategories());
         for (IMarkerEventSource markerEventSource : getMarkerEventSources(fTrace)) {
             categories.addAll(markerEventSource.getMarkerCategories());
         }
@@ -1570,20 +1689,45 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
                     } else if (fEntryComparator != null) {
                         List<TimeGraphEntry> list = new ArrayList<>(fEntryList);
                         Collections.sort(list, fEntryComparator);
+                        for (ITimeGraphEntry entry : list) {
+                            sortChildren(entry, fEntryComparator);
+                        }
                         fEntryList.clear();
                         fEntryList.addAll(list);
                     }
-                    hasEntries = fEntryList.size() != 0;
+                    hasEntries = !fEntryList.isEmpty();
                 }
-                if (fEntryList != fTimeGraphWrapper.getInput()) {
-                    fTimeGraphWrapper.setInput(fEntryList);
-                    /* restore the previously saved filters, if any */
-                    fTimeGraphWrapper.setFilters(fFiltersMap.get(fTrace));
-                    fTimeGraphWrapper.getTimeGraphViewer().setLinks(null);
-                    fTimeGraphWrapper.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile));
-                    fTimeGraphWrapper.getTimeGraphViewer().setMarkerCategories(getMarkerCategories());
-                } else {
-                    fTimeGraphWrapper.refresh();
+                boolean inputChanged = fEntryList != fTimeGraphWrapper.getInput();
+                TimeGraphCombo combo = getTimeGraphCombo();
+                try {
+                    // Set redraw to false to only draw once
+                    if (combo != null) {
+                        combo.getTreeViewer().getTree().setRedraw(false);
+                    }
+                    getTimeGraphViewer().getTimeGraphControl().setRedraw(false);
+                    if (inputChanged) {
+                        fTimeGraphWrapper.setInput(fEntryList);
+                        /* restore the previously saved filters, if any */
+                        fTimeGraphWrapper.setFilters(fFiltersMap.get(fTrace));
+                        fTimeGraphWrapper.getTimeGraphViewer().setLinks(null);
+                        fTimeGraphWrapper.getTimeGraphViewer().setBookmarks(refreshBookmarks(fEditorFile));
+                        fTimeGraphWrapper.getTimeGraphViewer().setMarkerCategories(getMarkerCategories());
+                        fTimeGraphWrapper.getTimeGraphViewer().setMarkers(null);
+                        applyViewContext();
+                    } else {
+                        fTimeGraphWrapper.refresh();
+                    }
+                    // reveal selection
+                    if (fIsRevealSelection) {
+                        fIsRevealSelection = false;
+                        ITimeGraphEntry entry1 = fTimeGraphWrapper.getSelection();
+                        fTimeGraphWrapper.setSelection(entry1);
+                    }
+                } finally {
+                    if (combo != null) {
+                        combo.getTreeViewer().getTree().setRedraw(true);
+                    }
+                    getTimeGraphViewer().getTimeGraphControl().setRedraw(true);
                 }
                 long startBound = (fStartTime == Long.MAX_VALUE ? SWT.DEFAULT : fStartTime);
                 long endBound = (fEndTime == Long.MIN_VALUE ? SWT.DEFAULT : fEndTime);
@@ -1596,9 +1740,13 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
                 long endTime = fTrace == null ? SWT.DEFAULT : ctx.getWindowRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
                 startTime = (fStartTime == Long.MAX_VALUE ? SWT.DEFAULT : Math.max(startTime, fStartTime));
                 endTime = (fEndTime == Long.MIN_VALUE ? SWT.DEFAULT : Math.min(endTime, fEndTime));
-                fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime);
+                fTimeGraphWrapper.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime, false);
                 fTimeGraphWrapper.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
 
+                if (inputChanged && selectionBeginTime != SWT.DEFAULT) {
+                    synchingToTime(selectionBeginTime);
+                }
+
                 if (fTimeGraphWrapper instanceof TimeGraphComboWrapper && !fPackDone) {
                     for (TreeColumn column : ((TimeGraphComboWrapper) fTimeGraphWrapper).getTreeViewer().getTree().getColumns()) {
                         column.pack();
@@ -1611,6 +1759,7 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
                 if (!zoomThread) {
                     startZoomThread(startTime, endTime);
                 }
+
             }
         });
     }
@@ -1647,7 +1796,26 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
         });
     }
 
-    private void startZoomThread(long startTime, long endTime) {
+    private void sortChildren(ITimeGraphEntry entry, Comparator<ITimeGraphEntry> comparator) {
+        if (entry instanceof TimeGraphEntry) {
+            ((TimeGraphEntry) entry).sortChildren(comparator);
+        }
+        for (ITimeGraphEntry child : entry.getChildren()) {
+            sortChildren(child, comparator);
+        }
+    }
+
+    /**
+     * Start or restart the zoom thread.
+     *
+     * @param startTime
+     *            the zoom start time
+     * @param endTime
+     *            the zoom end time
+     * @since 2.0
+     */
+    protected final void startZoomThread(long startTime, long endTime) {
+        fDirty.incrementAndGet();
         boolean restart = false;
         if (fZoomThread != null) {
             fZoomThread.cancel();
@@ -1659,6 +1827,8 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
         fZoomThread = createZoomThread(startTime, endTime, resolution, restart);
         if (fZoomThread != null) {
             fZoomThread.start();
+        } else {
+            fDirty.decrementAndGet();
         }
     }
 
@@ -1766,4 +1936,135 @@ public abstract class AbstractTimeGraphView extends TmfView implements ITmfTimeA
             fTimeGraphWrapper.performAlign(offset, width);
         }
     }
+
+    /**
+     * Returns whether or not the time graph view is dirty. The time graph view
+     * is considered dirty if it has yet to completely update its model.
+     *
+     * @return true if the time graph view has yet to completely update its
+     *         model, false otherwise
+     * @since 2.0
+     */
+    public boolean isDirty() {
+        if (fZoomThread == null) {
+            return false;
+        }
+        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 int index = i;
+            final Comparator<ITimeGraphEntry> comp = fColumnComparators[index];
+            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();
+                        int direction = tree.getSortDirection();
+                        if (prevSortcolumn == column) {
+                            direction = (direction == SWT.DOWN) ? SWT.UP : SWT.DOWN;
+                        } else {
+                            direction = SWT.DOWN;
+                        }
+                        tree.setSortColumn(column);
+                        tree.setSortDirection(direction);
+                        fSortDirection = direction;
+                        fCurrentSortColumn = index;
+                        Comparator<ITimeGraphEntry> comparator = comp;
+
+                        if (comparator instanceof ITimeGraphEntryComparator) {
+                            ((ITimeGraphEntryComparator) comparator).setDirection(direction);
+                        }
+                        if (direction != SWT.DOWN) {
+                            comparator = checkNotNull(Collections.reverseOrder(comparator));
+                        }
+                        setEntryComparator(comparator);
+                        fIsRevealSelection = true;
+                        if (fTimeGraphWrapper instanceof TimeGraphComboWrapper) {
+                            ((TimeGraphComboWrapper) fTimeGraphWrapper).getTreeViewer().getControl().setFocus();
+                        }
+                        refresh();
+                    }
+                });
+            }
+        }
+    }
+
+    private void restoreViewContext() {
+        TimeGraphCombo combo = getTimeGraphCombo();
+        ViewContext viewContext = fViewContext.get(fTrace);
+        if (combo != null) {
+            if (fColumnComparators != null) {
+                // restore sort settings
+                fSortDirection = SWT.DOWN;
+                fCurrentSortColumn = fInitialSortColumn;
+                if (viewContext != null) {
+                    fSortDirection = viewContext.getSortDirection();
+                    fCurrentSortColumn = viewContext.getSortColumn();
+                }
+                if ((fCurrentSortColumn < fColumnComparators.length) && (fColumnComparators[fCurrentSortColumn] != null)) {
+                    Comparator<ITimeGraphEntry> comparator = fColumnComparators[fCurrentSortColumn];
+                    if (comparator instanceof ITimeGraphEntryComparator) {
+                        ((ITimeGraphEntryComparator) comparator).setDirection(fSortDirection);
+                    }
+                    if (fSortDirection != SWT.DOWN) {
+                        comparator = checkNotNull(Collections.reverseOrder(comparator));
+                    }
+                    setEntryComparator(comparator);
+                }
+            }
+        }
+    }
+
+    private void applyViewContext() {
+        TimeGraphCombo combo = getTimeGraphCombo();
+        ViewContext viewContext = fViewContext.get(fTrace);
+        if (combo != null) {
+            TreeViewer treeViewer = combo.getTreeViewer();
+            final Tree tree = treeViewer.getTree();
+            final TreeColumn column = tree.getColumn(fCurrentSortColumn);
+            tree.setSortDirection(fSortDirection);
+            tree.setSortColumn(column);
+            combo.getTreeViewer().getControl().setFocus();
+        }
+        // restore and reveal selection
+        if ((viewContext != null) && (viewContext.getSelection() != null)) {
+            fTimeGraphWrapper.setSelection(viewContext.getSelection());
+        }
+        fViewContext.remove(fTrace);
+    }
+
+    private static class ViewContext {
+        private int fSortColumnIndex;
+        private int fSortDirection;
+        private @Nullable ITimeGraphEntry fSelection;
+
+        ViewContext(int sortColunm, int sortDirection, ITimeGraphEntry selection) {
+            fSortColumnIndex = sortColunm;
+            fSortDirection = sortDirection;
+            fSelection = selection;
+        }
+        /**
+         * @return the sortColumn
+         */
+        public int getSortColumn() {
+            return fSortColumnIndex;
+        }
+        /**
+         * @return the sortDirection
+         */
+        public int getSortDirection() {
+            return fSortDirection;
+        }
+        /**
+         * @return the selection
+         */
+        public ITimeGraphEntry getSelection() {
+            return fSelection;
+        }
+    }
 }
This page took 0.036897 seconds and 5 git commands to generate.