tmf: Rename "Next/Previous Event" action to "Next/Previous State Change"
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / callstack / CallStackView.java
index 2f9ec2ce6accd1eeef29474290721003f08f7d87..f5eb13beeb1bbc75b1145daa147e0404c861f514 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2015 Ericsson
+ * Copyright (c) 2013, 2016 Ericsson and others.
  *
  * All rights reserved. This program and the accompanying materials are
  * made available under the terms of the Eclipse Public License v1.0 which
@@ -14,9 +14,6 @@
 
 package org.eclipse.tracecompass.tmf.ui.views.callstack;
 
-import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
-
-import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -24,43 +21,32 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Consumer;
 
 import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.GroupMarker;
 import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.action.IMenuManager;
 import org.eclipse.jface.action.IToolBarManager;
-import org.eclipse.jface.action.MenuManager;
 import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.dialogs.IDialogSettings;
 import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.jface.util.IPropertyChangeListener;
 import org.eclipse.jface.util.PropertyChangeEvent;
 import org.eclipse.jface.viewers.DoubleClickEvent;
 import org.eclipse.jface.viewers.IDoubleClickListener;
-import org.eclipse.jface.viewers.ILabelProviderListener;
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.ITableLabelProvider;
 import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ControlAdapter;
-import org.eclipse.swt.events.ControlEvent;
 import org.eclipse.swt.events.MouseAdapter;
 import org.eclipse.swt.events.MouseEvent;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.FileDialog;
-import org.eclipse.swt.widgets.Menu;
-import org.eclipse.swt.widgets.Tree;
-import org.eclipse.tracecompass.internal.tmf.core.callstack.FunctionNameMapper;
 import org.eclipse.tracecompass.internal.tmf.ui.Activator;
 import org.eclipse.tracecompass.internal.tmf.ui.ITmfImageConstants;
 import org.eclipse.tracecompass.internal.tmf.ui.Messages;
@@ -76,27 +62,22 @@ import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue.Type;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
-import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
 import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
 import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
-import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp;
 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampDelta;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
-import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
-import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
 import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils;
 import org.eclipse.tracecompass.tmf.ui.editors.ITmfTraceEditor;
-import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
-import org.eclipse.tracecompass.tmf.ui.views.ITmfTimeAligned;
-import org.eclipse.tracecompass.tmf.ui.views.TmfView;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProvider;
+import org.eclipse.tracecompass.tmf.ui.symbols.ISymbolProviderPreferencePage;
+import org.eclipse.tracecompass.tmf.ui.symbols.SymbolProviderConfigDialog;
+import org.eclipse.tracecompass.tmf.ui.symbols.SymbolProviderManager;
+import org.eclipse.tracecompass.tmf.ui.views.timegraph.AbstractTimeGraphView;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphCombo;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphContentProvider;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
@@ -106,16 +87,15 @@ import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeEvent;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphControl;
 import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.TimeGraphSelection;
-import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
-import org.eclipse.ui.IActionBars;
 import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchActionConstants;
 
 /**
  * Main implementation for the Call Stack view
  *
  * @author Patrick Tasse
  */
