Merge branch 'master' into lttng-kepler
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / views / timechart / TimeChartView.java
index 69e2899bd18a5c11e507e8badb3ce0b6b726afd5..f0ba9e3124980b11687a498a3f2fd378b69db79f 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2010 Ericsson\r
- *\r
- * All rights reserved. This program and the accompanying materials are\r
- * made available under the terms of the Eclipse Public License v1.0 which\r
- * accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *   Patrick Tasse - Initial API and implementation\r
- *******************************************************************************/\r
-\r
-package org.eclipse.linuxtools.tmf.ui.views.timechart;\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashMap;\r
-import java.util.Iterator;\r
-import java.util.Map;\r
-\r
-import org.eclipse.core.resources.IFile;\r
-import org.eclipse.core.resources.IMarker;\r
-import org.eclipse.core.resources.IMarkerDelta;\r
-import org.eclipse.core.resources.IResourceChangeEvent;\r
-import org.eclipse.core.resources.IResourceChangeListener;\r
-import org.eclipse.core.resources.IResourceDelta;\r
-import org.eclipse.core.resources.ResourcesPlugin;\r
-import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;\r
-import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;\r
-import org.eclipse.linuxtools.tmf.core.filter.ITmfFilter;\r
-import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;\r
-import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;\r
-import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;\r
-import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal;\r
-import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;\r
-import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;\r
-import org.eclipse.linuxtools.tmf.ui.editors.ITmfTraceEditor;\r
-import org.eclipse.linuxtools.tmf.ui.signal.TmfTraceClosedSignal;\r
-import org.eclipse.linuxtools.tmf.ui.signal.TmfTraceOpenedSignal;\r
-import org.eclipse.linuxtools.tmf.ui.viewers.events.ITmfEventsFilterListener;\r
-import org.eclipse.linuxtools.tmf.ui.viewers.events.ITmfEventsFilterProvider;\r
-import org.eclipse.linuxtools.tmf.ui.views.TmfView;\r
-import org.eclipse.linuxtools.tmf.ui.views.colors.ColorSetting;\r
-import org.eclipse.linuxtools.tmf.ui.views.colors.ColorSettingsManager;\r
-import org.eclipse.linuxtools.tmf.ui.views.colors.IColorSettingsListener;\r
-import org.eclipse.linuxtools.tmf.ui.views.timechart.TimeChartEvent.RankRange;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphSelectionEvent;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphViewer;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;\r
-import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Display;\r
-import org.eclipse.ui.IEditorPart;\r
-import org.eclipse.ui.IEditorReference;\r
-\r
-/**\r
- * Generic Time Chart view, which is similar to a Gantt chart for trace analysis\r
- *\r
- * @version 1.0\r
- * @author Patrick Tasse\r
- */\r
-public class TimeChartView extends TmfView implements ITimeGraphRangeListener,\r
-        ITimeGraphSelectionListener, ITimeGraphTimeListener,\r
-        IColorSettingsListener, IResourceChangeListener,\r
-        ITmfEventsFilterListener {\r
-\r
-    /** TimeChartView's ID */\r
-    public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.timechart"; //$NON-NLS-1$\r
-\r
-    private static final int TIMESTAMP_SCALE = -9;\r
-\r
-    private final int fDisplayWidth;\r
-    private TimeGraphViewer fViewer;\r
-    private final ArrayList<TimeChartAnalysisEntry> fTimeAnalysisEntries = new ArrayList<TimeChartAnalysisEntry>();\r
-    private final Map<ITmfTrace<?>, TimeChartDecorationProvider> fDecorationProviders = new HashMap<ITmfTrace<?>, TimeChartDecorationProvider>();\r
-    private ArrayList<DecorateThread> fDecorateThreads;\r
-    private long fStartTime = 0;\r
-    private long fStopTime = Long.MAX_VALUE;\r
-    private boolean fRefreshBusy = false;\r
-    private boolean fRefreshPending = false;\r
-    private boolean fRedrawBusy = false;\r
-    private boolean fRedrawPending = false;\r
-    private final Object fSyncObj = new Object();\r
-    private ITimeGraphPresentationProvider fPresentationProvider;\r
-\r
-    /**\r
-     * Default constructor\r
-     */\r
-    public TimeChartView() {\r
-        super("Time Chart"); //$NON-NLS-1$\r
-        fDisplayWidth = Display.getDefault().getBounds().width;\r
-    }\r
-\r
-    @Override\r
-    public void createPartControl(Composite parent) {\r
-        fViewer = new TimeGraphViewer(parent, SWT.NONE);\r
-        fPresentationProvider = new TimeChartAnalysisProvider();\r
-        fViewer.setTimeGraphProvider(fPresentationProvider);\r
-        fViewer.setTimeCalendarFormat(true);\r
-        fViewer.addTimeListener(this);\r
-        fViewer.addRangeListener(this);\r
-        fViewer.addSelectionListener(this);\r
-        fViewer.setMinimumItemWidth(1);\r
-\r
-        IEditorReference[] editorReferences = getSite().getPage().getEditorReferences();\r
-        for (IEditorReference editorReference : editorReferences) {\r
-            IEditorPart editor = editorReference.getEditor(false);\r
-            if (editor instanceof ITmfTraceEditor) {\r
-                ITmfTrace<?> trace = ((ITmfTraceEditor) editor).getTrace();\r
-                if (trace != null) {\r
-                    IFile bookmarksFile = ((ITmfTraceEditor) editor).getBookmarksFile();\r
-                    TimeChartAnalysisEntry timeAnalysisEntry = new TimeChartAnalysisEntry(trace, fDisplayWidth * 2);\r
-                    fTimeAnalysisEntries.add(timeAnalysisEntry);\r
-                    fDecorationProviders.put(trace, new TimeChartDecorationProvider(bookmarksFile));\r
-                    Thread thread = new ProcessTraceThread(timeAnalysisEntry);\r
-                    thread.start();\r
-                }\r
-            }\r
-        }\r
-        fViewer.setInput(fTimeAnalysisEntries.toArray(new TimeChartAnalysisEntry[0]));\r
-\r
-        fDecorateThreads = new ArrayList<DecorateThread>();\r
-        ColorSettingsManager.addColorSettingsListener(this);\r
-        ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);\r
-    }\r
-\r
-    @Override\r
-    public void dispose() {\r
-        ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);\r
-        for (DecorateThread thread : fDecorateThreads) {\r
-            thread.cancel();\r
-        }\r
-        ColorSettingsManager.removeColorSettingsListener(this);\r
-        super.dispose();\r
-    }\r
-\r
-    @Override\r
-    public void setFocus() {\r
-        fViewer.setFocus();\r
-    }\r
-\r
-    private class ProcessTraceThread extends Thread {\r
-\r
-        private final TimeChartAnalysisEntry fTimeAnalysisEntry;\r
-\r
-        public ProcessTraceThread(TimeChartAnalysisEntry timeAnalysisEntry) {\r
-            super("ProcessTraceJob:" + timeAnalysisEntry.getName()); //$NON-NLS-1$\r
-            fTimeAnalysisEntry = timeAnalysisEntry;\r
-        }\r
-\r
-        @Override\r
-        public void run() {\r
-            updateTraceEntry(fTimeAnalysisEntry, Long.MAX_VALUE, 0, Long.MAX_VALUE);\r
-        }\r
-    }\r
-\r
-    private void updateTraceEntry(TimeChartAnalysisEntry timeAnalysisEntry, long stopRank, long startTime, long stopTime) {\r
-        ITmfTrace<?> trace = timeAnalysisEntry.getTrace();\r
-        TimeChartDecorationProvider decorationProvider = fDecorationProviders.get(trace);\r
-        if (decorationProvider == null) {\r
-            return; // the trace has been closed\r
-        }\r
-        ITmfContext context = null;\r
-        // TmfTimestamp lastTimestamp = null;\r
-        boolean done = false;\r
-        while (!done) {\r
-            synchronized (timeAnalysisEntry) {\r
-                if (timeAnalysisEntry.getLastRank() >= trace.getNbEvents()) {\r
-                    done = true;\r
-                    break;\r
-                }\r
-                if (context == null || context.getRank() != timeAnalysisEntry.getLastRank()) {\r
-                    if (context != null) {\r
-                        context.dispose();\r
-                    }\r
-                    if (timeAnalysisEntry.getLastRank() != -1) {\r
-                        context = trace.seekEvent(timeAnalysisEntry.getLastRank());\r
-                    } else {\r
-                        // context = trace.seekLocation(null);\r
-                        context = trace.seekEvent(0);\r
-                    }\r
-                }\r
-                while (true) {\r
-                    long rank = context.getRank();\r
-                    ITmfEvent event = trace.getNext(context);\r
-                    if (event == null) {\r
-                        done = true;\r
-                        break;\r
-                    }\r
-                    // if (!event.getTimestamp().equals(lastTimestamp)) {\r
-                    TimeChartEvent timeEvent = new TimeChartEvent(timeAnalysisEntry, event, rank, decorationProvider);\r
-                    if (timeEvent.getTime() >= startTime && timeEvent.getTime() <= stopTime) {\r
-                        timeAnalysisEntry.addTraceEvent(timeEvent);\r
-                    }\r
-                    // lastTimestamp = event.getTimestamp();\r
-                    // } *** commented out so that color setting priority gets\r
-                    // set even if the event has same time\r
-                    if (context.getRank() == trace.getNbEvents() || context.getRank() == stopRank) {\r
-                        done = true;\r
-                        break;\r
-                    }\r
-                    if (context.getRank() % trace.getCacheSize() == 1) {\r
-                        // break for UI refresh\r
-                        break;\r
-                    }\r
-                }\r
-                // timeAnalysisEntry.setLastRank(Math.min(trace.getNbEvents(),\r
-                // stopRank));\r
-                timeAnalysisEntry.setLastRank(context.getRank());\r
-            }\r
-            redrawViewer(true);\r
-        }\r
-        if (context != null) {\r
-            context.dispose();\r
-        }\r
-    }\r
-\r
-    private void refreshViewer() {\r
-        synchronized (fSyncObj) {\r
-            if (fRefreshBusy) {\r
-                fRefreshPending = true;\r
-                return;\r
-            }\r
-            fRefreshBusy = true;\r
-        }\r
-        // Perform the refresh on the UI thread\r
-        Display.getDefault().asyncExec(new Runnable() {\r
-            @Override\r
-            public void run() {\r
-                if (fViewer.getControl().isDisposed()) {\r
-                    return;\r
-                }\r
-                fViewer.setInput(fTimeAnalysisEntries.toArray(new TimeChartAnalysisEntry[0]));\r
-                fViewer.resetStartFinishTime();\r
-                synchronized (fSyncObj) {\r
-                    fRefreshBusy = false;\r
-                    if (fRefreshPending) {\r
-                        fRefreshPending = false;\r
-                        refreshViewer();\r
-                    }\r
-                }\r
-            }\r
-        });\r
-    }\r
-\r
-    private void redrawViewer(boolean resetTimeIntervals) {\r
-        synchronized (fSyncObj) {\r
-            if (fRedrawBusy) {\r
-                fRedrawPending = true;\r
-                return;\r
-            }\r
-            fRedrawBusy = true;\r
-        }\r
-        final boolean reset = resetTimeIntervals;\r
-        // Perform the refresh on the UI thread\r
-        Display.getDefault().asyncExec(new Runnable() {\r
-            @Override\r
-            public void run() {\r
-                if (fViewer.getControl().isDisposed()) {\r
-                    return;\r
-                }\r
-                if (reset) {\r
-                    fViewer.setTimeRange(fTimeAnalysisEntries.toArray(new TimeChartAnalysisEntry[0]));\r
-                    fViewer.setTimeBounds();\r
-                }\r
-                fViewer.getControl().redraw();\r
-                fViewer.getControl().update();\r
-                synchronized (fSyncObj) {\r
-                    fRedrawBusy = false;\r
-                    if (fRedrawPending) {\r
-                        fRedrawPending = false;\r
-                        redrawViewer(reset);\r
-                    }\r
-                }\r
-            }\r
-        });\r
-    }\r
-\r
-    private void itemize(long startTime, long stopTime) {\r
-        for (int i = 0; i < fTimeAnalysisEntries.size(); i++) {\r
-            Thread thread = new ItemizeThread(fTimeAnalysisEntries.get(i), startTime, stopTime);\r
-            thread.start();\r
-        }\r
-    }\r
-\r
-    private class ItemizeThread extends Thread {\r
-\r
-        private final TimeChartAnalysisEntry fTimeAnalysisEntry;\r
-        private final long fStartTime;\r
-        private final long fStopTime;\r
-        private final long fMaxDuration;\r
-\r
-        private ItemizeThread(TimeChartAnalysisEntry timeAnalysisEntry, long startTime, long stopTime) {\r
-            super("Itemize Thread:" + timeAnalysisEntry.getName()); //$NON-NLS-1$\r
-            fTimeAnalysisEntry = timeAnalysisEntry;\r
-            fStartTime = startTime;\r
-            fStopTime = stopTime;\r
-            fMaxDuration = 3 * (fStopTime - fStartTime) / fDisplayWidth;\r
-        }\r
-\r
-        @Override\r
-        public void run() {\r
-            itemizeTraceEntry(fTimeAnalysisEntry);\r
-        }\r
-\r
-        public void itemizeTraceEntry(TimeChartAnalysisEntry timeAnalysisEntry) {\r
-            Iterator<ITimeEvent> iterator = timeAnalysisEntry.getTimeEventsIterator();\r
-            TimeChartEvent event = null;\r
-            boolean hasNext = true;\r
-            while (hasNext) {\r
-                synchronized (timeAnalysisEntry) {\r
-                    while (hasNext = iterator.hasNext()) {\r
-                        event = (TimeChartEvent) iterator.next();\r
-                        if (event.getTime() + event.getDuration() > fStartTime && event.getTime() < fStopTime && event.getDuration() > fMaxDuration\r
-                                && event.getNbEvents() > 1) {\r
-                            break;\r
-                        }\r
-                    }\r
-                }\r
-                if (hasNext) {\r
-                    if (event.getItemizedEntry() == null) {\r
-                        itemizeEvent(event);\r
-                    } else {\r
-                        itemizeTraceEntry(event.getItemizedEntry());\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        public void itemizeEvent(TimeChartEvent event) {\r
-            synchronized (event) {\r
-                if (event.isItemizing()) {\r
-                    return;\r
-                }\r
-                event.setItemizing(true);\r
-            }\r
-            TimeChartAnalysisEntry timeAnalysisEntry = new TimeChartAnalysisEntry(fTimeAnalysisEntry.getTrace(), (int) Math.min(\r
-                    event.getNbEvents() + 1, fDisplayWidth * 2));\r
-            synchronized (event.getRankRangeList()) {\r
-                for (RankRange range : event.getRankRangeList()) {\r
-                    timeAnalysisEntry.setLastRank(range.getFirstRank());\r
-                    updateTraceEntry(timeAnalysisEntry, range.getLastRank() + 1, event.getTime(), event.getTime() + event.getDuration());\r
-                }\r
-            }\r
-            event.setItemizedEntry(timeAnalysisEntry);\r
-            redrawViewer(false);\r
-            itemizeTraceEntry(timeAnalysisEntry);\r
-            synchronized (event) {\r
-                event.setItemizing(false);\r
-            }\r
-        }\r
-    }\r
-\r
-    private void redecorate() {\r
-        synchronized (fDecorateThreads) {\r
-            for (DecorateThread thread : fDecorateThreads) {\r
-                thread.cancel();\r
-            }\r
-            fDecorateThreads.clear();\r
-            for (int i = 0; i < fTimeAnalysisEntries.size(); i++) {\r
-                DecorateThread thread = new DecorateThread(fTimeAnalysisEntries.get(i));\r
-                thread.start();\r
-                fDecorateThreads.add(thread);\r
-            }\r
-        }\r
-    }\r
-\r
-    private class DecorateThread extends Thread {\r
-        private volatile boolean interrupted = false;\r
-        private final TimeChartAnalysisEntry fTimeAnalysisEntry;\r
-        private final TimeChartDecorationProvider fDecorationProvider;\r
-        private ITmfContext fContext;\r
-        private int fCount = 0;\r
-\r
-        private DecorateThread(TimeChartAnalysisEntry timeAnalysisEntry) {\r
-            super("Decorate Thread:" + timeAnalysisEntry.getName()); //$NON-NLS-1$\r
-            fTimeAnalysisEntry = timeAnalysisEntry;\r
-            fDecorationProvider = fDecorationProviders.get(timeAnalysisEntry.getTrace());\r
-        }\r
-\r
-        @Override\r
-        public void run() {\r
-            resetTraceEntry(fTimeAnalysisEntry);\r
-            redrawViewer(false);\r
-            decorateTraceEntry(fTimeAnalysisEntry, null);\r
-            redrawViewer(false);\r
-            synchronized (fDecorateThreads) {\r
-                fDecorateThreads.remove(this);\r
-            }\r
-            if (fContext != null) {\r
-               fContext.dispose();\r
-            }\r
-        }\r
-\r
-        public void resetTraceEntry(TimeChartAnalysisEntry timeAnalysisEntry) {\r
-            Iterator<ITimeEvent> iterator = timeAnalysisEntry.getTimeEventsIterator();\r
-            TimeChartEvent event = null;\r
-            boolean hasNext = true;\r
-            while (!interrupted && hasNext) {\r
-                synchronized (timeAnalysisEntry) {\r
-                    while (hasNext = iterator.hasNext()) {\r
-                        event = (TimeChartEvent) iterator.next();\r
-                        break;\r
-                    }\r
-                }\r
-                if (hasNext) {\r
-                    // TODO possible concurrency problem here with ItemizeJob\r
-                    event.setColorSettingPriority(ColorSettingsManager.PRIORITY_NONE);\r
-                    if (event.getItemizedEntry() != null) {\r
-                        resetTraceEntry(event.getItemizedEntry());\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        public void decorateTraceEntry(TimeChartAnalysisEntry timeAnalysisEntry, TimeChartEvent parentEvent) {\r
-            // Set max duration high to ensure iterator does not consider\r
-            // itemized events\r
-            Iterator<ITimeEvent> iterator = timeAnalysisEntry.getTimeEventsIterator(0, Long.MAX_VALUE, Long.MAX_VALUE);\r
-            TimeChartEvent event = null;\r
-            int entryPriority = ColorSettingsManager.PRIORITY_NONE;\r
-            boolean entryIsBookmarked = false;\r
-            boolean entryIsVisible = false;\r
-            boolean entryIsSearchMatch = false;\r
-            boolean hasNext = true;\r
-            while (!interrupted && hasNext) {\r
-                synchronized (timeAnalysisEntry) {\r
-                    while (hasNext = iterator.hasNext()) {\r
-                        event = (TimeChartEvent) iterator.next();\r
-                        break;\r
-                    }\r
-                }\r
-                if (hasNext) {\r
-                    // TODO possible concurrency problem here with ItemizeJob\r
-                    if (event.getItemizedEntry() == null) {\r
-                        decorateEvent(event);\r
-                    } else {\r
-                        decorateTraceEntry(event.getItemizedEntry(), event);\r
-                    }\r
-                    entryPriority = Math.min(entryPriority, event.getColorSettingPriority());\r
-                    entryIsBookmarked |= event.isBookmarked();\r
-                    entryIsVisible |= event.isVisible();\r
-                    entryIsSearchMatch |= event.isSearchMatch();\r
-                    if (++fCount % timeAnalysisEntry.getTrace().getCacheSize() == 0) {\r
-                        redrawViewer(false);\r
-                    }\r
-                }\r
-            }\r
-            if (parentEvent != null) {\r
-                parentEvent.setColorSettingPriority(entryPriority);\r
-                parentEvent.setIsBookmarked(entryIsBookmarked);\r
-                parentEvent.setIsVisible(entryIsVisible);\r
-                parentEvent.setIsSearchMatch(entryIsSearchMatch);\r
-            }\r
-        }\r
-\r
-        public void decorateEvent(TimeChartEvent timeChartEvent) {\r
-            // TODO possible concurrency problem here with ItemizeJob\r
-            TimeChartAnalysisEntry timeAnalysisEntry = (TimeChartAnalysisEntry) timeChartEvent.getEntry();\r
-            ITmfTrace<?> trace = timeAnalysisEntry.getTrace();\r
-            int priority = ColorSettingsManager.PRIORITY_NONE;\r
-            boolean isBookmarked = false;\r
-            boolean isVisible = false;\r
-            boolean isSearchMatch = false;\r
-            synchronized (timeChartEvent.getRankRangeList()) {\r
-                for (RankRange range : timeChartEvent.getRankRangeList()) {\r
-                    if (interrupted) {\r
-                        return;\r
-                    }\r
-                    if (fContext == null || fContext.getRank() != range.getFirstRank()) {\r
-                        if (fContext != null) {\r
-                               fContext.dispose();\r
-                        }\r
-                        fContext = trace.seekEvent(range.getFirstRank());\r
-                        fContext.setRank(range.getFirstRank());\r
-                    }\r
-                    while (true) {\r
-                        if (interrupted) {\r
-                            return;\r
-                        }\r
-                        long rank = fContext.getRank();\r
-                        ITmfEvent event = trace.getNext(fContext);\r
-                        if (event == null) {\r
-                            break;\r
-                        }\r
-                        long eventTime = event.getTimestamp().normalize(0, -9).getValue();\r
-                        if (eventTime >= timeChartEvent.getTime() && eventTime <= timeChartEvent.getTime() + timeChartEvent.getDuration()) {\r
-                            priority = Math.min(priority, ColorSettingsManager.getColorSettingPriority(event));\r
-                        }\r
-                        isBookmarked |= fDecorationProvider.isBookmark(rank);\r
-                        isVisible |= fDecorationProvider.isVisible(event);\r
-                        isSearchMatch |= fDecorationProvider.isSearchMatch(event);\r
-                        if (fContext.getRank() > range.getLastRank()) {\r
-                            break;\r
-                        }\r
-                    }\r
-                }\r
-            }\r
-            timeChartEvent.setColorSettingPriority(priority);\r
-            timeChartEvent.setIsBookmarked(isBookmarked);\r
-            timeChartEvent.setIsVisible(isVisible);\r
-            timeChartEvent.setIsSearchMatch(isSearchMatch);\r
-        }\r
-\r
-        public void cancel() {\r
-            interrupted = true;\r
-        }\r
-    }\r
-\r
-    // ------------------------------------------------------------------------\r
-    // Listeners\r
-    // ------------------------------------------------------------------------\r
-\r
-    @Override\r
-    public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {\r
-        fStartTime = event.getStartTime();\r
-        fStopTime = event.getEndTime();\r
-        itemize(fStartTime, fStopTime);\r
-    }\r
-\r
-    @Override\r
-    public void selectionChanged(TimeGraphSelectionEvent event) {\r
-        ITimeGraphEntry timeAnalysisEntry = null;\r
-        if (event.getSelection() instanceof TimeChartAnalysisEntry) {\r
-            timeAnalysisEntry = event.getSelection();\r
-        } else if (event.getSelection() instanceof TimeChartEvent) {\r
-            timeAnalysisEntry = ((TimeChartEvent) event.getSelection()).getEntry();\r
-        }\r
-        if (timeAnalysisEntry instanceof TimeChartAnalysisEntry) {\r
-            broadcast(new TmfTraceSelectedSignal(this, ((TimeChartAnalysisEntry) timeAnalysisEntry).getTrace()));\r
-        }\r
-    }\r
-\r
-    @Override\r
-    public void timeSelected(TimeGraphTimeEvent event) {\r
-        broadcast(new TmfTimeSynchSignal(this, new TmfTimestamp(event.getTime(), TIMESTAMP_SCALE)));\r
-    }\r
-\r
-    @Override\r
-    public void colorSettingsChanged(ColorSetting[] colorSettings) {\r
-        // Set presentation provider again to trigger re-creation of new color settings which are stored\r
-        // in the TimeGraphControl class\r
-        fViewer.setTimeGraphProvider(fPresentationProvider);\r
-        redecorate();\r
-    }\r
-\r
-    @Override\r
-    public void resourceChanged(IResourceChangeEvent event) {\r
-        for (IMarkerDelta delta : event.findMarkerDeltas(IMarker.BOOKMARK, false)) {\r
-            for (TimeChartDecorationProvider provider : fDecorationProviders.values()) {\r
-                if (delta.getResource().equals(provider.getBookmarksFile())) {\r
-                    if (delta.getKind() == IResourceDelta.CHANGED && delta.getMarker().getAttribute(IMarker.LOCATION, -1) != -1) {\r
-                        provider.refreshBookmarks();\r
-                    } else if (delta.getKind() == IResourceDelta.REMOVED) {\r
-                        provider.refreshBookmarks();\r
-                    }\r
-                }\r
-            }\r
-        }\r
-        redecorate();\r
-    }\r
-\r
-    @Override\r
-    public void filterApplied(ITmfFilter filter, ITmfTrace<?> trace) {\r
-        TimeChartDecorationProvider decorationProvider = fDecorationProviders.get(trace);\r
-        decorationProvider.filterApplied(filter);\r
-        redecorate();\r
-    }\r
-\r
-    @Override\r
-    public void searchApplied(ITmfFilter filter, ITmfTrace<?> trace) {\r
-        TimeChartDecorationProvider decorationProvider = fDecorationProviders.get(trace);\r
-        decorationProvider.searchApplied(filter);\r
-        redecorate();\r
-    }\r
-\r
-    // ------------------------------------------------------------------------\r
-    // Signal handlers\r
-    // ------------------------------------------------------------------------\r
-\r
-    /**\r
-     * Handler for the Trace Opened signal\r
-     *\r
-     * @param signal\r
-     *            The incoming signal\r
-     */\r
-    @TmfSignalHandler\r
-    public void traceOpened(TmfTraceOpenedSignal signal) {\r
-        if (fTimeAnalysisEntries == null) {\r
-            return;\r
-        }\r
-        final ITmfTrace<?> trace = signal.getTrace();\r
-        final IFile bookmarksFile = signal.getBookmarksFile();\r
-        final ITmfEventsFilterProvider eventsFilterProvider = signal.getEventsFilterProvider();\r
-        TimeChartAnalysisEntry timeAnalysisEntry = null;\r
-        for (int i = 0; i < fTimeAnalysisEntries.size(); i++) {\r
-            if (fTimeAnalysisEntries.get(i).getTrace().equals(trace)) {\r
-                timeAnalysisEntry = fTimeAnalysisEntries.get(i);\r
-                break;\r
-            }\r
-        }\r
-        if (timeAnalysisEntry == null) {\r
-            timeAnalysisEntry = new TimeChartAnalysisEntry(trace, fDisplayWidth * 2);\r
-            fTimeAnalysisEntries.add(timeAnalysisEntry);\r
-            fDecorationProviders.put(trace, new TimeChartDecorationProvider(bookmarksFile));\r
-            Thread thread = new ProcessTraceThread(timeAnalysisEntry);\r
-            thread.start();\r
-        }\r
-        refreshViewer();\r
-        if (eventsFilterProvider != null) {\r
-            eventsFilterProvider.addEventsFilterListener(this);\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Handler for the Trace Closed signal\r
-     *\r
-     * @param signal\r
-     *            The incoming signal\r
-     */\r
-    @TmfSignalHandler\r
-    public void traceClosed(TmfTraceClosedSignal signal) {\r
-        if (fTimeAnalysisEntries == null) {\r
-            return;\r
-        }\r
-        final ITmfTrace<?> trace = signal.getTrace();\r
-        for (int i = 0; i < fTimeAnalysisEntries.size(); i++) {\r
-            if (fTimeAnalysisEntries.get(i).getTrace().equals(trace)) {\r
-                fTimeAnalysisEntries.remove(i);\r
-                fDecorationProviders.remove(trace);\r
-                refreshViewer();\r
-                break;\r
-            }\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Handler for the Trace Selected signal\r
-     *\r
-     * @param signal\r
-     *            The incoming signal\r
-     */\r
-    @TmfSignalHandler\r
-    public void traceSelected(TmfTraceSelectedSignal signal) {\r
-        if (signal.getSource() != this && fTimeAnalysisEntries != null) {\r
-            ITmfTrace<?> trace = signal.getTrace();\r
-            for (int i = 0; i < fTimeAnalysisEntries.size(); i++) {\r
-                if (fTimeAnalysisEntries.get(i).getTrace().equals(trace)) {\r
-                    fViewer.setSelection(fTimeAnalysisEntries.get(i));\r
-                    break;\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Handler for the Trace Updated signal\r
-     *\r
-     * @param signal\r
-     *            The incoming signal\r
-     */\r
-    @TmfSignalHandler\r
-    public void traceUpdated(TmfTraceUpdatedSignal signal) {\r
-        if (fTimeAnalysisEntries == null) {\r
-            return;\r
-        }\r
-        final ITmfTrace<?> trace = signal.getTrace();\r
-        for (int i = 0; i < fTimeAnalysisEntries.size(); i++) {\r
-            TimeChartAnalysisEntry timeAnalysisEntry = fTimeAnalysisEntries.get(i);\r
-            if (timeAnalysisEntry.getTrace().equals(trace)) {\r
-                updateTraceEntry(timeAnalysisEntry, Long.MAX_VALUE, 0, Long.MAX_VALUE);\r
-                break;\r
-            }\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Handler for the Time Synch signal\r
-     *\r
-     * @param signal\r
-     *            The incoming signal\r
-     */\r
-    @TmfSignalHandler\r
-    public void currentTimeUpdated(TmfTimeSynchSignal signal) {\r
-        final long time = signal.getCurrentTime().normalize(0, TIMESTAMP_SCALE).getValue();\r
-        Display.getDefault().asyncExec(new Runnable() {\r
-            @Override\r
-            public void run() {\r
-                fViewer.setSelectedTime(time, true);\r
-            }\r
-        });\r
-    }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2010 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.ui.views.timechart;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IMarkerDelta;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
+import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.filter.ITmfFilter;
+import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal;
+import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;
+import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
+import org.eclipse.linuxtools.tmf.ui.editors.ITmfTraceEditor;
+import org.eclipse.linuxtools.tmf.ui.signal.TmfTraceClosedSignal;
+import org.eclipse.linuxtools.tmf.ui.signal.TmfTraceOpenedSignal;
+import org.eclipse.linuxtools.tmf.ui.viewers.events.ITmfEventsFilterListener;
+import org.eclipse.linuxtools.tmf.ui.viewers.events.ITmfEventsFilterProvider;
+import org.eclipse.linuxtools.tmf.ui.views.TmfView;
+import org.eclipse.linuxtools.tmf.ui.views.colors.ColorSetting;
+import org.eclipse.linuxtools.tmf.ui.views.colors.ColorSettingsManager;
+import org.eclipse.linuxtools.tmf.ui.views.colors.IColorSettingsListener;
+import org.eclipse.linuxtools.tmf.ui.views.timechart.TimeChartEvent.RankRange;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.ITimeGraphPresentationProvider;
+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.TimeGraphRangeUpdateEvent;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphSelectionEvent;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.TimeGraphViewer;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeEvent;
+import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorReference;
+
+/**
+ * Generic Time Chart view, which is similar to a Gantt chart for trace analysis
+ *
+ * @version 1.0
+ * @author Patrick Tasse
+ */
+public class TimeChartView extends TmfView implements ITimeGraphRangeListener,
+        ITimeGraphSelectionListener, ITimeGraphTimeListener,
+        IColorSettingsListener, IResourceChangeListener,
+        ITmfEventsFilterListener {
+
+    /** TimeChartView's ID */
+    public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.timechart"; //$NON-NLS-1$
+
+    private static final int TIMESTAMP_SCALE = -9;
+
+    private final int fDisplayWidth;
+    private TimeGraphViewer fViewer;
+    private final ArrayList<TimeChartAnalysisEntry> fTimeAnalysisEntries = new ArrayList<TimeChartAnalysisEntry>();
+    private final Map<ITmfTrace, TimeChartDecorationProvider> fDecorationProviders = new HashMap<ITmfTrace, TimeChartDecorationProvider>();
+    private ArrayList<DecorateThread> fDecorateThreads;
+    private long fStartTime = 0;
+    private long fStopTime = Long.MAX_VALUE;
+    private boolean fRefreshBusy = false;
+    private boolean fRefreshPending = false;
+    private boolean fRedrawBusy = false;
+    private boolean fRedrawPending = false;
+    private final Object fSyncObj = new Object();
+    private ITimeGraphPresentationProvider fPresentationProvider;
+
+    /**
+     * Default constructor
+     */
+    public TimeChartView() {
+        super("Time Chart"); //$NON-NLS-1$
+        fDisplayWidth = Display.getDefault().getBounds().width;
+    }
+
+    @Override
+    public void createPartControl(Composite parent) {
+        fViewer = new TimeGraphViewer(parent, SWT.NONE);
+        fPresentationProvider = new TimeChartAnalysisProvider();
+        fViewer.setTimeGraphProvider(fPresentationProvider);
+        fViewer.setTimeCalendarFormat(true);
+        fViewer.addTimeListener(this);
+        fViewer.addRangeListener(this);
+        fViewer.addSelectionListener(this);
+        fViewer.setMinimumItemWidth(1);
+
+        IEditorReference[] editorReferences = getSite().getPage().getEditorReferences();
+        for (IEditorReference editorReference : editorReferences) {
+            IEditorPart editor = editorReference.getEditor(false);
+            if (editor instanceof ITmfTraceEditor) {
+                ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
+                if (trace != null) {
+                    IFile bookmarksFile = ((ITmfTraceEditor) editor).getBookmarksFile();
+                    TimeChartAnalysisEntry timeAnalysisEntry = new TimeChartAnalysisEntry(trace, fDisplayWidth * 2);
+                    fTimeAnalysisEntries.add(timeAnalysisEntry);
+                    fDecorationProviders.put(trace, new TimeChartDecorationProvider(bookmarksFile));
+                    Thread thread = new ProcessTraceThread(timeAnalysisEntry);
+                    thread.start();
+                }
+            }
+        }
+        fViewer.setInput(fTimeAnalysisEntries.toArray(new TimeChartAnalysisEntry[0]));
+
+        fDecorateThreads = new ArrayList<DecorateThread>();
+        ColorSettingsManager.addColorSettingsListener(this);
+        ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
+    }
+
+    @Override
+    public void dispose() {
+        ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
+        for (DecorateThread thread : fDecorateThreads) {
+            thread.cancel();
+        }
+        ColorSettingsManager.removeColorSettingsListener(this);
+        super.dispose();
+    }
+
+    @Override
+    public void setFocus() {
+        fViewer.setFocus();
+    }
+
+    private class ProcessTraceThread extends Thread {
+
+        private final TimeChartAnalysisEntry fTimeAnalysisEntry;
+
+        public ProcessTraceThread(TimeChartAnalysisEntry timeAnalysisEntry) {
+            super("ProcessTraceJob:" + timeAnalysisEntry.getName()); //$NON-NLS-1$
+            fTimeAnalysisEntry = timeAnalysisEntry;
+        }
+
+        @Override
+        public void run() {
+            updateTraceEntry(fTimeAnalysisEntry, Long.MAX_VALUE, 0, Long.MAX_VALUE);
+        }
+    }
+
+    private void updateTraceEntry(TimeChartAnalysisEntry timeAnalysisEntry, long stopRank, long startTime, long stopTime) {
+        ITmfTrace trace = timeAnalysisEntry.getTrace();
+        TimeChartDecorationProvider decorationProvider = fDecorationProviders.get(trace);
+        if (decorationProvider == null) {
+            return; // the trace has been closed
+        }
+        ITmfContext context = null;
+        // TmfTimestamp lastTimestamp = null;
+        boolean done = false;
+        while (!done) {
+            synchronized (timeAnalysisEntry) {
+                if (timeAnalysisEntry.getLastRank() >= trace.getNbEvents()) {
+                    done = true;
+                    break;
+                }
+                if (context == null || context.getRank() != timeAnalysisEntry.getLastRank()) {
+                    if (context != null) {
+                        context.dispose();
+                    }
+                    if (timeAnalysisEntry.getLastRank() != -1) {
+                        context = trace.seekEvent(timeAnalysisEntry.getLastRank());
+                    } else {
+                        // context = trace.seekLocation(null);
+                        context = trace.seekEvent(0);
+                    }
+                }
+                while (true) {
+                    long rank = context.getRank();
+                    ITmfEvent event = trace.getNext(context);
+                    if (event == null) {
+                        done = true;
+                        break;
+                    }
+                    // if (!event.getTimestamp().equals(lastTimestamp)) {
+                    TimeChartEvent timeEvent = new TimeChartEvent(timeAnalysisEntry, event, rank, decorationProvider);
+                    if (timeEvent.getTime() >= startTime && timeEvent.getTime() <= stopTime) {
+                        timeAnalysisEntry.addTraceEvent(timeEvent);
+                    }
+                    // lastTimestamp = event.getTimestamp();
+                    // } *** commented out so that color setting priority gets
+                    // set even if the event has same time
+                    if (context.getRank() == trace.getNbEvents() || context.getRank() == stopRank) {
+                        done = true;
+                        break;
+                    }
+                    if (context.getRank() % trace.getCacheSize() == 1) {
+                        // break for UI refresh
+                        break;
+                    }
+                }
+                // timeAnalysisEntry.setLastRank(Math.min(trace.getNbEvents(),
+                // stopRank));
+                timeAnalysisEntry.setLastRank(context.getRank());
+            }
+            redrawViewer(true);
+        }
+        if (context != null) {
+            context.dispose();
+        }
+    }
+
+    private void refreshViewer() {
+        synchronized (fSyncObj) {
+            if (fRefreshBusy) {
+                fRefreshPending = true;
+                return;
+            }
+            fRefreshBusy = true;
+        }
+        // Perform the refresh on the UI thread
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                if (fViewer.getControl().isDisposed()) {
+                    return;
+                }
+                fViewer.setInput(fTimeAnalysisEntries.toArray(new TimeChartAnalysisEntry[0]));
+                fViewer.resetStartFinishTime();
+                synchronized (fSyncObj) {
+                    fRefreshBusy = false;
+                    if (fRefreshPending) {
+                        fRefreshPending = false;
+                        refreshViewer();
+                    }
+                }
+            }
+        });
+    }
+
+    private void redrawViewer(boolean resetTimeIntervals) {
+        synchronized (fSyncObj) {
+            if (fRedrawBusy) {
+                fRedrawPending = true;
+                return;
+            }
+            fRedrawBusy = true;
+        }
+        final boolean reset = resetTimeIntervals;
+        // Perform the refresh on the UI thread
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                if (fViewer.getControl().isDisposed()) {
+                    return;
+                }
+                if (reset) {
+                    fViewer.setTimeRange(fTimeAnalysisEntries.toArray(new TimeChartAnalysisEntry[0]));
+                    fViewer.setTimeBounds();
+                }
+                fViewer.getControl().redraw();
+                fViewer.getControl().update();
+                synchronized (fSyncObj) {
+                    fRedrawBusy = false;
+                    if (fRedrawPending) {
+                        fRedrawPending = false;
+                        redrawViewer(reset);
+                    }
+                }
+            }
+        });
+    }
+
+    private void itemize(long startTime, long stopTime) {
+        for (int i = 0; i < fTimeAnalysisEntries.size(); i++) {
+            Thread thread = new ItemizeThread(fTimeAnalysisEntries.get(i), startTime, stopTime);
+            thread.start();
+        }
+    }
+
+    private class ItemizeThread extends Thread {
+
+        private final TimeChartAnalysisEntry fTimeAnalysisEntry;
+        private final long fStartTime;
+        private final long fStopTime;
+        private final long fMaxDuration;
+
+        private ItemizeThread(TimeChartAnalysisEntry timeAnalysisEntry, long startTime, long stopTime) {
+            super("Itemize Thread:" + timeAnalysisEntry.getName()); //$NON-NLS-1$
+            fTimeAnalysisEntry = timeAnalysisEntry;
+            fStartTime = startTime;
+            fStopTime = stopTime;
+            fMaxDuration = 3 * (fStopTime - fStartTime) / fDisplayWidth;
+        }
+
+        @Override
+        public void run() {
+            itemizeTraceEntry(fTimeAnalysisEntry);
+        }
+
+        public void itemizeTraceEntry(TimeChartAnalysisEntry timeAnalysisEntry) {
+            Iterator<ITimeEvent> iterator = timeAnalysisEntry.getTimeEventsIterator();
+            TimeChartEvent event = null;
+            boolean hasNext = true;
+            while (hasNext) {
+                synchronized (timeAnalysisEntry) {
+                    while (hasNext = iterator.hasNext()) {
+                        event = (TimeChartEvent) iterator.next();
+                        if (event.getTime() + event.getDuration() > fStartTime && event.getTime() < fStopTime && event.getDuration() > fMaxDuration
+                                && event.getNbEvents() > 1) {
+                            break;
+                        }
+                    }
+                }
+                if (hasNext) {
+                    if (event.getItemizedEntry() == null) {
+                        itemizeEvent(event);
+                    } else {
+                        itemizeTraceEntry(event.getItemizedEntry());
+                    }
+                }
+            }
+        }
+
+        public void itemizeEvent(TimeChartEvent event) {
+            synchronized (event) {
+                if (event.isItemizing()) {
+                    return;
+                }
+                event.setItemizing(true);
+            }
+            TimeChartAnalysisEntry timeAnalysisEntry = new TimeChartAnalysisEntry(fTimeAnalysisEntry.getTrace(), (int) Math.min(
+                    event.getNbEvents() + 1, fDisplayWidth * 2));
+            synchronized (event.getRankRangeList()) {
+                for (RankRange range : event.getRankRangeList()) {
+                    timeAnalysisEntry.setLastRank(range.getFirstRank());
+                    updateTraceEntry(timeAnalysisEntry, range.getLastRank() + 1, event.getTime(), event.getTime() + event.getDuration());
+                }
+            }
+            event.setItemizedEntry(timeAnalysisEntry);
+            redrawViewer(false);
+            itemizeTraceEntry(timeAnalysisEntry);
+            synchronized (event) {
+                event.setItemizing(false);
+            }
+        }
+    }
+
+    private void redecorate() {
+        synchronized (fDecorateThreads) {
+            for (DecorateThread thread : fDecorateThreads) {
+                thread.cancel();
+            }
+            fDecorateThreads.clear();
+            for (int i = 0; i < fTimeAnalysisEntries.size(); i++) {
+                DecorateThread thread = new DecorateThread(fTimeAnalysisEntries.get(i));
+                thread.start();
+                fDecorateThreads.add(thread);
+            }
+        }
+    }
+
+    private class DecorateThread extends Thread {
+        private volatile boolean interrupted = false;
+        private final TimeChartAnalysisEntry fTimeAnalysisEntry;
+        private final TimeChartDecorationProvider fDecorationProvider;
+        private ITmfContext fContext;
+        private int fCount = 0;
+
+        private DecorateThread(TimeChartAnalysisEntry timeAnalysisEntry) {
+            super("Decorate Thread:" + timeAnalysisEntry.getName()); //$NON-NLS-1$
+            fTimeAnalysisEntry = timeAnalysisEntry;
+            fDecorationProvider = fDecorationProviders.get(timeAnalysisEntry.getTrace());
+        }
+
+        @Override
+        public void run() {
+            resetTraceEntry(fTimeAnalysisEntry);
+            redrawViewer(false);
+            decorateTraceEntry(fTimeAnalysisEntry, null);
+            redrawViewer(false);
+            synchronized (fDecorateThreads) {
+                fDecorateThreads.remove(this);
+            }
+            if (fContext != null) {
+               fContext.dispose();
+            }
+        }
+
+        public void resetTraceEntry(TimeChartAnalysisEntry timeAnalysisEntry) {
+            Iterator<ITimeEvent> iterator = timeAnalysisEntry.getTimeEventsIterator();
+            TimeChartEvent event = null;
+            boolean hasNext = true;
+            while (!interrupted && hasNext) {
+                synchronized (timeAnalysisEntry) {
+                    while (hasNext = iterator.hasNext()) {
+                        event = (TimeChartEvent) iterator.next();
+                        break;
+                    }
+                }
+                if (hasNext) {
+                    // TODO possible concurrency problem here with ItemizeJob
+                    event.setColorSettingPriority(ColorSettingsManager.PRIORITY_NONE);
+                    if (event.getItemizedEntry() != null) {
+                        resetTraceEntry(event.getItemizedEntry());
+                    }
+                }
+            }
+        }
+
+        public void decorateTraceEntry(TimeChartAnalysisEntry timeAnalysisEntry, TimeChartEvent parentEvent) {
+            // Set max duration high to ensure iterator does not consider
+            // itemized events
+            Iterator<ITimeEvent> iterator = timeAnalysisEntry.getTimeEventsIterator(0, Long.MAX_VALUE, Long.MAX_VALUE);
+            TimeChartEvent event = null;
+            int entryPriority = ColorSettingsManager.PRIORITY_NONE;
+            boolean entryIsBookmarked = false;
+            boolean entryIsVisible = false;
+            boolean entryIsSearchMatch = false;
+            boolean hasNext = true;
+            while (!interrupted && hasNext) {
+                synchronized (timeAnalysisEntry) {
+                    while (hasNext = iterator.hasNext()) {
+                        event = (TimeChartEvent) iterator.next();
+                        break;
+                    }
+                }
+                if (hasNext) {
+                    // TODO possible concurrency problem here with ItemizeJob
+                    if (event.getItemizedEntry() == null) {
+                        decorateEvent(event);
+                    } else {
+                        decorateTraceEntry(event.getItemizedEntry(), event);
+                    }
+                    entryPriority = Math.min(entryPriority, event.getColorSettingPriority());
+                    entryIsBookmarked |= event.isBookmarked();
+                    entryIsVisible |= event.isVisible();
+                    entryIsSearchMatch |= event.isSearchMatch();
+                    if (++fCount % timeAnalysisEntry.getTrace().getCacheSize() == 0) {
+                        redrawViewer(false);
+                    }
+                }
+            }
+            if (parentEvent != null) {
+                parentEvent.setColorSettingPriority(entryPriority);
+                parentEvent.setIsBookmarked(entryIsBookmarked);
+                parentEvent.setIsVisible(entryIsVisible);
+                parentEvent.setIsSearchMatch(entryIsSearchMatch);
+            }
+        }
+
+        public void decorateEvent(TimeChartEvent timeChartEvent) {
+            // TODO possible concurrency problem here with ItemizeJob
+            TimeChartAnalysisEntry timeAnalysisEntry = (TimeChartAnalysisEntry) timeChartEvent.getEntry();
+            ITmfTrace trace = timeAnalysisEntry.getTrace();
+            int priority = ColorSettingsManager.PRIORITY_NONE;
+            boolean isBookmarked = false;
+            boolean isVisible = false;
+            boolean isSearchMatch = false;
+            synchronized (timeChartEvent.getRankRangeList()) {
+                for (RankRange range : timeChartEvent.getRankRangeList()) {
+                    if (interrupted) {
+                        return;
+                    }
+                    if (fContext == null || fContext.getRank() != range.getFirstRank()) {
+                        if (fContext != null) {
+                               fContext.dispose();
+                        }
+                        fContext = trace.seekEvent(range.getFirstRank());
+                        fContext.setRank(range.getFirstRank());
+                    }
+                    while (true) {
+                        if (interrupted) {
+                            return;
+                        }
+                        long rank = fContext.getRank();
+                        ITmfEvent event = trace.getNext(fContext);
+                        if (event == null) {
+                            break;
+                        }
+                        long eventTime = event.getTimestamp().normalize(0, -9).getValue();
+                        if (eventTime >= timeChartEvent.getTime() && eventTime <= timeChartEvent.getTime() + timeChartEvent.getDuration()) {
+                            priority = Math.min(priority, ColorSettingsManager.getColorSettingPriority(event));
+                        }
+                        isBookmarked |= fDecorationProvider.isBookmark(rank);
+                        isVisible |= fDecorationProvider.isVisible(event);
+                        isSearchMatch |= fDecorationProvider.isSearchMatch(event);
+                        if (fContext.getRank() > range.getLastRank()) {
+                            break;
+                        }
+                    }
+                }
+            }
+            timeChartEvent.setColorSettingPriority(priority);
+            timeChartEvent.setIsBookmarked(isBookmarked);
+            timeChartEvent.setIsVisible(isVisible);
+            timeChartEvent.setIsSearchMatch(isSearchMatch);
+        }
+
+        public void cancel() {
+            interrupted = true;
+        }
+    }
+
+    // ------------------------------------------------------------------------
+    // Listeners
+    // ------------------------------------------------------------------------
+
+    @Override
+    public void timeRangeUpdated(TimeGraphRangeUpdateEvent event) {
+        fStartTime = event.getStartTime();
+        fStopTime = event.getEndTime();
+        itemize(fStartTime, fStopTime);
+    }
+
+    @Override
+    public void selectionChanged(TimeGraphSelectionEvent event) {
+        ITimeGraphEntry timeAnalysisEntry = null;
+        if (event.getSelection() instanceof TimeChartAnalysisEntry) {
+            timeAnalysisEntry = event.getSelection();
+        } else if (event.getSelection() instanceof TimeChartEvent) {
+            timeAnalysisEntry = ((TimeChartEvent) event.getSelection()).getEntry();
+        }
+        if (timeAnalysisEntry instanceof TimeChartAnalysisEntry) {
+            broadcast(new TmfTraceSelectedSignal(this, ((TimeChartAnalysisEntry) timeAnalysisEntry).getTrace()));
+        }
+    }
+
+    @Override
+    public void timeSelected(TimeGraphTimeEvent event) {
+        broadcast(new TmfTimeSynchSignal(this, new TmfTimestamp(event.getTime(), TIMESTAMP_SCALE)));
+    }
+
+    @Override
+    public void colorSettingsChanged(ColorSetting[] colorSettings) {
+        // Set presentation provider again to trigger re-creation of new color settings which are stored
+        // in the TimeGraphControl class
+        fViewer.setTimeGraphProvider(fPresentationProvider);
+        redecorate();
+    }
+
+    @Override
+    public void resourceChanged(IResourceChangeEvent event) {
+        for (IMarkerDelta delta : event.findMarkerDeltas(IMarker.BOOKMARK, false)) {
+            for (TimeChartDecorationProvider provider : fDecorationProviders.values()) {
+                if (delta.getResource().equals(provider.getBookmarksFile())) {
+                    if (delta.getKind() == IResourceDelta.CHANGED && delta.getMarker().getAttribute(IMarker.LOCATION, -1) != -1) {
+                        provider.refreshBookmarks();
+                    } else if (delta.getKind() == IResourceDelta.REMOVED) {
+                        provider.refreshBookmarks();
+                    }
+                }
+            }
+        }
+        redecorate();
+    }
+
+    @Override
+    public void filterApplied(ITmfFilter filter, ITmfTrace trace) {
+        TimeChartDecorationProvider decorationProvider = fDecorationProviders.get(trace);
+        decorationProvider.filterApplied(filter);
+        redecorate();
+    }
+
+    @Override
+    public void searchApplied(ITmfFilter filter, ITmfTrace trace) {
+        TimeChartDecorationProvider decorationProvider = fDecorationProviders.get(trace);
+        decorationProvider.searchApplied(filter);
+        redecorate();
+    }
+
+    // ------------------------------------------------------------------------
+    // Signal handlers
+    // ------------------------------------------------------------------------
+
+    /**
+     * Handler for the Trace Opened signal
+     *
+     * @param signal
+     *            The incoming signal
+     */
+    @TmfSignalHandler
+    public void traceOpened(TmfTraceOpenedSignal signal) {
+        if (fTimeAnalysisEntries == null) {
+            return;
+        }
+        final ITmfTrace trace = signal.getTrace();
+        final IFile bookmarksFile = signal.getBookmarksFile();
+        final ITmfEventsFilterProvider eventsFilterProvider = signal.getEventsFilterProvider();
+        TimeChartAnalysisEntry timeAnalysisEntry = null;
+        for (int i = 0; i < fTimeAnalysisEntries.size(); i++) {
+            if (fTimeAnalysisEntries.get(i).getTrace().equals(trace)) {
+                timeAnalysisEntry = fTimeAnalysisEntries.get(i);
+                break;
+            }
+        }
+        if (timeAnalysisEntry == null) {
+            timeAnalysisEntry = new TimeChartAnalysisEntry(trace, fDisplayWidth * 2);
+            fTimeAnalysisEntries.add(timeAnalysisEntry);
+            fDecorationProviders.put(trace, new TimeChartDecorationProvider(bookmarksFile));
+            Thread thread = new ProcessTraceThread(timeAnalysisEntry);
+            thread.start();
+        }
+        refreshViewer();
+        if (eventsFilterProvider != null) {
+            eventsFilterProvider.addEventsFilterListener(this);
+        }
+    }
+
+    /**
+     * Handler for the Trace Closed signal
+     *
+     * @param signal
+     *            The incoming signal
+     */
+    @TmfSignalHandler
+    public void traceClosed(TmfTraceClosedSignal signal) {
+        if (fTimeAnalysisEntries == null) {
+            return;
+        }
+        final ITmfTrace trace = signal.getTrace();
+        for (int i = 0; i < fTimeAnalysisEntries.size(); i++) {
+            if (fTimeAnalysisEntries.get(i).getTrace().equals(trace)) {
+                fTimeAnalysisEntries.remove(i);
+                fDecorationProviders.remove(trace);
+                refreshViewer();
+                break;
+            }
+        }
+    }
+
+    /**
+     * Handler for the Trace Selected signal
+     *
+     * @param signal
+     *            The incoming signal
+     */
+    @TmfSignalHandler
+    public void traceSelected(TmfTraceSelectedSignal signal) {
+        if (signal.getSource() != this && fTimeAnalysisEntries != null) {
+            ITmfTrace trace = signal.getTrace();
+            for (int i = 0; i < fTimeAnalysisEntries.size(); i++) {
+                if (fTimeAnalysisEntries.get(i).getTrace().equals(trace)) {
+                    fViewer.setSelection(fTimeAnalysisEntries.get(i));
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Handler for the Trace Updated signal
+     *
+     * @param signal
+     *            The incoming signal
+     */
+    @TmfSignalHandler
+    public void traceUpdated(TmfTraceUpdatedSignal signal) {
+        if (fTimeAnalysisEntries == null) {
+            return;
+        }
+        final ITmfTrace trace = signal.getTrace();
+        for (int i = 0; i < fTimeAnalysisEntries.size(); i++) {
+            TimeChartAnalysisEntry timeAnalysisEntry = fTimeAnalysisEntries.get(i);
+            if (timeAnalysisEntry.getTrace().equals(trace)) {
+                updateTraceEntry(timeAnalysisEntry, Long.MAX_VALUE, 0, Long.MAX_VALUE);
+                break;
+            }
+        }
+    }
+
+    /**
+     * Handler for the Time Synch signal
+     *
+     * @param signal
+     *            The incoming signal
+     */
+    @TmfSignalHandler
+    public void currentTimeUpdated(TmfTimeSynchSignal signal) {
+        final long time = signal.getCurrentTime().normalize(0, TIMESTAMP_SCALE).getValue();
+        Display.getDefault().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                fViewer.setSelectedTime(time, true);
+            }
+        });
+    }
+
+}
This page took 0.07914 seconds and 5 git commands to generate.