-/*******************************************************************************\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
-public class TimeChartView extends TmfView implements ITimeGraphRangeListener, ITimeGraphSelectionListener, ITimeGraphTimeListener, IColorSettingsListener,\r
- IResourceChangeListener, ITmfEventsFilterListener {\r
-\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 final Object fSyncObj = new Object();\r
- private ITimeGraphPresentationProvider fPresentationProvider;\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.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
- refreshViewer(false);\r
- }\r
- if (context != null) {\r
- context.dispose();\r
- }\r
- }\r
-\r
- private void refreshViewer(boolean resetTimeIntervals) {\r
- synchronized (fSyncObj) {\r
- if (fRefreshBusy) {\r
- fRefreshPending = true;\r
- return;\r
- } else {\r
- fRefreshBusy = true;\r
- }\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
- fViewer.setInput(fTimeAnalysisEntries.toArray(new TimeChartAnalysisEntry[0]));\r
- if (reset) {\r
- fViewer.resetStartFinishTime();\r
- }\r
- synchronized (fSyncObj) {\r
- fRefreshBusy = false;\r
- if (fRefreshPending) {\r
- fRefreshPending = false;\r
- refreshViewer(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
- refreshViewer(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
- refreshViewer(false);\r
- decorateTraceEntry(fTimeAnalysisEntry, null);\r
- refreshViewer(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
- refreshViewer(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
- 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
- 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 = (TimeChartAnalysisEntry) 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
- @TmfSignalHandler\r
- public void traceOpened(TmfTraceOpenedSignal signal) {\r
- if (fTimeAnalysisEntries == null)\r
- return;\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(true);\r
- if (eventsFilterProvider != null) {\r
- eventsFilterProvider.addEventsFilterListener(this);\r
- }\r
- }\r
-\r
- @TmfSignalHandler\r
- public void traceClosed(TmfTraceClosedSignal signal) {\r
- if (fTimeAnalysisEntries == null)\r
- return;\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(true);\r
- break;\r
- }\r
- }\r
- }\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
- @TmfSignalHandler\r
- public void traceUpdated(TmfTraceUpdatedSignal signal) {\r
- if (fTimeAnalysisEntries == null)\r
- return;\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
- @TmfSignalHandler\r
- public void currentTimeUpdated(TmfTimeSynchSignal signal) {\r
- long time = signal.getCurrentTime().normalize(0, TIMESTAMP_SCALE).getValue();\r
- fViewer.setSelectedTime(time, true, this);\r
- }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2010, 2014 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.jface.action.IStatusLineManager;
+import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
+import org.eclipse.linuxtools.tmf.core.signal.TmfEventFilterAppliedSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfEventSearchAppliedSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTraceClosedSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTraceOpenedSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTraceSelectedSignal;
+import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal;
+import org.eclipse.linuxtools.tmf.core.timestamp.ITmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange;
+import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
+import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;
+import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
+import org.eclipse.linuxtools.tmf.core.trace.TmfTraceManager;
+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.linuxtools.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * 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 {
+
+ /** 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<>();
+ private final Map<ITmfTrace, TimeChartDecorationProvider> fDecorationProviders = new HashMap<>();
+ private final ArrayList<DecorateThread> fDecorateThreads = new ArrayList<>();
+ 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.setTimeFormat(TimeFormat.CALENDAR);
+ fViewer.addTimeListener(this);
+ fViewer.addRangeListener(this);
+ fViewer.addSelectionListener(this);
+ fViewer.setMinimumItemWidth(1);
+
+ IStatusLineManager statusLineManager = getViewSite().getActionBars().getStatusLineManager();
+ fViewer.getTimeGraphControl().setStatusLineManager(statusLineManager);
+
+ for (ITmfTrace trace : TmfTraceManager.getInstance().getOpenedTraces()) {
+ IFile bookmarksFile = TmfTraceManager.getInstance().getTraceEditorFile(trace);
+ 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]));
+
+ 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 startTime;
+ private final long stopTime;
+ private final long fMaxDuration;
+
+ private ItemizeThread(TimeChartAnalysisEntry timeAnalysisEntry, long startTime, long stopTime) {
+ super("Itemize Thread:" + timeAnalysisEntry.getName()); //$NON-NLS-1$
+ fTimeAnalysisEntry = timeAnalysisEntry;
+ this.startTime = startTime;
+ this.stopTime = stopTime;
+ fMaxDuration = 3 * (stopTime - startTime) / 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()) == true) {
+ event = (TimeChartEvent) iterator.next();
+ if (event.getTime() + event.getDuration() > startTime && event.getTime() < stopTime && event.getDuration() > fMaxDuration
+ && event.getNbEvents() > 1) {
+ break;
+ }
+ }
+ }
+ if (hasNext && event != null) {
+ 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()) == true) {
+ event = (TimeChartEvent) iterator.next();
+ break;
+ }
+ }
+ if (hasNext && event != null) {
+ // 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()) == true) {
+ event = (TimeChartEvent) iterator.next();
+ break;
+ }
+ }
+ if (hasNext && event != null) {
+ // 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, ITmfTimestamp.NANOSECOND_SCALE).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);
+ final ITmfTimestamp startTimestamp = new TmfTimestamp(event.getStartTime(), ITmfTimestamp.NANOSECOND_SCALE);
+ final ITmfTimestamp endTimestamp = new TmfTimestamp(event.getEndTime(), ITmfTimestamp.NANOSECOND_SCALE);
+ TmfTimeRange range = new TmfTimeRange(startTimestamp, endTimestamp);
+ broadcast(new TmfRangeSynchSignal(this, range));
+ }
+
+ @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.getBeginTime(), TIMESTAMP_SCALE), new TmfTimestamp(event.getEndTime(), 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();
+ }
+
+ // ------------------------------------------------------------------------
+ // Signal handlers
+ // ------------------------------------------------------------------------
+
+ /**
+ * Handler for the Trace Opened signal
+ *
+ * @param signal
+ * The incoming signal
+ * @since 2.0
+ */
+ @TmfSignalHandler
+ public void traceOpened(TmfTraceOpenedSignal signal) {
+ final ITmfTrace trace = signal.getTrace();
+ final IFile bookmarksFile = signal.getEditorFile();
+ 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();
+ }
+
+ /**
+ * Handler for the Trace Closed signal
+ *
+ * @param signal
+ * The incoming signal
+ * @since 2.0
+ */
+ @TmfSignalHandler
+ public void traceClosed(TmfTraceClosedSignal signal) {
+ 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);
+ synchronized (fDecorateThreads) {
+ for (DecorateThread thread : fDecorateThreads) {
+ if (thread.fTimeAnalysisEntry.getTrace() == trace) {
+ thread.cancel();
+ fDecorateThreads.remove(thread);
+ break;
+ }
+ }
+ }
+ refreshViewer();
+ break;
+ }
+ }
+ }
+
+ /**
+ * Handler for the Trace Selected signal
+ *
+ * @param signal
+ * The incoming signal
+ */
+ @TmfSignalHandler
+ public void traceSelected(TmfTraceSelectedSignal signal) {
+ if (signal.getSource() != this) {
+ 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;
+ }
+ }
+ long beginTime = fTraceManager.getSelectionBeginTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+ long endTime = fTraceManager.getSelectionEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+ fViewer.setSelectionRange(beginTime, endTime);
+ }
+ }
+
+ /**
+ * Handler for the Trace Updated signal
+ *
+ * @param signal
+ * The incoming signal
+ */
+ @TmfSignalHandler
+ public void traceUpdated(TmfTraceUpdatedSignal signal) {
+ 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 beginTime = signal.getBeginTime().normalize(0, TIMESTAMP_SCALE).getValue();
+ final long endTime = signal.getEndTime().normalize(0, TIMESTAMP_SCALE).getValue();
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (beginTime == endTime) {
+ fViewer.setSelectedTime(beginTime, true);
+ if (fStartTime != fViewer.getTime0() || fStopTime != fViewer.getTime1()) {
+ fStartTime = fViewer.getTime0();
+ fStopTime = fViewer.getTime1();
+ itemize(fStartTime, fStopTime);
+ }
+ } else {
+ fViewer.setSelectionRange(beginTime, endTime);
+ }
+ }
+ });
+ }
+
+ /**
+ * Handler for the Time Range Synch signal
+ *
+ * @param signal
+ * The incoming signal
+ * @since 2.0
+ */
+ @TmfSignalHandler
+ public void synchToRange(final TmfRangeSynchSignal signal) {
+ if (signal.getSource() == this) {
+ return;
+ }
+ final long startTime = signal.getCurrentRange().getStartTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+ final long endTime = signal.getCurrentRange().getEndTime().normalize(0, ITmfTimestamp.NANOSECOND_SCALE).getValue();
+ Display.getDefault().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ fStartTime = startTime;
+ fStopTime = endTime;
+ itemize(fStartTime, fStopTime);
+ fViewer.setStartFinishTime(startTime, endTime);
+ }
+ });
+ }
+
+ /**
+ * Handler for the Event Filter Applied signal
+ *
+ * @param signal
+ * The incoming signal
+ * @since 2.0
+ */
+ @TmfSignalHandler
+ public void filterApplied(TmfEventFilterAppliedSignal signal) {
+ TimeChartDecorationProvider decorationProvider = fDecorationProviders.get(signal.getTrace());
+ if (decorationProvider == null) {
+ return;
+ }
+ decorationProvider.filterApplied(signal.getEventFilter());
+ redecorate();
+ }
+
+ /**
+ * Handler for the Event Search Applied signal
+ *
+ * @param signal
+ * The incoming signal
+ * @since 2.0
+ */
+ @TmfSignalHandler
+ public void searchApplied(TmfEventSearchAppliedSignal signal) {
+ TimeChartDecorationProvider decorationProvider = fDecorationProviders.get(signal.getTrace());
+ if (decorationProvider == null) {
+ return;
+ }
+ decorationProvider.searchApplied(signal.getSearchFilter());
+ redecorate();
+ }
+
+}