-public class CallStackView extends TmfView implements ITmfTimeAligned {
+public class CallStackView extends AbstractTimeGraphView {
 
     // ------------------------------------------------------------------------
     // Constants
@@ -124,14 +104,7 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
     /** View ID. */
     public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.callstack"; //$NON-NLS-1$
 
-    /**
-     * Redraw state enum
-     */
-    private enum State {
-        IDLE, BUSY, PENDING
-    }
-
-    private static final String[] COLUMN_TIMES = new String[] {
+    private static final String[] COLUMN_NAMES = new String[] {
             Messages.CallStackView_FunctionColumn,
             Messages.CallStackView_DepthColumn,
             Messages.CallStackView_EntryTimeColumn,
@@ -139,12 +112,8 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
             Messages.CallStackView_DurationColumn
     };
 
-    private static final int[] COLUMN_WIDTHS = new int[] {
-            200,
-            50,
-            120,
-            120,
-            120
+    private static final String[] FILTER_COLUMN_NAMES = new String[] {
+            Messages.CallStackView_ThreadColumn
     };
 
     /** Timeout between updates in the build thread in ms */
@@ -153,10 +122,10 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
     // Fraction of a function duration to be added as spacing
     private static final double SPACING_RATIO = 0.01;
 
+    private static final Image PROCESS_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/process_obj.gif"); //$NON-NLS-1$
     private static final Image THREAD_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/thread_obj.gif"); //$NON-NLS-1$
     private static final Image STACKFRAME_IMAGE = Activator.getDefault().getImageFromPath("icons/obj16/stckframe_obj.gif"); //$NON-NLS-1$
 
-    private static final String IMPORT_MAPPING_ICON_PATH = "icons/etool16/import.gif"; //$NON-NLS-1$
     private static final String IMPORT_BINARY_ICON_PATH = "icons/obj16/binaries_obj.gif"; //$NON-NLS-1$
 
     private static final ImageDescriptor SORT_BY_NAME_ICON = Activator.getDefault().getImageDescripterFromPath("icons/etool16/sort_alpha.gif"); //$NON-NLS-1$
@@ -171,8 +140,8 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
         BY_NAME, BY_NAME_REV, BY_ID, BY_ID_REV, BY_TIME, BY_TIME_REV
     }
 
-    private SortOption fSortOption;
-    private Comparator<ITimeGraphEntry> fThreadComparator = null;
+    private @NonNull SortOption fSortOption = SortOption.BY_NAME;
+    private @NonNull Comparator<ITimeGraphEntry> fThreadComparator = new ThreadNameComparator(false);
     private Action fSortByNameAction;
     private Action fSortByIdAction;
     private Action fSortByTimeAction;
@@ -181,35 +150,7 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
     // Fields
     // ------------------------------------------------------------------------
 
-    // The time graph combo
-    private TimeGraphCombo fTimeGraphCombo;
-
-    // The selected trace
-    private ITmfTrace fTrace;
-
-    // The selected thread map
-    private final Map<ITmfTrace, String> fSelectedThreadMap = new HashMap<>();
-
-    // The time graph entry list
-    private List<TraceEntry> fEntryList;
-
-    // The trace to entry list hash map
-    private final Map<ITmfTrace, List<TraceEntry>> fEntryListMap = new HashMap<>();
-
-    // The trace to build thread hash map
-    private final Map<ITmfTrace, BuildThread> fBuildThreadMap = new HashMap<>();
-
-    /** The map to map function addresses to function names */
-    private Map<String, String> fNameMapping;
-
-    // The start time
-    private long fStartTime = SWT.DEFAULT;
-
-    // The end time
-    private long fEndTime = SWT.DEFAULT;
-
-    // The display width
-    private int fDisplayWidth;
+    private final Map<ITmfTrace, ISymbolProvider> fSymbolProviders = new HashMap<>();
 
     // The next event action
     private Action fNextEventAction;
@@ -223,20 +164,8 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
     // The previous item action
     private Action fPreviousItemAction;
 
-    // The action to import a function-name mapping file
-    private Action fImportMappingAction;
-
     // The action to import a binary file mapping */
-    private Action fImportBinaryFileMappingAction;
-
-    // The zoom thread
-    private ZoomThread fZoomThread;
-
-    // The redraw state used to prevent unnecessary queuing of display runnables
-    private State fRedrawState = State.IDLE;
-
-    // The redraw synchronization object
-    private final Object fSyncObj = new Object();
+    private Action fConfigureSymbolsAction;
 
     // The saved time sync. signal used when switching off the pinning of a view
     private TmfSelectionRangeUpdatedSignal fSavedTimeSyncSignal;
@@ -245,11 +174,15 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
     // a view
     private TmfWindowRangeUpdatedSignal fSavedRangeSyncSignal;
 
+    // When set to true, syncToTime() will select the first call stack entry
+    // whose current state start time exactly matches the sync time.
+    private boolean fSyncSelection = false;
+
     // ------------------------------------------------------------------------
     // Classes
     // ------------------------------------------------------------------------
 
-    private class TraceEntry extends TimeGraphEntry {
+    private static class TraceEntry extends TimeGraphEntry {
         public TraceEntry(String name, long startTime, long endTime) {
             super(name, startTime, endTime);
         }
@@ -260,19 +193,28 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
         }
     }
 
-    private class ThreadEntry extends TimeGraphEntry {
-        // The call stack quark
-        private final int fCallStackQuark;
-        // The state system from which this entry comes
-        private final ITmfStateSystem fSS;
+    private static class ProcessEntry extends TimeGraphEntry {
+
+        private final int fProcessId;
+
+        public ProcessEntry(String name, int processId, long startTime, long endTime) {
+            super(name, startTime, endTime);
+            fProcessId = processId;
+        }
+
+        @Override
+        public boolean hasTimeEvents() {
+            return false;
+        }
+    }
+
+    private static class ThreadEntry extends TimeGraphEntry {
         // The thread id
         private final long fThreadId;
 
-        public ThreadEntry(ITmfStateSystem ss, String name, long threadId, int callStackQuark, long startTime, long endTime) {
+        public ThreadEntry(String name, long threadId, long startTime, long endTime) {
             super(name, startTime, endTime);
-            fCallStackQuark = callStackQuark;
             fThreadId = threadId;
-            fSS = ss;
         }
 
         @Override
@@ -280,21 +222,24 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
             return false;
         }
 
-        public int getCallStackQuark() {
-            return fCallStackQuark;
-        }
-
         public long getThreadId() {
             return fThreadId;
         }
+    }
 
-        @Nullable
-        public ITmfStateSystem getStateSystem() {
-            return fSS;
+    private class CallStackComparator implements Comparator<ITimeGraphEntry> {
+        @Override
+        public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
+            if (o1 instanceof ThreadEntry && o2 instanceof ThreadEntry) {
+                return fThreadComparator.compare(o1, o2);
+            } else if (o1 instanceof ProcessEntry && o2 instanceof ProcessEntry) {
+                return Integer.compare(((ProcessEntry) o1).fProcessId, ((ProcessEntry) o2).fProcessId);
+            }
+            return 0;
         }
     }
 
-    private class ThreadNameComparator implements Comparator<ITimeGraphEntry> {
+    private static class ThreadNameComparator implements Comparator<ITimeGraphEntry> {
         private boolean reverse;
 
         public ThreadNameComparator(boolean reverse) {
@@ -308,7 +253,7 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
         }
     }
 
-    private class ThreadIdComparator implements Comparator<ITimeGraphEntry> {
+    private static class ThreadIdComparator implements Comparator<ITimeGraphEntry> {
         private boolean reverse;
 
         public ThreadIdComparator(boolean reverse) {
@@ -317,14 +262,17 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
 
         @Override
         public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
-            ThreadEntry t1 = (ThreadEntry) o1;
-            ThreadEntry t2 = (ThreadEntry) o2;
-            return reverse ? Long.compare(t2.getThreadId(), t1.getThreadId()) :
+            if (o1 instanceof ThreadEntry && o2 instanceof ThreadEntry) {
+                ThreadEntry t1 = (ThreadEntry) o1;
+                ThreadEntry t2 = (ThreadEntry) o2;
+                return reverse ? Long.compare(t2.getThreadId(), t1.getThreadId()) :
                     Long.compare(t1.getThreadId(), t2.getThreadId());
+            }
+            return 0;
         }
     }
 
-    private class ThreadTimeComparator implements Comparator<ITimeGraphEntry> {
+    private static class ThreadTimeComparator implements Comparator<ITimeGraphEntry> {
         private boolean reverse;
 
         public ThreadTimeComparator(boolean reverse) {
@@ -338,29 +286,14 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
         }
     }
 
-    private class TreeLabelProvider implements ITableLabelProvider {
-
-        @Override
-        public void addListener(ILabelProviderListener listener) {
-        }
-
-        @Override
-        public void dispose() {
-        }
-
-        @Override
-        public boolean isLabelProperty(Object element, String property) {
-            return false;
-        }
-
-        @Override
-        public void removeListener(ILabelProviderListener listener) {
-        }
+    private static class CallStackTreeLabelProvider extends TreeLabelProvider {
 
         @Override
         public Image getColumnImage(Object element, int columnIndex) {
             if (columnIndex == 0) {
-                if (element instanceof ThreadEntry) {
+                if (element instanceof ProcessEntry) {
+                    return PROCESS_IMAGE;
+                } else if (element instanceof ThreadEntry) {
                     return THREAD_IMAGE;
                 } else if (element instanceof CallStackEntry) {
                     CallStackEntry entry = (CallStackEntry) element;
@@ -382,10 +315,10 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
                     int depth = entry.getStackLevel();
                     return Integer.toString(depth);
                 } else if (columnIndex == 2 && entry.getFunctionName().length() > 0) {
-                    ITmfTimestamp ts = new TmfTimestamp(entry.getFunctionEntryTime(), ITmfTimestamp.NANOSECOND_SCALE);
+                    ITmfTimestamp ts = TmfTimestamp.fromNanos(entry.getFunctionEntryTime());
                     return ts.toString();
                 } else if (columnIndex == 3 && entry.getFunctionName().length() > 0) {
-                    ITmfTimestamp ts = new TmfTimestamp(entry.getFunctionExitTime(), ITmfTimestamp.NANOSECOND_SCALE);
+                    ITmfTimestamp ts = TmfTimestamp.fromNanos(entry.getFunctionExitTime());
                     return ts.toString();
                 } else if (columnIndex == 4 && entry.getFunctionName().length() > 0) {
                     ITmfTimestamp ts = new TmfTimestampDelta(entry.getFunctionExitTime() - entry.getFunctionEntryTime(), ITmfTimestamp.NANOSECOND_SCALE);
@@ -401,82 +334,21 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
 
     }
 
-    private class BuildThread extends Thread {
-        private final @NonNull ITmfTrace fBuildTrace;
-        private final ITmfTrace fParentTrace;
-        private final IProgressMonitor fMonitor;
-
-        public BuildThread(@NonNull ITmfTrace trace, ITmfTrace parentTrace) {
-            super("CallStackView build"); //$NON-NLS-1$
-            fBuildTrace = trace;
-            fParentTrace = parentTrace;
-            fMonitor = new NullProgressMonitor();
-        }
-
+    private class CallStackFilterContentProvider extends TimeGraphContentProvider {
         @Override
-        public void run() {
-            buildThreadList(fBuildTrace, fParentTrace, fMonitor);
-            synchronized (fBuildThreadMap) {
-                fBuildThreadMap.remove(fBuildTrace);
+        public boolean hasChildren(Object element) {
+            if (element instanceof TraceEntry) {
+                return super.hasChildren(element);
             }
-        }
-
-        public void cancel() {
-            fMonitor.setCanceled(true);
-        }
-    }
-
-    private class ZoomThread extends Thread {
-        private final List<TraceEntry> fZoomEntryList;
-        private final long fZoomStartTime;
-        private final long fZoomEndTime;
-        private final IProgressMonitor fMonitor;
-
-        public ZoomThread(List<TraceEntry> entryList, long startTime, long endTime) {
-            super("CallStackView zoom"); //$NON-NLS-1$
-            fZoomEntryList = entryList;
-            fZoomStartTime = startTime;
-            fZoomEndTime = endTime;
-            fMonitor = new NullProgressMonitor();
+            return false;
         }
 
         @Override
-        public void run() {
-            if (fZoomEntryList == null) {
-                return;
-            }
-            long resolution = Math.max(1, (fZoomEndTime - fZoomStartTime) / fDisplayWidth);
-            for (TraceEntry traceEntry : fZoomEntryList) {
-                for (ITimeGraphEntry threadEntry : traceEntry.getChildren()) {
-                    ITmfStateSystem ss = ((ThreadEntry) threadEntry).getStateSystem();
-                    if (ss == null) {
-                        continue;
-                    }
-                    ss.waitUntilBuilt();
-                    if (ss.isCancelled()) {
-                        continue;
-                    }
-                    for (ITimeGraphEntry child : threadEntry.getChildren()) {
-                        if (fMonitor.isCanceled()) {
-                            break;
-                        }
-                        CallStackEntry entry = (CallStackEntry) child;
-                        if (fZoomStartTime <= fStartTime && fZoomEndTime >= fEndTime) {
-                            entry.setZoomedEventList(null);
-                        } else {
-                            List<ITimeEvent> zoomedEventList = getEventList(entry, fZoomStartTime, fZoomEndTime, resolution, fMonitor);
-                            if (zoomedEventList != null) {
-                                entry.setZoomedEventList(zoomedEventList);
-                            }
-                        }
-                        redraw();
-                    }
-                }
+        public ITimeGraphEntry[] getChildren(Object parentElement) {
+            if (parentElement instanceof TraceEntry) {
+                return super.getChildren(parentElement);
             }
-        }
-
-        public void cancel() {
-            fMonitor.setCanceled(true);
+            return new ITimeGraphEntry[0];
         }
     }
 
@@ -488,8 +360,14 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
      * Default constructor
      */
     public CallStackView() {
-        super(ID);
-        fDisplayWidth = Display.getDefault().getBounds().width;
+        super(ID, new CallStackPresentationProvider());
+        ((CallStackPresentationProvider) getPresentationProvider()).setCallStackView(this);
+        setTreeColumns(COLUMN_NAMES);
+        setTreeLabelProvider(new CallStackTreeLabelProvider());
+        setEntryComparator(new CallStackComparator());
+        setFilterColumns(FILTER_COLUMN_NAMES);
+        setFilterContentProvider(new CallStackFilterContentProvider());
+        setFilterLabelProvider(new CallStackTreeLabelProvider());
     }
 
     // ------------------------------------------------------------------------
@@ -499,56 +377,15 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
     @Override
     public void createPartControl(Composite parent) {
         super.createPartControl(parent);
-        fTimeGraphCombo = new TimeGraphCombo(parent, SWT.NONE);
-
-        fTimeGraphCombo.setTreeContentProvider(new TimeGraphContentProvider());
-
-        fTimeGraphCombo.setTreeLabelProvider(new TreeLabelProvider());
-
-        fTimeGraphCombo.setTreeColumns(COLUMN_TIMES);
-
-        fTimeGraphCombo.getTreeViewer().getTree().getColumn(0).setWidth(COLUMN_WIDTHS[0]);
-        fTimeGraphCombo.getTreeViewer().getTree().getColumn(1).setWidth(COLUMN_WIDTHS[1]);
-        fTimeGraphCombo.getTreeViewer().getTree().getColumn(2).setWidth(COLUMN_WIDTHS[2]);
-        fTimeGraphCombo.getTreeViewer().getTree().getColumn(3).setWidth(COLUMN_WIDTHS[3]);
-        fTimeGraphCombo.getTreeViewer().getTree().getColumn(4).setWidth(COLUMN_WIDTHS[4]);
-
-        fTimeGraphCombo.setTimeGraphContentProvider(new TimeGraphContentProvider());
-        fTimeGraphCombo.setTimeGraphProvider(new CallStackPresentationProvider(this));
-        fTimeGraphCombo.getTimeGraphViewer().setTimeFormat(TimeFormat.CALENDAR);
-
-        fTimeGraphCombo.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
-            @Override
-            public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
-                long startTime = event.getStartTime();
-                long endTime = event.getEndTime();
-                TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
-                broadcast(new TmfWindowRangeUpdatedSignal(CallStackView.this, range));
-                startZoomThread(startTime, endTime);
-            }
-        });
 
-        fTimeGraphCombo.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
+        getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
             @Override
             public void timeSelected(TimeGraphTimeEvent event) {
-                long beginTime = event.getBeginTime();
-                long endTime = event.getEndTime();
-                synchingToTime(beginTime);
-                broadcast(new TmfSelectionRangeUpdatedSignal(CallStackView.this, new TmfNanoTimestamp(beginTime), new TmfNanoTimestamp(endTime)));
-            }
-        });
-
-        fTimeGraphCombo.getTimeGraphViewer().getControl().addControlListener(new ControlAdapter() {
-            @Override
-            public void controlResized(ControlEvent e) {
-                fDisplayWidth = fTimeGraphCombo.getTimeGraphViewer().getControl().getSize().x;
-                if (fEntryList != null) {
-                    startZoomThread(fTimeGraphCombo.getTimeGraphViewer().getTime0(), fTimeGraphCombo.getTimeGraphViewer().getTime1());
-                }
+                synchingToTime(event.getBeginTime());
             }
         });
 
-        fTimeGraphCombo.getTreeViewer().addDoubleClickListener(new IDoubleClickListener() {
+        getTimeGraphCombo().getTreeViewer().addDoubleClickListener(new IDoubleClickListener() {
             @Override
             public void doubleClick(DoubleClickEvent event) {
                 Object selection = ((IStructuredSelection) event.getSelection()).getFirstElement();
@@ -560,19 +397,19 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
                         long spacingTime = (long) ((exitTime - entryTime) * SPACING_RATIO);
                         entryTime -= spacingTime;
                         exitTime += spacingTime;
-                        TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(entryTime), new TmfNanoTimestamp(exitTime));
+                        TmfTimeRange range = new TmfTimeRange(TmfTimestamp.fromNanos(entryTime), TmfTimestamp.fromNanos(exitTime));
                         broadcast(new TmfWindowRangeUpdatedSignal(CallStackView.this, range));
-                        fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(entryTime, exitTime);
+                        getTimeGraphViewer().setStartFinishTime(entryTime, exitTime);
                         startZoomThread(entryTime, exitTime);
                     }
                 }
             }
         });
 
-        fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl().addMouseListener(new MouseAdapter() {
+        getTimeGraphViewer().getTimeGraphControl().addMouseListener(new MouseAdapter() {
             @Override
             public void mouseDoubleClick(MouseEvent e) {
-                TimeGraphControl timeGraphControl = fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl();
+                TimeGraphControl timeGraphControl = getTimeGraphViewer().getTimeGraphControl();
                 ISelection selection = timeGraphControl.getSelection();
                 if (selection instanceof TimeGraphSelection) {
                     Object o = ((TimeGraphSelection) selection).getFirstElement();
@@ -583,22 +420,16 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
                         long spacingTime = (long) ((endTime - startTime) * SPACING_RATIO);
                         startTime -= spacingTime;
                         endTime += spacingTime;
-                        TmfTimeRange range = new TmfTimeRange(new TmfNanoTimestamp(startTime), new TmfNanoTimestamp(endTime));
+                        TmfTimeRange range = new TmfTimeRange(TmfTimestamp.fromNanos(startTime), TmfTimestamp.fromNanos(endTime));
                         broadcast(new TmfWindowRangeUpdatedSignal(CallStackView.this, range));
-                        fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
+                        getTimeGraphViewer().setStartFinishTime(startTime, endTime);
                         startZoomThread(startTime, endTime);
                     }
                 }
             }
         });
 
-        IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager();
-        fTimeGraphCombo.getTimeGraphViewer().getTimeGraphControl().setStatusLineManager(statusLineManager);
-
-        // View Action Handling
-        makeActions();
         contributeToActionBars();
-        createContextMenu();
         loadSortOption();
 
         IEditorPart editor = getSite().getPage().getActiveEditor();
@@ -610,69 +441,6 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
         }
     }
 
-    @Override
-    public void setFocus() {
-        fTimeGraphCombo.setFocus();
-    }
-
-    // ------------------------------------------------------------------------
-    // Signal handlers
-    // ------------------------------------------------------------------------
-    /**
-     * Handler for the trace opened signal.
-     *
-     * @param signal
-     *            The incoming signal
-     */
-    @TmfSignalHandler
-    public void traceOpened(TmfTraceOpenedSignal signal) {
-        fTrace = signal.getTrace();
-        loadTrace();
-    }
-
-    /**
-     * Handler for the trace selected signal
-     *
-     * @param signal
-     *            The incoming signal
-     */
-    @TmfSignalHandler
-    public void traceSelected(final TmfTraceSelectedSignal signal) {
-        if (signal.getTrace() == fTrace) {
-            return;
-        }
-        fTrace = signal.getTrace();
-        loadTrace();
-    }
-
-    /**
-     * Trace is closed: clear the data structures and the view
-     *
-     * @param signal
-     *            the signal received
-     */
-    @TmfSignalHandler
-    public void traceClosed(final TmfTraceClosedSignal signal) {
-        synchronized (fBuildThreadMap) {
-            for (ITmfTrace trace : TmfTraceManager.getTraceSet(signal.getTrace())) {
-                BuildThread buildThread = fBuildThreadMap.remove(trace);
-                if (buildThread != null) {
-                    buildThread.cancel();
-                }
-            }
-        }
-        synchronized (fEntryListMap) {
-            fEntryListMap.remove(signal.getTrace());
-        }
-        fSelectedThreadMap.remove(signal.getTrace());
-        if (signal.getTrace() == fTrace) {
-            fTrace = null;
-            fStartTime = SWT.DEFAULT;
-            fEndTime = SWT.DEFAULT;
-            refresh();
-        }
-    }
-
     /**
      * Handler for the selection range signal.
      *
@@ -680,127 +448,98 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
      *            The incoming signal
      * @since 1.0
      */
+    @Override
     @TmfSignalHandler
     public void selectionRangeUpdated(final TmfSelectionRangeUpdatedSignal signal) {
 
         fSavedTimeSyncSignal = isPinned() ? new TmfSelectionRangeUpdatedSignal(signal.getSource(), signal.getBeginTime(), signal.getEndTime()) : null;
 
-        if (signal.getSource() == this || fTrace == null || isPinned()) {
+        if (signal.getSource() == this || getTrace() == null || isPinned()) {
             return;
         }
-        final long beginTime = signal.getBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
-        final long endTime = signal.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+        final long beginTime = signal.getBeginTime().toNanos();
+        final long endTime = signal.getEndTime().toNanos();
         Display.getDefault().asyncExec(new Runnable() {
             @Override
             public void run() {
-                if (fTimeGraphCombo.isDisposed()) {
+                if (getTimeGraphCombo().isDisposed()) {
                     return;
                 }
                 if (beginTime == endTime) {
-                    fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(beginTime, true);
+                    getTimeGraphViewer().setSelectedTime(beginTime, true);
                 } else {
-                    fTimeGraphCombo.getTimeGraphViewer().setSelectionRange(beginTime, endTime);
+                    getTimeGraphViewer().setSelectionRange(beginTime, endTime, true);
                 }
+                fSyncSelection = true;
                 synchingToTime(beginTime);
-                startZoomThread(fTimeGraphCombo.getTimeGraphViewer().getTime0(), fTimeGraphCombo.getTimeGraphViewer().getTime1());
-                if (fEntryList == null) {
-                    return;
-                }
-                TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
-                for (TraceEntry traceEntry : fEntryList) {
-                    for (ITimeGraphEntry child : traceEntry.getChildren()) {
-                        ThreadEntry threadEntry = (ThreadEntry) child;
-                        ITmfStateSystem ss = threadEntry.getStateSystem();
-                        if (ss == null || beginTime < ss.getStartTime() || beginTime > ss.getCurrentEndTime()) {
-                            continue;
-                        }
-                        try {
-                            int quark = threadEntry.getCallStackQuark();
-                            ITmfStateInterval stackInterval = ss.querySingleState(beginTime, quark);
-                            if (beginTime == stackInterval.getStartTime()) {
-                                int stackLevel = stackInterval.getStateValue().unboxInt();
-                                ITimeGraphEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
-                                fTimeGraphCombo.setSelection(selectedEntry);
-                                viewer.getTimeGraphControl().fireSelectionChanged();
-                                break;
-                            }
-                        } catch (AttributeNotFoundException | TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
-                            Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
-                        }
-                    }
-                }
+                fSyncSelection = false;
+                startZoomThread(getTimeGraphViewer().getTime0(), getTimeGraphViewer().getTime1());
             }
         });
+
     }
 
     /**
-     * Handler for the window range signal.
-     *
-     * @param signal
-     *            The incoming signal
-     * @since 1.0
+     * @since 2.0
      */
+    @Override
     @TmfSignalHandler
     public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal) {
 
         if (isPinned()) {
-            fSavedRangeSyncSignal =
-                    new TmfWindowRangeUpdatedSignal(signal.getSource(), new TmfTimeRange(signal.getCurrentRange().getStartTime(), signal.getCurrentRange().getEndTime()));
-
+            fSavedRangeSyncSignal = new TmfWindowRangeUpdatedSignal(signal.getSource(), signal.getCurrentRange());
             fSavedTimeSyncSignal = null;
         }
 
-        if (signal.getSource() == this || fTrace == null || isPinned()) {
-            return;
-        }
-        if (signal.getCurrentRange().getIntersection(fTrace.getTimeRange()) == null) {
+        if ((signal.getSource() == this) || isPinned()) {
             return;
         }
-        final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
-        final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
-        Display.getDefault().asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                if (fTimeGraphCombo.isDisposed()) {
-                    return;
-                }
-                fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
-                startZoomThread(startTime, endTime);
-            }
-        });
+        super.windowRangeUpdated(signal);
     }
 
     // ------------------------------------------------------------------------
     // Internal
     // ------------------------------------------------------------------------
 
-    private void loadTrace() {
-        synchronized (fEntryListMap) {
-            fEntryList = fEntryListMap.get(fTrace);
-            if (fEntryList == null) {
-                fStartTime = SWT.DEFAULT;
-                fEndTime = SWT.DEFAULT;
-                refresh();
-                synchronized (fBuildThreadMap) {
-                    for (ITmfTrace trace : TmfTraceManager.getTraceSet(fTrace)) {
-                        trace = checkNotNull(trace);
-                        BuildThread buildThread = new BuildThread(trace, fTrace);
-                        fBuildThreadMap.put(trace, buildThread);
-                        buildThread.start();
-                    }
-                }
-            } else {
-                fStartTime = fTrace.getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
-                fEndTime = fTrace.getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
-                refresh();
+    @Override
+    @TmfSignalHandler
+    public void traceClosed(TmfTraceClosedSignal signal) {
+        super.traceClosed(signal);
+        synchronized(fSymbolProviders){
+            for(ITmfTrace trace : getTracesToBuild(signal.getTrace())){
+                fSymbolProviders.remove(trace);
             }
         }
     }
 
-    private void buildThreadList(final @NonNull ITmfTrace trace, final ITmfTrace parentTrace, IProgressMonitor monitor) {
+    /**
+     * @since 2.0
+     */
+    @Override
+    protected void refresh() {
+        super.refresh();
+        updateConfigureSymbolsAction();
+    }
+
+    @Override
+    protected void buildEntryList(final ITmfTrace trace, final ITmfTrace parentTrace, final IProgressMonitor monitor) {
         if (monitor.isCanceled()) {
             return;
         }
+
+        /*
+         * Load the symbol provider for the current trace, even if it does not
+         * provide a call stack analysis module. See
+         * https://bugs.eclipse.org/bugs/show_bug.cgi?id=494212
+         */
+        ISymbolProvider provider = fSymbolProviders.get(trace);
+        if (provider == null) {
+            provider = SymbolProviderManager.getInstance().getSymbolProvider(trace);
+            provider.loadConfiguration(null);
+            fSymbolProviders.put(trace, provider);
+        }
+
+        /* Continue with the call stack view specific operations */
         AbstractCallStackAnalysis module = getCallStackModule(trace);
         if (module == null) {
             addUnavailableEntry(trace, parentTrace);
@@ -813,8 +552,8 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
         }
 
         Map<ITmfTrace, TraceEntry> traceEntryMap = new HashMap<>();
+        Map<Integer, ProcessEntry> processEntryMap = new HashMap<>();
         Map<Integer, ThreadEntry> threadEntryMap = new HashMap<>();
-        String[] threadPaths = module.getThreadsPattern();
 
         long start = ss.getStartTime();
 
@@ -831,7 +570,7 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
             if (start == end && !complete) { // when complete execute one last time regardless of end time
                 continue;
             }
-            List<Integer> threadQuarks = ss.getQuarks(threadPaths);
+
             TraceEntry traceEntry = traceEntryMap.get(trace);
             if (traceEntry == null) {
                 traceEntry = new TraceEntry(trace.getName(), start, end + 1);
@@ -841,75 +580,139 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
             } else {
                 traceEntry.updateEndTime(end);
             }
-            for (int i = 0; i < threadQuarks.size(); i++) {
-                if (monitor.isCanceled()) {
-                    return;
-                }
-                int threadQuark = threadQuarks.get(i);
-                try {
-                    String[] callStackPath = module.getCallStackPath();
-                    int callStackQuark = ss.getQuarkRelative(threadQuark, callStackPath);
-                    String threadName = ss.getAttributeName(threadQuark);
-                    long threadEnd = end + 1;
-                    ITmfStateInterval endInterval = ss.querySingleState(ss.getCurrentEndTime(), callStackQuark);
-                    if (endInterval.getStateValue().isNull() && endInterval.getStartTime() != ss.getStartTime()) {
-                        threadEnd = endInterval.getStartTime();
-                    }
-                    ThreadEntry threadEntry = threadEntryMap.get(threadQuark);
-                    if (threadEntry == null) {
-                        long threadId = ss.querySingleState(ss.getCurrentEndTime(), threadQuark).getStateValue().unboxLong();
-                        long threadStart = start;
-                        ITmfStateInterval startInterval = ss.querySingleState(start, callStackQuark);
-                        if (startInterval.getStateValue().isNull()) {
-                            threadStart = Math.min(startInterval.getEndTime() + 1, end + 1);
+
+            try {
+                List<ITmfStateInterval> endStates = ss.queryFullState(ss.getCurrentEndTime());
+
+                List<Integer> processQuarks = ss.getQuarks(module.getProcessesPattern());
+                for (int processQuark : processQuarks) {
+
+                    /*
+                     * Default to trace entry, overwrite if a process entry exists.
+                     */
+                    TimeGraphEntry threadParent = traceEntry;
+                    int processId = -1;
+                    if (processQuark != ITmfStateSystem.ROOT_ATTRIBUTE) {
+                        /* Create the entry for the process */
+                        ProcessEntry processEntry = processEntryMap.get(processQuark);
+                        if (processEntry == null) {
+                            String processName = ss.getAttributeName(processQuark);
+                            ITmfStateValue processStateValue = endStates.get(processQuark).getStateValue();
+                            if (processStateValue.getType() == Type.INTEGER) {
+                                processId = processStateValue.unboxInt();
+                            } else {
+                                try {
+                                    processId = Integer.parseInt(processName);
+                                } catch (NumberFormatException e) {
+                                    /* use default processId */
+                                }
+                            }
+                            processEntry = new ProcessEntry(processName, processId, start, end);
+                            processEntryMap.put(processQuark, processEntry);
+                            traceEntry.addChild(processEntry);
+                        } else {
+                            processEntry.updateEndTime(end);
                         }
-                        threadEntry = new ThreadEntry(ss, threadName, threadId, callStackQuark, threadStart, threadEnd);
-                        threadEntryMap.put(threadQuark, threadEntry);
-                        traceEntry.addChild(threadEntry);
-                    } else {
-                        threadEntry.updateEndTime(threadEnd);
+                        /* The parent of the thread entries will be a process */
+                        threadParent = processEntry;
                     }
-                    int level = 1;
-                    for (int stackLevelQuark : ss.getSubAttributes(callStackQuark, false)) {
-                        if (level > threadEntry.getChildren().size()) {
-                            CallStackEntry callStackEntry = new CallStackEntry(threadName, stackLevelQuark, level, trace, ss);
-                            threadEntry.addChild(callStackEntry);
+
+                    /* Create the threads under the process */
+                    List<Integer> threadQuarks = ss.getQuarks(processQuark, module.getThreadsPattern());
+
+                    /*
+                     * Only query startStates if necessary (threadEntry == null)
+                     */
+                    List<ITmfStateInterval> startStates = null;
+                    for (int threadQuark : threadQuarks) {
+                        if (monitor.isCanceled()) {
+                            return;
+                        }
+
+                        String[] callStackPath = module.getCallStackPath();
+                        int callStackQuark = ss.getQuarkRelative(threadQuark, callStackPath);
+                        String threadName = ss.getAttributeName(threadQuark);
+                        long threadEnd = end + 1;
+                        ITmfStateInterval endInterval = endStates.get(callStackQuark);
+                        if (endInterval.getStateValue().isNull() && endInterval.getStartTime() != ss.getStartTime()) {
+                            threadEnd = endInterval.getStartTime();
+                        }
+                        /*
+                         * Default to process/trace entry, overwrite if a thread entry exists.
+                         */
+                        TimeGraphEntry callStackParent = threadParent;
+                        if (threadQuark != processQuark) {
+                            ThreadEntry threadEntry = threadEntryMap.get(threadQuark);
+                            if (threadEntry == null) {
+                                if (startStates == null) {
+                                    startStates = ss.queryFullState(ss.getStartTime());
+                                }
+                                long threadId = -1;
+                                ITmfStateValue threadStateValue = endStates.get(threadQuark).getStateValue();
+                                if (threadStateValue.getType() == Type.LONG || threadStateValue.getType() == Type.INTEGER) {
+                                    threadId = threadStateValue.unboxLong();
+                                } else {
+                                    try {
+                                        threadId = Long.parseLong(threadName);
+                                    } catch (NumberFormatException e) {
+                                        /* use default threadId */
+                                    }
+                                }
+                                long threadStart = start;
+                                ITmfStateInterval startInterval = startStates.get(callStackQuark);
+                                if (startInterval.getStateValue().isNull()) {
+                                    threadStart = Math.min(startInterval.getEndTime() + 1, end + 1);
+                                }
+                                threadEntry = new ThreadEntry(threadName, threadId, threadStart, threadEnd);
+                                threadEntryMap.put(threadQuark, threadEntry);
+                                threadParent.addChild(threadEntry);
+                            } else {
+                                threadEntry.updateEndTime(threadEnd);
+                            }
+                            /* The parent of the call stack entries will be a thread */
+                            callStackParent = threadEntry;
+                        }
+                        int level = 1;
+                        for (int stackLevelQuark : ss.getSubAttributes(callStackQuark, false)) {
+                            if (level > callStackParent.getChildren().size()) {
+                                CallStackEntry callStackEntry = new CallStackEntry(threadName, stackLevelQuark, level, processId, trace, ss);
+                                callStackParent.addChild(callStackEntry);
+                            }
+                            level++;
                         }
-                        level++;
                     }
-                } catch (AttributeNotFoundException e) {
-                    Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
-                } catch (StateSystemDisposedException e) {
-                    /* Ignored */
                 }
+            } catch (AttributeNotFoundException e) {
+                Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
+            } catch (StateSystemDisposedException e) {
+                /* Ignored */
             }
-            if (parentTrace == fTrace) {
-                synchronized (fEntryListMap) {
-                    fStartTime = fStartTime == SWT.DEFAULT ? start : Math.min(fStartTime, start);
-                    fEndTime = fEndTime == SWT.DEFAULT ? end + 1 : Math.max(fEndTime, end + 1);
+
+            if (parentTrace == getTrace()) {
+                synchronized (this) {
+                    setStartTime(getStartTime() == SWT.DEFAULT ? start : Math.min(getStartTime(), start));
+                    setEndTime(getEndTime() == SWT.DEFAULT ? end + 1 : Math.max(getEndTime(), end + 1));
                 }
+                synchingToTime(getTimeGraphViewer().getSelectionBegin());
                 refresh();
             }
-            for (ITimeGraphEntry threadEntry : traceEntry.getChildren()) {
-                for (ITimeGraphEntry callStackEntry : threadEntry.getChildren()) {
+
+            Consumer<TimeGraphEntry> consumer = new Consumer<TimeGraphEntry>() {
+                @Override
+                public void accept(TimeGraphEntry entry) {
                     if (monitor.isCanceled()) {
                         return;
                     }
-                    buildStatusEvents(parentTrace, (CallStackEntry) callStackEntry, monitor, start, end);
+                    if (entry instanceof CallStackEntry) {
+                        buildStatusEvents(parentTrace, (CallStackEntry) entry, monitor, ss.getStartTime(), end);
+                        return;
+                    }
+                    entry.getChildren().forEach(this);
                 }
-            }
-            start = end;
-        }
-    }
+            };
+            traceEntry.getChildren().forEach(consumer);
 
-    private void addToEntryList(ITmfTrace trace, List<TraceEntry> list) {
-        synchronized (fEntryListMap) {
-            List<TraceEntry> entryList = fEntryListMap.get(trace);
-            if (entryList == null) {
-                fEntryListMap.put(trace, new CopyOnWriteArrayList<>(list));
-            } else {
-                entryList.addAll(list);
-            }
+            start = end;
         }
     }
 
@@ -917,40 +720,45 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
         String name = Messages.CallStackView_StackInfoNotAvailable + ' ' + '(' + trace.getName() + ')';
         TraceEntry unavailableEntry = new TraceEntry(name, 0, 0);
         addToEntryList(parentTrace, Collections.singletonList(unavailableEntry));
-        if (parentTrace == fTrace) {
+        if (parentTrace == getTrace()) {
             refresh();
         }
     }
 
-    private void buildStatusEvents(ITmfTrace trace, CallStackEntry entry, IProgressMonitor monitor, long start, long end) {
+    private void buildStatusEvents(ITmfTrace trace, CallStackEntry entry, @NonNull IProgressMonitor monitor, long start, long end) {
         ITmfStateSystem ss = entry.getStateSystem();
-        long resolution = Math.max(1, (end - ss.getStartTime()) / fDisplayWidth);
+        long resolution = Math.max(1, (end - ss.getStartTime()) / getDisplayWidth());
         List<ITimeEvent> eventList = getEventList(entry, start, end + 1, resolution, monitor);
         if (eventList != null) {
-            for (ITimeEvent event : eventList) {
-                entry.addEvent(event);
-            }
+            entry.setEventList(eventList);
         }
-        if (trace == fTrace) {
+        if (trace == getTrace()) {
             redraw();
         }
     }
 
-    private static List<ITimeEvent> getEventList(CallStackEntry entry,
-            long startTime, long endTime, long resolution,
-            IProgressMonitor monitor) {
+    /**
+     * @since 1.2
+     */
+    @Override
+    protected final List<ITimeEvent> getEventList(TimeGraphEntry tgentry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
+        if (!(tgentry instanceof CallStackEntry)) {
+            return null;
+        }
+        CallStackEntry entry = (CallStackEntry) tgentry;
         ITmfStateSystem ss = entry.getStateSystem();
         long start = Math.max(startTime, ss.getStartTime());
         long end = Math.min(endTime, ss.getCurrentEndTime() + 1);
         if (end <= start) {
             return null;
         }
+        boolean isZoomThread = Thread.currentThread() instanceof ZoomThread;
         List<ITimeEvent> eventList = null;
         try {
             List<ITmfStateInterval> stackIntervals = StateSystemUtils.queryHistoryRange(ss, entry.getQuark(), start, end - 1, resolution, monitor);
             eventList = new ArrayList<>(stackIntervals.size());
             long lastEndTime = -1;
-            boolean lastIsNull = true;
+            boolean lastIsNull = false;
             for (ITmfStateInterval statusInterval : stackIntervals) {
                 if (monitor.isCanceled()) {
                     return null;
@@ -963,7 +771,7 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
                     eventList.add(new CallStackEvent(entry, time, duration, value));
                     lastIsNull = false;
                 } else {
-                    if (lastEndTime == -1) {
+                    if (lastEndTime == -1 && isZoomThread) {
                         // add null event if it intersects the start time
                         eventList.add(new NullTimeEvent(entry, time, duration));
                     } else {
@@ -971,7 +779,7 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
                             // add unknown event if between two null states
                             eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
                         }
-                        if (time + duration >= endTime) {
+                        if (time + duration >= endTime && isZoomThread) {
                             // add null event if it intersects the end time
                             eventList.add(new NullTimeEvent(entry, time, duration));
                         }
@@ -990,143 +798,116 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
         return eventList;
     }
 
-    private void synchingToTime(long time) {
-        if (fEntryList == null) {
+    /**
+     * @since 1.2
+     */
+    @Override
+    protected void synchingToTime(final long time) {
+        List<TimeGraphEntry> traceEntries = getEntryList(getTrace());
+        Map<ITmfStateSystem, List<ITmfStateInterval>> fullStateMap = new HashMap<>();
+        if (traceEntries == null) {
             return;
         }
-        for (TraceEntry traceEntry : fEntryList) {
-            for (ITimeGraphEntry threadEntry : traceEntry.getChildren()) {
-                ITmfStateSystem ss = ((ThreadEntry) threadEntry).getStateSystem();
-                if (ss == null) {
-                    continue;
-                }
-                if (ss.isCancelled()) {
-                    continue;
-                }
-                if (time < ss.getStartTime() || time > ss.getCurrentEndTime()) {
-                    continue;
-                }
-                for (ITimeGraphEntry child : threadEntry.getChildren()) {
-                    CallStackEntry callStackEntry = (CallStackEntry) child;
+        Consumer<TimeGraphEntry> consumer = new Consumer<TimeGraphEntry>() {
+            @Override
+            public void accept(TimeGraphEntry entry) {
+                if (entry instanceof CallStackEntry) {
+                    CallStackEntry callStackEntry = (CallStackEntry) entry;
+                    ITmfStateSystem ss = callStackEntry.getStateSystem();
+                    if (time < ss.getStartTime() || time > ss.getCurrentEndTime()) {
+                        return;
+                    }
+                    ITmfTrace trace = callStackEntry.getTrace();
                     try {
-                        ITmfStateInterval stackLevelInterval = ss.querySingleState(time, callStackEntry.getQuark());
+                        List<ITmfStateInterval> fullState = getFullState(ss);
+                        ITmfStateInterval stackLevelInterval = fullState.get(callStackEntry.getQuark());
                         ITmfStateValue nameValue = stackLevelInterval.getStateValue();
-                        String name = ""; //$NON-NLS-1$
-                        try {
-                            if (nameValue.getType() == Type.STRING) {
-                                String address = nameValue.unboxStr();
-                                name = getFunctionName(address);
-                            } else if (nameValue.getType() == Type.INTEGER) {
-                                name = "0x" + Integer.toHexString(nameValue.unboxInt()); //$NON-NLS-1$
-                            } else if (nameValue.getType() == Type.LONG) {
-                                name = "0x" + Long.toHexString(nameValue.unboxLong()); //$NON-NLS-1$
-                            }
-                        } catch (StateValueTypeException e) {
-                        }
+
+                        String name = getFunctionName(trace, callStackEntry.getProcessId(), time, nameValue);
                         callStackEntry.setFunctionName(name);
-                        if (name.length() > 0) {
+                        if (!name.isEmpty()) {
                             callStackEntry.setFunctionEntryTime(stackLevelInterval.getStartTime());
                             callStackEntry.setFunctionExitTime(stackLevelInterval.getEndTime() + 1);
                         }
-                    } catch (AttributeNotFoundException e) {
-                        Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
+                        if (fSyncSelection) {
+                            int callStackQuark = ss.getParentAttributeQuark(callStackEntry.getQuark());
+                            ITmfStateInterval stackInterval = fullState.get(callStackQuark);
+                            if (time == stackInterval.getStartTime()) {
+                                ITmfStateValue stackLevelState = stackInterval.getStateValue();
+                                if (stackLevelState.unboxInt() == callStackEntry.getStackLevel() || stackLevelState.isNull()) {
+                                    Display.getDefault().asyncExec(() -> {
+                                        getTimeGraphCombo().setSelection(callStackEntry);
+                                        getTimeGraphViewer().getTimeGraphControl().fireSelectionChanged();
+                                        fSyncSelection = false;
+                                    });
+                                }
+                            }
+                        }
                     } catch (StateSystemDisposedException e) {
                         /* Ignored */
                     }
+                    return;
                 }
+                entry.getChildren().forEach(this);
             }
-        }
-        fTimeGraphCombo.refresh();
-    }
 
-    private void refresh() {
-        Display.getDefault().asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                if (fTimeGraphCombo.isDisposed()) {
-                    return;
+            private List<ITmfStateInterval> getFullState(ITmfStateSystem ss) throws StateSystemDisposedException {
+                List<ITmfStateInterval> fullState = fullStateMap.get(ss);
+                if (fullState == null) {
+                    fullState = ss.queryFullState(time);
+                    fullStateMap.put(ss, fullState);
                 }
-                synchronized (fEntryListMap) {
-                    fEntryList = fEntryListMap.get(fTrace);
-                    if (fEntryList == null) {
-                        fEntryList = new ArrayList<>();
-                    }
-                    for (TraceEntry traceEntry : fEntryList) {
-                        traceEntry.sortChildren(fThreadComparator);
-                    }
-                }
-                if (fEntryList != fTimeGraphCombo.getInput()) {
-                    fTimeGraphCombo.setInput(fEntryList);
-                } else {
-                    fTimeGraphCombo.refresh();
-                }
-                fTimeGraphCombo.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime);
-
-                TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
-                long selectionBeginTime = fTrace == null ? SWT.DEFAULT : ctx.getSelectionRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
-                long selectionEndTime = fTrace == null ? SWT.DEFAULT : ctx.getSelectionRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
-                long startTime = fTrace == null ? SWT.DEFAULT : ctx.getWindowRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
-                long endTime = fTrace == null ? SWT.DEFAULT : ctx.getWindowRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
-                startTime = (fStartTime == SWT.DEFAULT ? SWT.DEFAULT : Math.max(startTime, fStartTime));
-                endTime = (fEndTime == SWT.DEFAULT ? SWT.DEFAULT : Math.min(endTime, fEndTime));
-                fTimeGraphCombo.getTimeGraphViewer().setSelectionRange(selectionBeginTime, selectionEndTime);
-                synchingToTime(selectionBeginTime);
-                fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
-                startZoomThread(startTime, endTime);
+                return fullState;
             }
-        });
+        };
+        traceEntries.forEach(consumer);
+        if (Display.getCurrent() != null) {
+            getTimeGraphCombo().refresh();
+        }
     }
 
-    private void redraw() {
-        synchronized (fSyncObj) {
-            if (fRedrawState == State.IDLE) {
-                fRedrawState = State.BUSY;
-            } else {
-                fRedrawState = State.PENDING;
-                return;
-            }
-        }
-        Display.getDefault().asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                if (fTimeGraphCombo.isDisposed()) {
-                    return;
+    String getFunctionName(ITmfTrace trace, int processId, long timestamp, ITmfStateValue nameValue) {
+        long address = Long.MAX_VALUE;
+        String name = ""; //$NON-NLS-1$
+        try {
+            if (nameValue.getType() == Type.STRING) {
+                name = nameValue.unboxStr();
+                try {
+                    address = Long.parseLong(name, 16);
+                } catch (NumberFormatException e) {
+                    // ignore
                 }
-                fTimeGraphCombo.redraw();
-                fTimeGraphCombo.update();
-                synchronized (fSyncObj) {
-                    if (fRedrawState == State.PENDING) {
-                        fRedrawState = State.IDLE;
-                        redraw();
-                    } else {
-                        fRedrawState = State.IDLE;
-                    }
+            } else if (nameValue.getType() == Type.INTEGER) {
+                name = "0x" + Integer.toUnsignedString(nameValue.unboxInt(), 16); //$NON-NLS-1$
+                address = nameValue.unboxInt();
+            } else if (nameValue.getType() == Type.LONG) {
+                name = "0x" + Long.toUnsignedString(nameValue.unboxLong(), 16); //$NON-NLS-1$
+                address = nameValue.unboxLong();
+            }
+        } catch (StateValueTypeException e) {
+        }
+        if (address != Long.MAX_VALUE) {
+            ISymbolProvider provider = fSymbolProviders.get(trace);
+            if (provider != null) {
+                String symbol = provider.getSymbolText(processId, timestamp, address);
+                if (symbol != null) {
+                    name = symbol;
                 }
             }
-        });
-    }
-
-    private void startZoomThread(long startTime, long endTime) {
-        if (fZoomThread != null) {
-            fZoomThread.cancel();
         }
-        fZoomThread = new ZoomThread(fEntryList, startTime, endTime);
-        fZoomThread.start();
+        return name;
     }
 
     private void makeActions() {
-        fPreviousItemAction = fTimeGraphCombo.getTimeGraphViewer().getPreviousItemAction();
+        fPreviousItemAction = getTimeGraphViewer().getPreviousItemAction();
         fPreviousItemAction.setText(Messages.TmfTimeGraphViewer_PreviousItemActionNameText);
         fPreviousItemAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousItemActionToolTipText);
-        fNextItemAction = fTimeGraphCombo.getTimeGraphViewer().getNextItemAction();
+        fNextItemAction = getTimeGraphViewer().getNextItemAction();
         fNextItemAction.setText(Messages.TmfTimeGraphViewer_NextItemActionNameText);
         fNextItemAction.setToolTipText(Messages.TmfTimeGraphViewer_NextItemActionToolTipText);
     }
 
     private void contributeToActionBars() {
-        IActionBars bars = getViewSite().getActionBars();
-        fillLocalToolBar(bars.getToolBarManager());
-
         // Create pin action
         contributePinActionToToolBar();
         fPinAction.addPropertyChangeListener(new IPropertyChangeListener() {
@@ -1147,33 +928,43 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
         });
     }
 
-    private void fillLocalToolBar(IToolBarManager manager) {
-        manager.add(getImportBinaryAction());
-        manager.add(getImportMappingAction());
+    /**
+     * @since 1.2
+     */
+    @Override
+    protected void fillLocalToolBar(IToolBarManager manager) {
+        makeActions();
+        manager.add(getConfigureSymbolsAction());
         manager.add(new Separator());
         manager.add(getSortByNameAction());
         manager.add(getSortByIdAction());
         manager.add(getSortByTimeAction());
         manager.add(new Separator());
-        manager.add(fTimeGraphCombo.getTimeGraphViewer().getResetScaleAction());
+        manager.add(getTimeGraphCombo().getShowFilterDialogAction());
+        manager.add(new Separator());
+        manager.add(getTimeGraphViewer().getResetScaleAction());
         manager.add(getPreviousEventAction());
         manager.add(getNextEventAction());
+        manager.add(new Separator());
+        manager.add(getTimeGraphViewer().getToggleBookmarkAction());
+        manager.add(getTimeGraphViewer().getPreviousMarkerAction());
+        manager.add(getTimeGraphViewer().getNextMarkerAction());
+        manager.add(new Separator());
         manager.add(fPreviousItemAction);
         manager.add(fNextItemAction);
-        manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomInAction());
-        manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomOutAction());
-        manager.add(new Separator());
+        manager.add(getTimeGraphViewer().getZoomInAction());
+        manager.add(getTimeGraphViewer().getZoomOutAction());
     }
 
-    private void createContextMenu() {
-        final MenuManager contextMenu = new MenuManager();
+    /**
+     * @since 2.0
+     */
+    @Override
+    protected void fillTimeGraphEntryContextMenu(IMenuManager contextMenu) {
+        contextMenu.add(new GroupMarker(IWorkbenchActionConstants.GROUP_REORGANIZE));
         contextMenu.add(getSortByNameAction());
         contextMenu.add(getSortByIdAction());
         contextMenu.add(getSortByTimeAction());
-
-        Tree tree = fTimeGraphCombo.getTreeViewer().getTree();
-        Menu menu = contextMenu.createContextMenu(tree);
-        tree.setMenu(menu);
     }
 
     /**
@@ -1186,7 +977,7 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
             fNextEventAction = new Action() {
                 @Override
                 public void run() {
-                    TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
+                    TimeGraphViewer viewer = getTimeGraphViewer();
                     ITimeGraphEntry entry = viewer.getSelection();
                     if (entry instanceof CallStackEntry) {
                         try {
@@ -1201,20 +992,20 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
                             stackInterval = ss.querySingleState(Math.min(ss.getCurrentEndTime(), newTime), quark);
                             int stackLevel = stackInterval.getStateValue().unboxInt();
                             ITimeGraphEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
-                            fTimeGraphCombo.setSelection(selectedEntry);
+                            getTimeGraphCombo().setSelection(selectedEntry);
                             viewer.getTimeGraphControl().fireSelectionChanged();
                             startZoomThread(viewer.getTime0(), viewer.getTime1());
 
-                        } catch (AttributeNotFoundException | TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
+                        } catch (TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
                             Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                         }
                     }
                 }
             };
 
-            fNextEventAction.setText(Messages.TmfTimeGraphViewer_NextEventActionNameText);
-            fNextEventAction.setToolTipText(Messages.TmfTimeGraphViewer_NextEventActionToolTipText);
-            fNextEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_EVENT));
+            fNextEventAction.setText(Messages.TmfTimeGraphViewer_NextStateChangeActionNameText);
+            fNextEventAction.setToolTipText(Messages.TmfTimeGraphViewer_NextStateChangeActionToolTipText);
+            fNextEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_NEXT_STATE_CHANGE));
         }
 
         return fNextEventAction;
@@ -1230,7 +1021,7 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
             fPrevEventAction = new Action() {
                 @Override
                 public void run() {
-                    TimeGraphViewer viewer = fTimeGraphCombo.getTimeGraphViewer();
+                    TimeGraphViewer viewer = getTimeGraphCombo().getTimeGraphViewer();
                     ITimeGraphEntry entry = viewer.getSelection();
                     if (entry instanceof CallStackEntry) {
                         try {
@@ -1246,20 +1037,20 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
                             viewer.setSelectedTimeNotify(stackInterval.getStartTime(), true);
                             int stackLevel = stackInterval.getStateValue().unboxInt();
                             ITimeGraphEntry selectedEntry = threadEntry.getChildren().get(Math.max(0, stackLevel - 1));
-                            fTimeGraphCombo.setSelection(selectedEntry);
+                            getTimeGraphCombo().setSelection(selectedEntry);
                             viewer.getTimeGraphControl().fireSelectionChanged();
                             startZoomThread(viewer.getTime0(), viewer.getTime1());
 
-                        } catch (AttributeNotFoundException | TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
+                        } catch (TimeRangeException | StateSystemDisposedException | StateValueTypeException e) {
                             Activator.getDefault().logError("Error querying state system", e); //$NON-NLS-1$
                         }
                     }
                 }
             };
 
-            fPrevEventAction.setText(Messages.TmfTimeGraphViewer_PreviousEventActionNameText);
-            fPrevEventAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousEventActionToolTipText);
-            fPrevEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREV_EVENT));
+            fPrevEventAction.setText(Messages.TmfTimeGraphViewer_PreviousStateChangeActionNameText);
+            fPrevEventAction.setToolTipText(Messages.TmfTimeGraphViewer_PreviousStateChangeActionToolTipText);
+            fPrevEventAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_PREV_STATE_CHANGE));
         }
 
         return fPrevEventAction;
@@ -1287,7 +1078,10 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
         AbstractCallStackAnalysis module = it.next();
         /* This analysis is not automatic, we need to schedule it on-demand */
         module.schedule();
-        module.waitForInitialization();
+        if (!module.waitForInitialization()) {
+            /* The initialization did not succeed */
+            return null;
+        }
         return module;
     }
 
@@ -1295,72 +1089,6 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
     // Methods related to function name mapping
     // ------------------------------------------------------------------------
 
-    /**
-     * Common code for all import file mapping actions
-     */
-    private abstract class AbstractImportFileMappingAction extends Action {
-        private final String fDialogTitle;
-
-        private AbstractImportFileMappingAction(String dialogTitle) {
-            fDialogTitle = dialogTitle;
-        }
-
-        @Override
-        public void run() {
-            FileDialog dialog = new FileDialog(getViewSite().getShell());
-            dialog.setText(fDialogTitle);
-            final String filePath = dialog.open();
-            if (filePath == null) {
-                /* No file was selected, don't change anything */
-                return;
-            }
-
-            /*
-             * Start the mapping import in a separate thread (we do not want to
-             * UI thread to do this).
-             */
-            Job job = new Job(Messages.CallStackView_ImportMappingJobName) {
-                @Override
-                public IStatus run(IProgressMonitor monitor) {
-                    fNameMapping = doMapping(new File(filePath));
-
-                    /* Refresh call stack entries and event labels */
-                    Display.getDefault().asyncExec(new Runnable() {
-                        @Override
-                        public void run() {
-                            synchingToTime(fTimeGraphCombo.getTimeGraphViewer().getSelectionBegin());
-                        }
-                    });
-                    return Status.OK_STATUS;
-                }
-            };
-            job.schedule();
-        }
-
-        abstract Map<String, String> doMapping(File file);
-    }
-
-    /**
-     * Toolbar icon to import the function address-to-name mapping file.
-     */
-    private Action getImportMappingAction() {
-        if (fImportMappingAction != null) {
-            return fImportMappingAction;
-        }
-        fImportMappingAction = new AbstractImportFileMappingAction(Messages.CallStackView_ImportMappingDialogTitle) {
-            @Override
-            Map<String, String> doMapping(File file) {
-                return FunctionNameMapper.mapFromNmTextFile(file);
-            }
-        };
-
-        fImportMappingAction.setText(Messages.CallStackView_ImportMappingButtonText);
-        fImportMappingAction.setToolTipText(Messages.CallStackView_ImportMappingButtonTooltip);
-        fImportMappingAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_MAPPING_ICON_PATH));
-
-        return fImportMappingAction;
-    }
-
     private Action getSortByNameAction() {
         if (fSortByNameAction == null) {
             fSortByNameAction = new Action(Messages.CallStackView_SortByThreadName, IAction.AS_CHECK_BOX) {
@@ -1472,80 +1200,71 @@ public class CallStackView extends TmfView implements ITmfTimeAligned {
         }
         section.put(SORT_OPTION_KEY, sortOption.name());
         loadSortOption();
-        if (fEntryList == null) {
+        List<TimeGraphEntry> entryList = getEntryList(getTrace());
+        if (entryList == null) {
             return;
         }
-        for (TraceEntry traceEntry : fEntryList) {
+        for (TimeGraphEntry traceEntry : entryList) {
             traceEntry.sortChildren(fThreadComparator);
         }
         refresh();
     }
 
-    /**
-     * Toolbar icon to import the function address-to-name mapping binary file.
-     */
-    private Action getImportBinaryAction() {
-        if (fImportBinaryFileMappingAction != null) {
-            return fImportBinaryFileMappingAction;
+    private Action getConfigureSymbolsAction() {
+        if (fConfigureSymbolsAction != null) {
+            return fConfigureSymbolsAction;
         }
 
-        fImportBinaryFileMappingAction = new AbstractImportFileMappingAction(Messages.CallStackView_ImportBinaryFileDialogTitle) {
+        fConfigureSymbolsAction = new Action(Messages.CallStackView_ConfigureSymbolProvidersText) {
             @Override
-            Map<String, String> doMapping(File file) {
-                return FunctionNameMapper.mapFromBinaryFile(file);
+            public void run() {
+                SymbolProviderConfigDialog dialog = new SymbolProviderConfigDialog(getSite().getShell(), getProviderPages());
+                if (dialog.open() == IDialogConstants.OK_ID) {
+                    refresh();
+                }
             }
         };
 
-        fImportBinaryFileMappingAction.setText(Messages.CallStackView_ImportBinaryFileButtonText);
-        fImportBinaryFileMappingAction.setToolTipText(Messages.CallStackView_ImportBinaryFileButtonTooltip);
-        fImportBinaryFileMappingAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_BINARY_ICON_PATH));
+        fConfigureSymbolsAction.setToolTipText(Messages.CallStackView_ConfigureSymbolProvidersTooltip);
+        fConfigureSymbolsAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(IMPORT_BINARY_ICON_PATH));
 
-        return fImportBinaryFileMappingAction;
-    }
+        /*
+         * The updateConfigureSymbolsAction() method (called by refresh()) will
+         * set the action to true if applicable after the symbol provider has
+         * been properly loaded.
+         */
+        fConfigureSymbolsAction.setEnabled(false);
 
-    String getFunctionName(String address) {
-        if (fNameMapping == null) {
-            /* No mapping available, just print the addresses */
-            return address;
-        }
-        String ret = fNameMapping.get(address);
-        if (ret == null) {
-            /*
-             * We didn't find this address in the mapping file, just use the
-             * address
-             */
-            return address;
-        }
-        return ret;
+        return fConfigureSymbolsAction;
     }
 
     /**
-     * @since 1.0
+     * @return an array of {@link ISymbolProviderPreferencePage} that will
+     *         configure the current traces
      */
-    @Override
-    public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
-        if (fTimeGraphCombo == null) {
-            return null;
+    private ISymbolProviderPreferencePage[] getProviderPages() {
+        List<ISymbolProviderPreferencePage> pages = new ArrayList<>();
+        ITmfTrace trace = getTrace();
+        if (trace != null) {
+            for (ITmfTrace subTrace : getTracesToBuild(trace)) {
+                ISymbolProvider provider = fSymbolProviders.get(subTrace);
+                if (provider != null) {
+                    ISymbolProviderPreferencePage page = provider.createPreferencePage();
+                    if (page != null) {
+                        pages.add(page);
+                    }
+                }
+            }
         }
-        return fTimeGraphCombo.getTimeViewAlignmentInfo();
+        return pages.toArray(new ISymbolProviderPreferencePage[pages.size()]);
     }
 
     /**
-     * @since 1.0
+     * Update the enable status of the configure symbols action
      */
-    @Override
-    public int getAvailableWidth(int requestedOffset) {
-        if (fTimeGraphCombo == null) {
-            return 0;
-        }
-        return fTimeGraphCombo.getAvailableWidth(requestedOffset);
+    private void updateConfigureSymbolsAction() {
+        ISymbolProviderPreferencePage[] providerPages = getProviderPages();
+        getConfigureSymbolsAction().setEnabled(providerPages.length > 0);
     }
 
-    /**
-     * @since 1.0
-     */
-    @Override
-    public void performAlign(int offset, int width) {
-        fTimeGraphCombo.performAlign(offset, width);
-    }
 }
This page took 0.043042 seconds and 5 git commands to generate.