gdbtrace: Move plugins to the Trace Compass namespace
[deliverable/tracecompass.git] / org.eclipse.linuxtools.lttng2.kernel.ui / src / org / eclipse / linuxtools / internal / lttng2 / kernel / ui / views / controlflow / ControlFlowView.java
index 30105c25cb40c28ac7d6e1a28e147b0a7195effa..3627e80aa9e8eff4edb536512fb2f94e6ead7813 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2012 Ericsson
+ * Copyright (c) 2012, 2014 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
@@ -8,70 +8,52 @@
  *
  * Contributors:
  *   Patrick Tasse - Initial API and implementation
+ *   Geneviève Bastien - Move code to provide base classes for time graph view
  *******************************************************************************/
 
 package org.eclipse.linuxtools.internal.lttng2.kernel.ui.views.controlflow;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.jface.action.Action;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.action.IToolBarManager;
-import org.eclipse.jface.action.Separator;
-import org.eclipse.jface.viewers.ILabelProviderListener;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.dialogs.IDialogSettings;
 import org.eclipse.linuxtools.internal.lttng2.kernel.core.Attributes;
+import org.eclipse.linuxtools.internal.lttng2.kernel.ui.Activator;
 import org.eclipse.linuxtools.internal.lttng2.kernel.ui.Messages;
-import org.eclipse.linuxtools.lttng2.kernel.core.trace.CtfKernelTrace;
-import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfTimestamp;
-import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
-import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
-import org.eclipse.linuxtools.tmf.core.exceptions.AttributeNotFoundException;
-import org.eclipse.linuxtools.tmf.core.exceptions.StateValueTypeException;
-import org.eclipse.linuxtools.tmf.core.exceptions.TimeRangeException;
-import org.eclipse.linuxtools.tmf.core.interval.ITmfStateInterval;
-import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentDisposedSignal;
-import org.eclipse.linuxtools.tmf.core.signal.TmfExperimentSelectedSignal;
-import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
-import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
-import org.eclipse.linuxtools.tmf.core.signal.TmfStateSystemBuildCompleted;
-import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
-import org.eclipse.linuxtools.tmf.core.statesystem.IStateSystemQuerier;
+import org.eclipse.linuxtools.lttng2.kernel.core.analysis.LttngKernelAnalysisModule;
+import org.eclipse.linuxtools.statesystem.core.ITmfStateSystem;
+import org.eclipse.linuxtools.statesystem.core.exceptions.AttributeNotFoundException;
+import org.eclipse.linuxtools.statesystem.core.exceptions.StateSystemDisposedException;
+import org.eclipse.linuxtools.statesystem.core.exceptions.StateValueTypeException;
+import org.eclipse.linuxtools.statesystem.core.exceptions.TimeRangeException;
+import org.eclipse.linuxtools.statesystem.core.interval.ITmfStateInterval;
+import org.eclipse.linuxtools.statesystem.core.statevalue.ITmfStateValue;
+import org.eclipse.linuxtools.tmf.core.statesystem.TmfStateSystemAnalysisModule;
 import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
-import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
-import org.eclipse.linuxtools.tmf.ui.views.TmfView;
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener;
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphCombo;
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphSelectionEvent;
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
+import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
+import org.eclipse.linuxtools.tmf.ui.views.timegraph.AbstractTimeGraphView;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ILinkEvent;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeEvent;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeGraphEntry;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.TimeLinkEvent;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.Resolution;
 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.TreeColumn;
-import org.eclipse.ui.IActionBars;
 
 /**
  * The Control Flow view main object
  *
  */
