blob: 32a7c3fcc09c4bd09ac3e68d47a2a3c330afe40a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2019 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Patrick Tasse - Initial API and implementation
*******************************************************************************/
package org.eclipse.tracecompass.tmf.ui.views.timechart;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
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.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
import org.eclipse.tracecompass.tmf.core.resources.ITmfMarker;
import org.eclipse.tracecompass.tmf.core.signal.TmfEventFilterAppliedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfEventSearchAppliedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
import org.eclipse.tracecompass.tmf.core.signal.TmfTimestampFormatUpdateSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfTraceUpdatedSignal;
import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal;
import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimePreferencesConstants;
import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimePreferences;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
import org.eclipse.tracecompass.tmf.ui.views.ITmfTimeAligned;
import org.eclipse.tracecompass.tmf.ui.views.TmfView;
import org.eclipse.tracecompass.tmf.ui.views.colors.ColorSetting;
import org.eclipse.tracecompass.tmf.ui.views.colors.ColorSettingsManager;
import org.eclipse.tracecompass.tmf.ui.views.colors.IColorSettingsListener;
import org.eclipse.tracecompass.tmf.ui.views.timechart.TimeChartEvent.RankRange;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphRangeListener;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphSelectionListener;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.ITimeGraphTimeListener;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphRangeUpdateEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphSelectionEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphTimeEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.TimeGraphViewer;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeEvent;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.widgets.Utils.TimeFormat;
/**
* 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, ITmfTimeAligned {
/** TimeChartView's ID */
public static final String ID = "org.eclipse.linuxtools.tmf.ui.views.timechart"; //$NON-NLS-1$
private final int fDisplayWidth;
private TimeGraphViewer fViewer;
private final List<TimeChartAnalysisEntry> fTimeAnalysisEntries = new ArrayList<>();
private final Map<ITmfTrace, TimeChartDecorationProvider> fDecorationProviders = new HashMap<>();
private final List<DecorateThread> fDecorateThreads = new ArrayList<>();
private final Map<ITmfTrace, ProcessTraceThread> fProcessTraceThreads = new HashMap<>();
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 TimeChartAnalysisProvider fPresentationProvider;
/**
* Default constructor
*/
public TimeChartView() {
super("Time Chart"); //$NON-NLS-1$
fDisplayWidth = Display.getDefault().getBounds().width;
}
@Override
public void createPartControl(Composite parent) {
super.createPartControl(parent);
fViewer = new TimeGraphViewer(parent, SWT.NONE);
fPresentationProvider = new TimeChartAnalysisProvider();
fViewer.setTimeGraphProvider(fPresentationProvider);
fViewer.addTimeListener(this);
fViewer.addRangeListener(this);
fViewer.addSelectionListener(this);
fViewer.setMinimumItemWidth(1);
fViewer.getTimeGraphControl().setBlendSubPixelEvents(true);
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));
startProcessTraceThread(timeAnalysisEntry);
}
fViewer.setInput(fTimeAnalysisEntries.toArray(new TimeChartAnalysisEntry[0]));
ColorSettingsManager.addColorSettingsListener(this);
ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
updateTimeFormat();
}
@Override
public void dispose() {
ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
synchronized (fDecorateThreads) {
for (DecorateThread thread : fDecorateThreads) {
thread.cancel();
}
}
ColorSettingsManager.removeColorSettingsListener(this);
super.dispose();
}
@Override
public void setFocus() {
fViewer.setFocus();
}
private void startProcessTraceThread(TimeChartAnalysisEntry entry) {
synchronized (fProcessTraceThreads) {
ProcessTraceThread thread = fProcessTraceThreads.get(entry.getTrace());
if (thread != null) {
thread.restart();
} else {
thread = new ProcessTraceThread(entry);
fProcessTraceThreads.put(entry.getTrace(), thread);
thread.start();
}
}
}
private class ProcessTraceThread extends Thread {
private final TimeChartAnalysisEntry fTimeAnalysisEntry;
private boolean fRestart;
public ProcessTraceThread(TimeChartAnalysisEntry timeAnalysisEntry) {
super("ProcessTraceJob:" + timeAnalysisEntry.getName()); //$NON-NLS-1$
fTimeAnalysisEntry = timeAnalysisEntry;
}
public void restart() {
synchronized (fProcessTraceThreads) {
fRestart = true;
}
}
@Override
public void run() {
while (true) {
updateTraceEntry(fTimeAnalysisEntry, Long.MAX_VALUE,
TmfTimestamp.BIG_BANG.toNanos(),
TmfTimestamp.BIG_CRUNCH.toNanos());
synchronized (fProcessTraceThreads) {
if (fRestart) {
fRestart = false;
} else {
fProcessTraceThreads.remove(fTimeAnalysisEntry.getTrace());
return;
}
}
}
}
}
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(() -> {
if (fViewer.getControl().isDisposed()) {
return;
}
fViewer.setInput(fTimeAnalysisEntries.toArray(new TimeChartAnalysisEntry[0]));
fViewer.resetStartFinishTime(false);
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(() -> {
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().toNanos();
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 = TmfTimestamp.fromNanos(event.getStartTime());
final ITmfTimestamp endTimestamp = TmfTimestamp.fromNanos(event.getEndTime());
TmfTimeRange range = new TmfTimeRange(startTimestamp, endTimestamp);
broadcast(new TmfWindowRangeUpdatedSignal(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 TmfSelectionRangeUpdatedSignal(this, TmfTimestamp.fromNanos(event.getBeginTime()), TmfTimestamp.fromNanos(event.getEndTime())));
}
@Override
public void colorSettingsChanged(ColorSetting[] colorSettings) {
fPresentationProvider.colorSettingsChanged(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.REMOVED ||
delta.getMarker().getAttribute(IMarker.LOCATION, -1) != -1 ||
delta.getMarker().getAttribute(ITmfMarker.MARKER_RANK, (String) null) != null) {
provider.refreshBookmarks();
}
}
}
}
redecorate();
}
// ------------------------------------------------------------------------
// Signal handlers
// ------------------------------------------------------------------------
/**
* Handler for the Trace Opened signal
*
* @param signal
* The incoming signal
*/
@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));
startProcessTraceThread(timeAnalysisEntry);
}
refreshViewer();
}
/**
* Handler for the Trace Closed signal
*
* @param signal
* The incoming signal
*/
@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), true);
break;
}
}
TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
long beginTime = ctx.getSelectionRange().getStartTime().toNanos();
long endTime = ctx.getSelectionRange().getEndTime().toNanos();
fViewer.setSelectionRange(beginTime, endTime, false);
}
}
/**
* 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)) {
startProcessTraceThread(timeAnalysisEntry);
break;
}
}
}
/**
* Handler for the selection range updated signal.
*
* @param signal
* The incoming signal
* @since 1.0
*/
@TmfSignalHandler
public void selectionRangeUpdated(TmfSelectionRangeUpdatedSignal signal) {
final long beginTime = signal.getBeginTime().toNanos();
final long endTime = signal.getEndTime().toNanos();
Display.getDefault().asyncExec(() -> {
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, true);
}
});
}
/**
* Handler for the window range updated signal.
*
* @param signal
* The incoming signal
* @since 1.0
*/
@TmfSignalHandler
public void windowRangeUpdated(final TmfWindowRangeUpdatedSignal signal) {
if (signal.getSource() == this) {
return;
}
final long startTime = signal.getCurrentRange().getStartTime().toNanos();
final long endTime = signal.getCurrentRange().getEndTime().toNanos();
Display.getDefault().asyncExec(() -> {
fStartTime = startTime;
fStopTime = endTime;
itemize(fStartTime, fStopTime);
fViewer.setStartFinishTime(startTime, endTime);
});
}
/**
* Handler for the Event Filter Applied signal
*
* @param signal
* The incoming signal
*/
@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
*/
@TmfSignalHandler
public void searchApplied(TmfEventSearchAppliedSignal signal) {
TimeChartDecorationProvider decorationProvider = fDecorationProviders.get(signal.getTrace());
if (decorationProvider == null) {
return;
}
decorationProvider.searchApplied(signal.getSearchFilter());
redecorate();
}
/**
* Handler for the Timestamp Format Updated signal
*
* @param signal
* the format of the timestamps was updated.
* @since 5.0
*/
@TmfSignalHandler
public void updateTimeFormat(final TmfTimestampFormatUpdateSignal signal) {
updateTimeFormat();
fViewer.refresh();
}
private void updateTimeFormat() {
String datime = TmfTimePreferences.getPreferenceMap().get(ITmfTimePreferencesConstants.DATIME);
if (ITmfTimePreferencesConstants.TIME_ELAPSED_FMT.equals(datime)) {
fViewer.setTimeFormat(TimeFormat.RELATIVE);
} else {
fViewer.setTimeFormat(TimeFormat.CALENDAR);
}
}
/**
* @since 1.0
*/
@Override
public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
if (fViewer == null) {
return null;
}
return fViewer.getTimeViewAlignmentInfo();
}
/**
* @since 1.0
*/
@Override
public int getAvailableWidth(int requestedOffset) {
return fViewer.getAvailableWidth(requestedOffset);
}
/**
* @since 1.0
*/
@Override
public void performAlign(int offset, int width) {
fViewer.performAlign(offset, width);
}
}