-public class ControlFlowView extends TmfView {
+public class ControlFlowView extends AbstractTimeGraphView {
 
     // ------------------------------------------------------------------------
     // Constants
@@ -82,18 +64,13 @@ public class ControlFlowView extends TmfView {
      */
     public static final String ID = "org.eclipse.linuxtools.lttng2.kernel.ui.views.controlflow"; //$NON-NLS-1$
 
-    /**
-     * Initial time range
-     */
-    private static final long INITIAL_WINDOW_OFFSET = (1L * 100  * 1000 * 1000); // .1sec
-
-    private static final String PROCESS_COLUMN    = Messages.ControlFlowView_processColumn;
-    private static final String TID_COLUMN        = Messages.ControlFlowView_tidColumn;
-    private static final String PTID_COLUMN       = Messages.ControlFlowView_ptidColumn;
+    private static final String PROCESS_COLUMN = Messages.ControlFlowView_processColumn;
+    private static final String TID_COLUMN = Messages.ControlFlowView_tidColumn;
+    private static final String PTID_COLUMN = Messages.ControlFlowView_ptidColumn;
     private static final String BIRTH_TIME_COLUMN = Messages.ControlFlowView_birthTimeColumn;
-    private static final String TRACE_COLUMN      = Messages.ControlFlowView_traceColumn;
+    private static final String TRACE_COLUMN = Messages.ControlFlowView_traceColumn;
 
-    private final String[] COLUMN_NAMES = new String[] {
+    private static final String[] COLUMN_NAMES = new String[] {
             PROCESS_COLUMN,
             TID_COLUMN,
             PTID_COLUMN,
@@ -101,142 +78,78 @@ public class ControlFlowView extends TmfView {
             TRACE_COLUMN
     };
 
-    /**
-     * Redraw state enum
-     */
-    private enum State { IDLE, BUSY, PENDING }
-
-    // ------------------------------------------------------------------------
-    // Fields
-    // ------------------------------------------------------------------------
-
-    // The timegraph combo
-    private TimeGraphCombo fTimeGraphCombo;
-
-    // The selected experiment
-    private TmfExperiment fSelectedExperiment;
-
-    // The timegraph entry list
-    private ArrayList<ControlFlowEntry> fEntryList;
-
-    // The time graph entry list synchronization object
-    final private Object fEntryListSyncObj = new Object();
-
-    // The start time
-    private long fStartTime;
-
-    // The end time
-    private long fEndTime;
-
-    // The display width
-    private final int fDisplayWidth;
-
-    // The zoom thread
-    private ZoomThread fZoomThread;
-
-    // The next resource action
-    private Action fNextResourceAction;
-
-    // The previous resource action
-    private Action fPreviousResourceAction;
-
-    // A comparator class
-    private final ControlFlowEntryComparator fControlFlowEntryComparator = new ControlFlowEntryComparator();
-
-    // The redraw state used to prevent unnecessary queuing of display runnables
-    private State fRedrawState = State.IDLE;
+    private static final String[] FILTER_COLUMN_NAMES = new String[] {
+            PROCESS_COLUMN,
+            TID_COLUMN
+    };
 
-    // The redraw synchronization object
-    final private Object fSyncObj = new Object();
+    // Timeout between updates in the build thread in ms
+    private static final long BUILD_UPDATE_TIMEOUT = 500;
 
     // ------------------------------------------------------------------------
-    // Classes
+    // Constructors
     // ------------------------------------------------------------------------
 
-    private class TreeContentProvider implements ITreeContentProvider {
-
-        @Override
-        public void dispose() {
-        }
-
-        @Override
-        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-        }
-
-        @Override
-        public Object[] getElements(Object inputElement) {
-            return (ITimeGraphEntry[]) inputElement;
-        }
-
-        @Override
-        public Object[] getChildren(Object parentElement) {
-            ITimeGraphEntry entry = (ITimeGraphEntry) parentElement;
-            return entry.getChildren();
-        }
-
-        @Override
-        public Object getParent(Object element) {
-            ITimeGraphEntry entry = (ITimeGraphEntry) element;
-            return entry.getParent();
-        }
-
-        @Override
-        public boolean hasChildren(Object element) {
-            ITimeGraphEntry entry = (ITimeGraphEntry) element;
-            return entry.hasChildren();
-        }
-
+    /**
+     * Constructor
+     */
+    public ControlFlowView() {
+        super(ID, new ControlFlowPresentationProvider());
+        setTreeColumns(COLUMN_NAMES);
+        setTreeLabelProvider(new ControlFlowTreeLabelProvider());
+        setFilterColumns(FILTER_COLUMN_NAMES);
+        setFilterLabelProvider(new ControlFlowFilterLabelProvider());
+        setEntryComparator(new ControlFlowEntryComparator());
     }
 
-    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
+    protected void fillLocalToolBar(IToolBarManager manager) {
+        super.fillLocalToolBar(manager);
+        IDialogSettings settings = Activator.getDefault().getDialogSettings();
+        IDialogSettings section = settings.getSection(getClass().getName());
+        if (section == null) {
+            section = settings.addNewSection(getClass().getName());
+        }
+
+        IAction hideArrowsAction = getTimeGraphCombo().getTimeGraphViewer().getHideArrowsAction(section);
+        manager.add(hideArrowsAction);
+
+        IAction followArrowBwdAction = getTimeGraphCombo().getTimeGraphViewer().getFollowArrowBwdAction();
+        followArrowBwdAction.setText(Messages.ControlFlowView_followCPUBwdText);
+        followArrowBwdAction.setToolTipText(Messages.ControlFlowView_followCPUBwdText);
+        manager.add(followArrowBwdAction);
+
+        IAction followArrowFwdAction = getTimeGraphCombo().getTimeGraphViewer().getFollowArrowFwdAction();
+        followArrowFwdAction.setText(Messages.ControlFlowView_followCPUFwdText);
+        followArrowFwdAction.setToolTipText(Messages.ControlFlowView_followCPUFwdText);
+        manager.add(followArrowFwdAction);
+    }
 
-        @Override
-        public void removeListener(ILabelProviderListener listener) {
-        }
+    @Override
+    protected String getNextText() {
+        return Messages.ControlFlowView_nextProcessActionNameText;
+    }
 
-        @Override
-        public Image getColumnImage(Object element, int columnIndex) {
-            return null;
-        }
+    @Override
+    protected String getNextTooltip() {
+        return Messages.ControlFlowView_nextProcessActionToolTipText;
+    }
 
-        @Override
-        public String getColumnText(Object element, int columnIndex) {
-            ControlFlowEntry entry = (ControlFlowEntry) element;
-            if (columnIndex == 0) {
-                return entry.getName();
-            } else if (columnIndex == 1) {
-                return Integer.toString(entry.getThreadId());
-            } else if (columnIndex == 2) {
-                if (entry.getParentThreadId() > 0) {
-                    return Integer.toString(entry.getParentThreadId());
-                }
-            } else if (columnIndex == 3) {
-                return Utils.formatTime(entry.getBirthTime(), TimeFormat.ABSOLUTE, Resolution.NANOSEC);
-            } else if (columnIndex == 4) {
-                return entry.getTrace().getName();
-            }
-            return ""; //$NON-NLS-1$
-        }
+    @Override
+    protected String getPrevText() {
+        return Messages.ControlFlowView_previousProcessActionNameText;
+    }
 
+    @Override
+    protected String getPrevTooltip() {
+        return Messages.ControlFlowView_previousProcessActionToolTipText;
     }
 
     private static class ControlFlowEntryComparator implements Comparator<ITimeGraphEntry> {
 
         @Override
         public int compare(ITimeGraphEntry o1, ITimeGraphEntry o2) {
+
             int result = 0;
 
             if ((o1 instanceof ControlFlowEntry) && (o2 instanceof ControlFlowEntry)) {
@@ -259,445 +172,249 @@ public class ControlFlowView extends TmfView {
         }
     }
 
-
-    private class ZoomThread extends Thread {
-        private final long fZoomStartTime;
-        private final long fZoomEndTime;
-        private final long fResolution;
-        private final IProgressMonitor fMonitor;
-
-        public ZoomThread(long startTime, long endTime) {
-            super("ControlFlowView zoom"); //$NON-NLS-1$
-            fZoomStartTime = startTime;
-            fZoomEndTime = endTime;
-            fResolution = Math.max(1, (fZoomEndTime - fZoomStartTime) / fDisplayWidth);
-            fMonitor = new NullProgressMonitor();
-        }
+    /**
+     * @author gbastien
+     *
+     */
+    protected static class ControlFlowTreeLabelProvider extends TreeLabelProvider {
 
         @Override
-        public void run() {
-            ArrayList<ControlFlowEntry> entryList = null;
-            synchronized (fEntryListSyncObj) {
-                entryList = (ArrayList<ControlFlowEntry>) fEntryList.clone();
-            }
-            if (entryList == null) {
-                return;
-            }
-            for (ControlFlowEntry entry : entryList) {
-                if (fMonitor.isCanceled()) {
-                    break;
-                }
-                zoom(entry, fMonitor);
-            }
-        }
+        public String getColumnText(Object element, int columnIndex) {
+            ControlFlowEntry entry = (ControlFlowEntry) element;
 
-        private void zoom(ControlFlowEntry entry, IProgressMonitor monitor) {
-            if (fZoomStartTime <= fStartTime && fZoomEndTime >= fEndTime) {
-                entry.setZoomedEventList(null);
-            } else {
-                List<ITimeEvent> zoomedEventList = getEventList(entry, fZoomStartTime, fZoomEndTime, fResolution, monitor);
-                if (zoomedEventList != null) {
-                    entry.setZoomedEventList(zoomedEventList);
-                }
-            }
-            redraw();
-            for (ControlFlowEntry child : entry.getChildren()) {
-                if (fMonitor.isCanceled()) {
-                    return;
+            if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_processColumn)) {
+                return entry.getName();
+            } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_tidColumn)) {
+                return Integer.toString(entry.getThreadId());
+            } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_ptidColumn)) {
+                if (entry.getParentThreadId() > 0) {
+                    return Integer.toString(entry.getParentThreadId());
                 }
-                zoom(child, monitor);
+            } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_birthTimeColumn)) {
+                return Utils.formatTime(entry.getStartTime(), TimeFormat.CALENDAR, Resolution.NANOSEC);
+            } else if (COLUMN_NAMES[columnIndex].equals(Messages.ControlFlowView_traceColumn)) {
+                return entry.getTrace().getName();
             }
+            return ""; //$NON-NLS-1$
         }
 
-        public void cancel() {
-            fMonitor.setCanceled(true);
-        }
-    }
-
-    // ------------------------------------------------------------------------
-    // Constructors
-    // ------------------------------------------------------------------------
-
-    /**
-     * Constructor
-     */
-    public ControlFlowView() {
-        super(ID);
-        fDisplayWidth = Display.getDefault().getBounds().width;
     }
 
-    // ------------------------------------------------------------------------
-    // ViewPart
-    // ------------------------------------------------------------------------
-
-    /* (non-Javadoc)
-     * @see org.eclipse.linuxtools.tmf.ui.views.TmfView#createPartControl(org.eclipse.swt.widgets.Composite)
-     */
-    @Override
-    public void createPartControl(Composite parent) {
-        fTimeGraphCombo = new TimeGraphCombo(parent, SWT.NONE);
-
-        fTimeGraphCombo.setTreeContentProvider(new TreeContentProvider());
-
-        fTimeGraphCombo.setTreeLabelProvider(new TreeLabelProvider());
-
-        fTimeGraphCombo.setTimeGraphProvider(new ControlFlowPresentationProvider());
-
-        fTimeGraphCombo.setTreeColumns(COLUMN_NAMES);
-
-        fTimeGraphCombo.getTimeGraphViewer().addRangeListener(new ITimeGraphRangeListener() {
-            @Override
-            public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
-                final long startTime = event.getStartTime();
-                final long endTime = event.getEndTime();
-                TmfTimeRange range = new TmfTimeRange(new CtfTmfTimestamp(startTime), new CtfTmfTimestamp(endTime));
-                TmfTimestamp time = new CtfTmfTimestamp(fTimeGraphCombo.getTimeGraphViewer().getSelectedTime());
-                broadcast(new TmfRangeSynchSignal(ControlFlowView.this, range, time));
-                if (fZoomThread != null) {
-                    fZoomThread.cancel();
-                }
-                startZoomThread(startTime, endTime);
-            }
-        });
-
-        fTimeGraphCombo.getTimeGraphViewer().addTimeListener(new ITimeGraphTimeListener() {
-            @Override
-            public void timeSelected(TimeGraphTimeEvent event) {
-                long time = event.getTime();
-                broadcast(new TmfTimeSynchSignal(ControlFlowView.this, new CtfTmfTimestamp(time)));
-            }
-        });
-
-        fTimeGraphCombo.addSelectionListener(new ITimeGraphSelectionListener() {
-            @Override
-            public void selectionChanged(TimeGraphSelectionEvent event) {
-                //ITimeGraphEntry selection = event.getSelection();
-            }
-        });
+    private static class ControlFlowFilterLabelProvider extends TreeLabelProvider {
 
-        fTimeGraphCombo.getTimeGraphViewer().setTimeCalendarFormat(true);
+        @Override
+        public String getColumnText(Object element, int columnIndex) {
+            ControlFlowEntry entry = (ControlFlowEntry) element;
 
-        final Thread thread = new Thread("ControlFlowView build") { //$NON-NLS-1$
-            @Override
-            public void run() {
-                if (TmfExperiment.getCurrentExperiment() != null) {
-                    selectExperiment(TmfExperiment.getCurrentExperiment());
-                }
+            if (columnIndex == 0) {
+                return entry.getName();
+            } else if (columnIndex == 1) {
+                return Integer.toString(entry.getThreadId());
             }
-        };
-        thread.start();
+            return ""; //$NON-NLS-1$
+        }
 
-        // View Action Handling
-        makeActions();
-        contributeToActionBars();
-    }
-
-    /* (non-Javadoc)
-     * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
-     */
-    @Override
-    public void setFocus() {
-        fTimeGraphCombo.setFocus();
     }
 
     // ------------------------------------------------------------------------
-    // Signal handlers
+    // Internal
     // ------------------------------------------------------------------------
 
-    /**
-     * Handler for the experiment selected signal
-     *
-     * @param signal
-     *            The signal that's received
-     */
-    @TmfSignalHandler
-    public void experimentSelected(final TmfExperimentSelectedSignal signal) {
-        if (signal.getExperiment().equals(fSelectedExperiment)) {
+    @Override
+    protected void buildEventList(final ITmfTrace trace, ITmfTrace parentTrace, IProgressMonitor monitor) {
+        if (trace == null) {
             return;
         }
-
-        final Thread thread = new Thread("ControlFlowView build") { //$NON-NLS-1$
-            @Override
-            public void run() {
-                selectExperiment(signal.getExperiment());
-            }
-        };
-        thread.start();
-    }
-
-    /**
-     * Experiment is disposed: clear the data structures and the view
-     *
-     * @param signal the signal received
-     */
-    @TmfSignalHandler
-    public void experimentDisposed(final TmfExperimentDisposedSignal signal) {
-        if (signal.getExperiment().equals(fSelectedExperiment)) {
-            fSelectedExperiment = null;
-            fStartTime = 0;
-            fEndTime = 0;
-            fZoomThread.cancel();
-            synchronized(fEntryListSyncObj) {
-                fEntryList.clear();
-            }
-            refresh(INITIAL_WINDOW_OFFSET);
-        }
-    }
-
-    /**
-     * Handler for the synch signal
-     *
-     * @param signal
-     *            The signal that's received
-     */
-    @TmfSignalHandler
-    public void synchToTime(final TmfTimeSynchSignal signal) {
-        if (signal.getSource() == this || fSelectedExperiment == null || fSelectedExperiment.getTraces() == null) {
+        ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, LttngKernelAnalysisModule.ID);
+        if (ssq == null) {
             return;
         }
-        final long time = signal.getCurrentTime().normalize(0, -9).getValue();
 
-        int thread = -1;
-        for (ITmfTrace trace : fSelectedExperiment.getTraces()) {
-            if (thread > 0) {
-                break;
+        List<ControlFlowEntry> entryList = new ArrayList<>();
+        Map<Integer, ControlFlowEntry> entryMap = new HashMap<>();
+
+        long start = ssq.getStartTime();
+        setStartTime(Math.min(getStartTime(), start));
+
+        boolean complete = false;
+        while (!complete) {
+            if (monitor.isCanceled()) {
+                return;
             }
-            if (trace instanceof CtfKernelTrace) {
-                CtfKernelTrace ctfKernelTrace = (CtfKernelTrace) trace;
-                IStateSystemQuerier ssq = ctfKernelTrace.getStateSystem();
-                if (time >= ssq.getStartTime() && time <= ssq.getCurrentEndTime()) {
-                    List<Integer> currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD);  //$NON-NLS-1$
-                    for (int currentThreadQuark : currentThreadQuarks) {
-                        try {
-                            ITmfStateInterval currentThreadInterval = ssq.querySingleState(time, currentThreadQuark);
-                            int currentThread = currentThreadInterval.getStateValue().unboxInt();
-                            if (currentThread > 0) {
-                                int statusQuark = ssq.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThread), Attributes.STATUS);
-                                ITmfStateInterval statusInterval = ssq.querySingleState(time, statusQuark);
-                                if (statusInterval.getStartTime() == time) {
-                                    thread = currentThread;
-                                    break;
-                                }
-                            }
-                        } catch (AttributeNotFoundException e) {
-                            e.printStackTrace();
-                        } catch (TimeRangeException e) {
-                            e.printStackTrace();
-                        } catch (StateValueTypeException e) {
-                            e.printStackTrace();
-                        }
-                    }
-                }
+            complete = ssq.waitUntilBuilt(BUILD_UPDATE_TIMEOUT);
+            if (ssq.isCancelled()) {
+                return;
             }
-        }
-        final int selectedThread = thread;
-
-        Display.getDefault().asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                if (fTimeGraphCombo.isDisposed()) {
+            long end = ssq.getCurrentEndTime();
+            if (start == end && !complete) { // when complete execute one last time regardless of end time
+                continue;
+            }
+            setEndTime(Math.max(getEndTime(), end + 1));
+            List<Integer> threadQuarks = ssq.getQuarks(Attributes.THREADS, "*"); //$NON-NLS-1$
+            for (int threadQuark : threadQuarks) {
+                if (monitor.isCanceled()) {
                     return;
                 }
-                fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(time, true);
-                startZoomThread(fTimeGraphCombo.getTimeGraphViewer().getTime0(), fTimeGraphCombo.getTimeGraphViewer().getTime1());
-
-                if (selectedThread > 0) {
-                    for (Object element : fTimeGraphCombo.getTimeGraphViewer().getExpandedElements()) {
-                        if (element instanceof ControlFlowEntry) {
-                            ControlFlowEntry entry = (ControlFlowEntry) element;
-                            if (entry.getThreadId() == selectedThread) {
-                                fTimeGraphCombo.setSelection(entry);
+                String threadName = ssq.getAttributeName(threadQuark);
+                int threadId = -1;
+                try {
+                    threadId = Integer.parseInt(threadName);
+                } catch (NumberFormatException e1) {
+                    continue;
+                }
+                if (threadId <= 0) { // ignore the 'unknown' (-1) and swapper (0) threads
+                    continue;
+                }
+
+                int execNameQuark;
+                List<ITmfStateInterval> execNameIntervals;
+                try {
+                    execNameQuark = ssq.getQuarkRelative(threadQuark, Attributes.EXEC_NAME);
+                    execNameIntervals = ssq.queryHistoryRange(execNameQuark, start, end);
+                } catch (AttributeNotFoundException e) {
+                    /* No information on this thread (yet?), skip it for now */
+                    continue;
+                } catch (StateSystemDisposedException e) {
+                    /* State system is closing down, no point continuing */
+                    break;
+                }
+
+                for (ITmfStateInterval execNameInterval : execNameIntervals) {
+                    if (monitor.isCanceled()) {
+                        return;
+                    }
+                    ControlFlowEntry entry = entryMap.get(threadId);
+                    if (!execNameInterval.getStateValue().isNull() &&
+                            execNameInterval.getStateValue().getType() == ITmfStateValue.Type.STRING) {
+                        String execName = execNameInterval.getStateValue().unboxStr();
+                        long startTime = execNameInterval.getStartTime();
+                        long endTime = execNameInterval.getEndTime() + 1;
+                        if (entry == null) {
+                            ITmfStateInterval ppidInterval = null;
+                            try {
+                                int ppidQuark = ssq.getQuarkRelative(threadQuark, Attributes.PPID);
+                                ppidInterval = ssq.querySingleState(startTime, ppidQuark);
+                            } catch (AttributeNotFoundException e) {
+                                /* No info, keep PPID at -1 */
+                            } catch (StateSystemDisposedException e) {
+                                /* SS is closing down, time to bail */
                                 break;
                             }
+                            int ppid = -1;
+                            if (!(ppidInterval == null) && !ppidInterval.getStateValue().isNull()) {
+                                ppid = ppidInterval.getStateValue().unboxInt();
+                            }
+                            entry = new ControlFlowEntry(threadQuark, trace, execName, threadId, ppid, startTime, endTime);
+                            entryList.add(entry);
+                            entryMap.put(threadId, entry);
+                        } else {
+                            // update the name of the entry to the latest
+                            // execName
+                            entry.setName(execName);
+                            entry.updateEndTime(endTime);
                         }
+                    } else {
+                        entryMap.remove(threadId);
                     }
                 }
             }
-        });
-    }
 
-    /**
-     * Handler for the range sync signal
-     *
-     * @param signal
-     *            The signal that's received
-     */
-    @TmfSignalHandler
-    public void synchToRange(final TmfRangeSynchSignal signal) {
-        if (signal.getSource() == this || fSelectedExperiment == null) {
-            return;
-        }
-        final long startTime = signal.getCurrentRange().getStartTime().normalize(0, -9).getValue();
-        final long endTime = signal.getCurrentRange().getEndTime().normalize(0, -9).getValue();
-        final long time = signal.getCurrentTime().normalize(0, -9).getValue();
-        Display.getDefault().asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                if (fTimeGraphCombo.isDisposed()) {
-                    return;
-                }
-                fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(startTime, endTime);
-                fTimeGraphCombo.getTimeGraphViewer().setSelectedTime(time, false);
-                startZoomThread(startTime, endTime);
-            }
-        });
-    }
+            updateTree(entryList, parentTrace);
 
-    /**
-     * Handler for the state system build completed signal
-     *
-     * @param signal
-     *            The signal that's received
-     */
-    @TmfSignalHandler
-    public void stateSystemBuildCompleted (final TmfStateSystemBuildCompleted signal) {
-        final TmfExperiment selectedExperiment = fSelectedExperiment;
-        if (selectedExperiment == null || selectedExperiment.getTraces() == null) {
-            return;
-        }
-        for (ITmfTrace trace : selectedExperiment.getTraces()) {
-            if (trace == signal.getTrace() && trace instanceof CtfKernelTrace) {
-                final Thread thread = new Thread("ControlFlowView build") { //$NON-NLS-1$
-                    @Override
-                    public void run() {
-                        // rebuild the model
-                        selectExperiment(selectedExperiment);
-                    }
-                };
-                thread.start();
+            if (parentTrace.equals(getTrace())) {
+                refresh();
             }
-        }
-    }
-
-    // ------------------------------------------------------------------------
-    // Internal
-    // ------------------------------------------------------------------------
 
-    private void selectExperiment(TmfExperiment experiment) {
-        fStartTime = Long.MAX_VALUE;
-        fEndTime = Long.MIN_VALUE;
-        fSelectedExperiment = experiment;
-        ArrayList<ControlFlowEntry> rootList = new ArrayList<ControlFlowEntry>();
-        for (ITmfTrace trace : experiment.getTraces()) {
-            if (trace instanceof CtfKernelTrace) {
-                ArrayList<ControlFlowEntry> entryList = new ArrayList<ControlFlowEntry>();
-                CtfKernelTrace ctfKernelTrace = (CtfKernelTrace) trace;
-                IStateSystemQuerier ssq = ctfKernelTrace.getStateSystem();
-                long start = ssq.getStartTime();
-                long end = ssq.getCurrentEndTime() + 1;
-                fStartTime = Math.min(fStartTime, start);
-                fEndTime = Math.max(fEndTime, end);
-                List<Integer> threadQuarks = ssq.getQuarks(Attributes.THREADS, "*"); //$NON-NLS-1$
-                for (int threadQuark : threadQuarks) {
-                    String threadName = ssq.getAttributeName(threadQuark);
-                    int threadId = -1;
-                    try {
-                        threadId = Integer.parseInt(threadName);
-                    } catch (NumberFormatException e1) {
-                        continue;
-                    }
-                    if (threadId == 0) { // ignore the swapper thread
-                        continue;
-                    }
-                    int execNameQuark = -1;
-                    try {
-                        try {
-                            execNameQuark = ssq.getQuarkRelative(threadQuark, Attributes.EXEC_NAME);
-                        } catch (AttributeNotFoundException e) {
-                            continue;
-                        }
-                        int ppidQuark = ssq.getQuarkRelative(threadQuark, Attributes.PPID);
-                        List<ITmfStateInterval> execNameIntervals = ssq.queryHistoryRange(execNameQuark, start, end - 1);
-                        long birthTime = -1;
-                        for (ITmfStateInterval execNameInterval : execNameIntervals) {
-                            if (!execNameInterval.getStateValue().isNull() && execNameInterval.getStateValue().getType() == 1) {
-                                String execName = execNameInterval.getStateValue().unboxStr();
-                                long startTime = execNameInterval.getStartTime();
-                                long endTime = execNameInterval.getEndTime() + 1;
-                                if (birthTime == -1) {
-                                    birthTime = startTime;
-                                }
-                                int ppid = -1;
-                                if (ppidQuark != -1) {
-                                    ITmfStateInterval ppidInterval = ssq.querySingleState(startTime, ppidQuark);
-                                    ppid = ppidInterval.getStateValue().unboxInt();
-                                }
-                                ControlFlowEntry entry = new ControlFlowEntry(threadQuark, ctfKernelTrace, execName, threadId, ppid, birthTime, startTime, endTime);
-                                entryList.add(entry);
-                                entry.addEvent(new TimeEvent(entry, startTime, endTime - startTime));
-                            } else {
-                                birthTime = -1;
-                            }
-                        }
-                    } catch (AttributeNotFoundException e) {
-                        e.printStackTrace();
-                    } catch (TimeRangeException e) {
-                        e.printStackTrace();
-                    } catch (StateValueTypeException e) {
-                        e.printStackTrace();
-                    }
+            for (ControlFlowEntry entry : entryList) {
+                if (monitor.isCanceled()) {
+                    return;
                 }
-                buildTree(entryList, rootList);
+                buildStatusEvents(entry.getTrace(), entry, monitor, start, end);
             }
-            Collections.sort(rootList, fControlFlowEntryComparator);
-            synchronized (fEntryListSyncObj) {
-                fEntryList = (ArrayList<ControlFlowEntry>) rootList.clone();
-            }
-            refresh(INITIAL_WINDOW_OFFSET);
-        }
-        for (ControlFlowEntry entry : rootList) {
-            buildStatusEvents(entry);
+
+            start = end;
         }
     }
 
-    private static void buildTree(ArrayList<ControlFlowEntry> entryList,
-            ArrayList<ControlFlowEntry> rootList) {
+    private void updateTree(List<ControlFlowEntry> entryList, ITmfTrace parentTrace) {
+        List<TimeGraphEntry> rootListToAdd = new ArrayList<>();
+        List<TimeGraphEntry> rootListToRemove = new ArrayList<>();
+        List<TimeGraphEntry> rootList = getEntryList(parentTrace);
+
         for (ControlFlowEntry entry : entryList) {
-            boolean root = true;
-            if (entry.getParentThreadId() > 0) {
+            boolean root = (entry.getParent() == null);
+            if (root && entry.getParentThreadId() > 0) {
                 for (ControlFlowEntry parent : entryList) {
                     if (parent.getThreadId() == entry.getParentThreadId() &&
                             entry.getStartTime() >= parent.getStartTime() &&
                             entry.getStartTime() <= parent.getEndTime()) {
                         parent.addChild(entry);
                         root = false;
+                        if (rootList != null && rootList.contains(entry)) {
+                            rootListToRemove.add(entry);
+                        }
                         break;
                     }
                 }
             }
-            if (root) {
-                rootList.add(entry);
+            if (root && (rootList == null || !rootList.contains(entry))) {
+                rootListToAdd.add(entry);
             }
         }
+
+        addToEntryList(parentTrace, rootListToAdd);
+        removeFromEntryList(parentTrace, rootListToRemove);
     }
 
-    private void buildStatusEvents(ControlFlowEntry entry) {
-        IStateSystemQuerier ssq = entry.getTrace().getStateSystem();
-        long start = ssq.getStartTime();
-        long end = ssq.getCurrentEndTime() + 1;
-        long resolution = Math.max(1, (end - start) / fDisplayWidth);
-        List<ITimeEvent> eventList = getEventList(entry, entry.getStartTime(), entry.getEndTime(), resolution, new NullProgressMonitor());
-        entry.setEventList(eventList);
-        redraw();
+    private void buildStatusEvents(ITmfTrace trace, ControlFlowEntry entry, IProgressMonitor monitor, long start, long end) {
+        if (start < entry.getEndTime() && end > entry.getStartTime()) {
+            ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), LttngKernelAnalysisModule.ID);
+            if (ssq == null) {
+                return;
+            }
+
+            long startTime = Math.max(start, entry.getStartTime());
+            long endTime = Math.min(end + 1, entry.getEndTime());
+            long resolution = Math.max(1, (end - ssq.getStartTime()) / getDisplayWidth());
+            List<ITimeEvent> eventList = getEventList(entry, startTime, endTime, resolution, monitor);
+            if (eventList == null) {
+                return;
+            }
+            for (ITimeEvent event : eventList) {
+                entry.addEvent(event);
+            }
+            if (trace.equals(getTrace())) {
+                redraw();
+            }
+        }
         for (ITimeGraphEntry child : entry.getChildren()) {
-            buildStatusEvents((ControlFlowEntry) child);
+            if (monitor.isCanceled()) {
+                return;
+            }
+            buildStatusEvents(trace, (ControlFlowEntry) child, monitor, start, end);
         }
     }
 
-    private static List<ITimeEvent> getEventList(ControlFlowEntry entry,
-            long startTime, long endTime, long resolution,
-            IProgressMonitor monitor) {
-        startTime = Math.max(startTime, entry.getStartTime());
-        endTime = Math.min(endTime, entry.getEndTime());
-        if (endTime <= startTime) {
+    @Override
+    protected @Nullable List<ITimeEvent> getEventList(TimeGraphEntry tgentry, long startTime, long endTime, long resolution, IProgressMonitor monitor) {
+        List<ITimeEvent> eventList = null;
+        if (!(tgentry instanceof ControlFlowEntry)) {
+            return eventList;
+        }
+        ControlFlowEntry entry = (ControlFlowEntry) tgentry;
+        final long realStart = Math.max(startTime, entry.getStartTime());
+        final long realEnd = Math.min(endTime, entry.getEndTime());
+        if (realEnd <= realStart) {
+            return null;
+        }
+        ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(entry.getTrace(), LttngKernelAnalysisModule.ID);
+        if (ssq == null) {
             return null;
         }
-        IStateSystemQuerier ssq = entry.getTrace().getStateSystem();
-        List<ITimeEvent> eventList = null;
         try {
             int statusQuark = ssq.getQuarkRelative(entry.getThreadQuark(), Attributes.STATUS);
-            List<ITmfStateInterval> statusIntervals = ssq.queryHistoryRange(statusQuark, startTime, endTime - 1, resolution, monitor);
-            eventList = new ArrayList<ITimeEvent>(statusIntervals.size());
+            List<ITmfStateInterval> statusIntervals = ssq.queryHistoryRange(statusQuark, realStart, realEnd - 1, resolution, monitor);
+            eventList = new ArrayList<>(statusIntervals.size());
             long lastEndTime = -1;
             for (ITmfStateInterval statusInterval : statusIntervals) {
                 if (monitor.isCanceled()) {
@@ -712,110 +429,164 @@ public class ControlFlowView extends TmfView {
                     e.printStackTrace();
                 }
                 if (lastEndTime != time && lastEndTime != -1) {
-                    eventList.add(new ControlFlowEvent(entry, lastEndTime, time - lastEndTime, 0));
+                    eventList.add(new TimeEvent(entry, lastEndTime, time - lastEndTime));
                 }
-                eventList.add(new ControlFlowEvent(entry, time, duration, status));
+                eventList.add(new TimeEvent(entry, time, duration, status));
                 lastEndTime = time + duration;
             }
-        } catch (AttributeNotFoundException e) {
-            e.printStackTrace();
-        } catch (TimeRangeException e) {
+        } catch (AttributeNotFoundException | TimeRangeException e) {
             e.printStackTrace();
+        } catch (StateSystemDisposedException e) {
+            /* Ignored */
         }
         return eventList;
     }
 
-    private void refresh(final long windowRange) {
-        Display.getDefault().asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                if (fTimeGraphCombo.isDisposed()) {
-                    return;
-                }
-                ITimeGraphEntry[] entries = null;
-                synchronized (fEntryListSyncObj) {
-                    entries = fEntryList.toArray(new ITimeGraphEntry[0]);
+    /**
+     * Returns a value corresponding to the selected entry.
+     *
+     * Used in conjunction with synchingToTime to change the selected entry. If
+     * one of these methods is overridden in child class, then both should be.
+     *
+     * @param time
+     *            The currently selected time
+     * @return a value identifying the entry
+     */
+    private int getSelectionValue(long time) {
+        int thread = -1;
+        ITmfTrace[] traces = TmfTraceManager.getTraceSet(getTrace());
+        if (traces == null) {
+            return thread;
+        }
+        for (ITmfTrace trace : traces) {
+            if (thread > 0) {
+                break;
+            }
+            if (trace == null) {
+                continue;
+            }
+            ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, LttngKernelAnalysisModule.ID);
+            if (ssq == null) {
+                continue;
+            }
+            if (time >= ssq.getStartTime() && time <= ssq.getCurrentEndTime()) {
+                List<Integer> currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
+                for (int currentThreadQuark : currentThreadQuarks) {
+                    try {
+                        ITmfStateInterval currentThreadInterval = ssq.querySingleState(time, currentThreadQuark);
+                        int currentThread = currentThreadInterval.getStateValue().unboxInt();
+                        if (currentThread > 0) {
+                            int statusQuark = ssq.getQuarkAbsolute(Attributes.THREADS, Integer.toString(currentThread), Attributes.STATUS);
+                            ITmfStateInterval statusInterval = ssq.querySingleState(time, statusQuark);
+                            if (statusInterval.getStartTime() == time) {
+                                thread = currentThread;
+                                break;
+                            }
+                        }
+                    } catch (AttributeNotFoundException | TimeRangeException | StateValueTypeException e) {
+                        e.printStackTrace();
+                    } catch (StateSystemDisposedException e) {
+                        /* Ignored */
+                    }
                 }
-                Arrays.sort(entries, fControlFlowEntryComparator);
-                fTimeGraphCombo.setInput(entries);
-                fTimeGraphCombo.getTimeGraphViewer().setTimeBounds(fStartTime, fEndTime);
-
-                long endTime = fStartTime + windowRange;
+            }
+        }
+        return thread;
+    }
 
-                if (fEndTime < endTime) {
-                    endTime = fEndTime;
-                }
-                fTimeGraphCombo.getTimeGraphViewer().setStartFinishTime(fStartTime, endTime);
-                for (TreeColumn column : fTimeGraphCombo.getTreeViewer().getTree().getColumns()) {
-                    column.pack();
+    @Override
+    protected void synchingToTime(long time) {
+        int selected = getSelectionValue(time);
+        if (selected > 0) {
+            for (Object element : getTimeGraphViewer().getExpandedElements()) {
+                if (element instanceof ControlFlowEntry) {
+                    ControlFlowEntry entry = (ControlFlowEntry) element;
+                    if (entry.getThreadId() == selected) {
+                        getTimeGraphCombo().setSelection(entry);
+                        break;
+                    }
                 }
-
-                startZoomThread(fStartTime, endTime);
             }
-        });
+        }
     }
 
-    private void redraw() {
-        synchronized (fSyncObj) {
-            if (fRedrawState == State.IDLE) {
-                fRedrawState = State.BUSY;
-            } else {
-                fRedrawState = State.PENDING;
-                return;
+    @Override
+    protected List<ILinkEvent> getLinkList(long startTime, long endTime, long resolution, IProgressMonitor monitor) {
+        List<ILinkEvent> list = new ArrayList<>();
+        ITmfTrace[] traces = TmfTraceManager.getTraceSet(getTrace());
+        List<TimeGraphEntry> entryList = getEntryList(getTrace());
+        if (traces == null || entryList == null) {
+            return list;
+        }
+        for (ITmfTrace trace : traces) {
+            if (trace == null) {
+                continue;
             }
-        }
-        Display.getDefault().asyncExec(new Runnable() {
-            @Override
-            public void run() {
-                if (fTimeGraphCombo.isDisposed()) {
-                    return;
+            ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, LttngKernelAnalysisModule.ID);
+            if (ssq == null) {
+                continue;
+            }
+            try {
+                long start = Math.max(startTime, ssq.getStartTime());
+                long end = Math.min(endTime, ssq.getCurrentEndTime());
+                if (end < start) {
+                    continue;
                 }
-                fTimeGraphCombo.redraw();
-                fTimeGraphCombo.update();
-                synchronized (fSyncObj) {
-                    if (fRedrawState == State.PENDING) {
-                        fRedrawState = State.IDLE;
-                        redraw();
-                    } else {
-                        fRedrawState = State.IDLE;
+                List<Integer> currentThreadQuarks = ssq.getQuarks(Attributes.CPUS, "*", Attributes.CURRENT_THREAD); //$NON-NLS-1$
+                for (int currentThreadQuark : currentThreadQuarks) {
+                    // adjust the query range to include the previous and following intervals
+                    long qstart = Math.max(ssq.querySingleState(start, currentThreadQuark).getStartTime() - 1, ssq.getStartTime());
+                    long qend = Math.min(ssq.querySingleState(end, currentThreadQuark).getEndTime() + 1, ssq.getCurrentEndTime());
+                    List<ITmfStateInterval> currentThreadIntervals = ssq.queryHistoryRange(currentThreadQuark, qstart, qend, resolution, monitor);
+                    int prevThread = 0;
+                    long prevEnd = 0;
+                    long lastEnd = 0;
+                    for (ITmfStateInterval currentThreadInterval : currentThreadIntervals) {
+                        if (monitor.isCanceled()) {
+                            return null;
+                        }
+                        long time = currentThreadInterval.getStartTime();
+                        if (time != lastEnd) {
+                            // don't create links where there are gaps in intervals due to the resolution
+                            prevThread = 0;
+                            prevEnd = 0;
+                        }
+                        int thread = currentThreadInterval.getStateValue().unboxInt();
+                        if (thread > 0 && prevThread > 0) {
+                            ITimeGraphEntry prevEntry = findEntry(entryList, trace, prevThread);
+                            ITimeGraphEntry nextEntry = findEntry(entryList, trace, thread);
+                            list.add(new TimeLinkEvent(prevEntry, nextEntry, prevEnd, time - prevEnd, 0));
+                        }
+                        lastEnd = currentThreadInterval.getEndTime() + 1;
+                        if (thread != 0) {
+                            prevThread = thread;
+                            prevEnd = lastEnd;
+                        }
                     }
                 }
+            } catch (TimeRangeException | AttributeNotFoundException | StateValueTypeException e) {
+                e.printStackTrace();
+            } catch (StateSystemDisposedException e) {
+                /* Ignored */
             }
-        });
-    }
-
-    private void startZoomThread(long startTime, long endTime) {
-        if (fZoomThread != null) {
-            fZoomThread.cancel();
         }
-        fZoomThread = new ZoomThread(startTime, endTime);
-        fZoomThread.start();
-    }
-
-    private void makeActions() {
-        fPreviousResourceAction = fTimeGraphCombo.getTimeGraphViewer().getPreviousItemAction();
-        fPreviousResourceAction.setText(Messages.ControlFlowView_previousProcessActionNameText);
-        fPreviousResourceAction.setToolTipText(Messages.ControlFlowView_previousProcessActionToolTipText);
-        fNextResourceAction = fTimeGraphCombo.getTimeGraphViewer().getNextItemAction();
-        fNextResourceAction.setText(Messages.ControlFlowView_nextProcessActionNameText);
-        fNextResourceAction.setToolTipText(Messages.ControlFlowView_nextProcessActionToolTipText);
-    }
-
-    private void contributeToActionBars() {
-        IActionBars bars = getViewSite().getActionBars();
-        fillLocalToolBar(bars.getToolBarManager());
+        return list;
     }
 
-    private void fillLocalToolBar(IToolBarManager manager) {
-        manager.add(fTimeGraphCombo.getTimeGraphViewer().getShowLegendAction());
-        manager.add(new Separator());
-        manager.add(fTimeGraphCombo.getTimeGraphViewer().getResetScaleAction());
-        manager.add(fTimeGraphCombo.getTimeGraphViewer().getPreviousEventAction());
-        manager.add(fTimeGraphCombo.getTimeGraphViewer().getNextEventAction());
-        manager.add(fPreviousResourceAction);
-        manager.add(fNextResourceAction);
-        manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomInAction());
-        manager.add(fTimeGraphCombo.getTimeGraphViewer().getZoomOutAction());
-        manager.add(new Separator());
+    private ControlFlowEntry findEntry(List<? extends ITimeGraphEntry> entryList, ITmfTrace trace, int threadId) {
+        for (ITimeGraphEntry entry : entryList) {
+            if (entry instanceof ControlFlowEntry) {
+                ControlFlowEntry controlFlowEntry = (ControlFlowEntry) entry;
+                if (controlFlowEntry.getThreadId() == threadId && controlFlowEntry.getTrace() == trace) {
+                    return controlFlowEntry;
+                } else if (entry.hasChildren()) {
+                    controlFlowEntry = findEntry(entry.getChildren(), trace, threadId);
+                    if (controlFlowEntry != null) {
+                        return controlFlowEntry;
+                    }
+                }
+            }
+        }
+        return null;
     }
 }
This page took 0.036947 seconds and 5 git commands to generate.