Commit | Line | Data |
---|---|---|
03c96217 | 1 | /****************************************************************************** |
edded5c1 | 2 | * Copyright (c) 2015, 2016 Ericsson |
03c96217 BH |
3 | * |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: | |
10 | * France Lapointe Nguyen - Initial API and implementation | |
11 | * Bernd Hufmann - Extracted abstract class from LatencyScatterGraphViewer | |
12 | *******************************************************************************/ | |
13 | ||
edded5c1 | 14 | package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.scatter; |
03c96217 | 15 | |
21c917fe | 16 | import java.text.Format; |
03c96217 BH |
17 | import java.util.ArrayList; |
18 | import java.util.Collection; | |
19 | import java.util.Collections; | |
20 | import java.util.Iterator; | |
21 | import java.util.List; | |
e18d40d0 | 22 | import java.util.concurrent.atomic.AtomicInteger; |
03c96217 BH |
23 | |
24 | import org.eclipse.core.runtime.IProgressMonitor; | |
25 | import org.eclipse.core.runtime.IStatus; | |
26 | import org.eclipse.core.runtime.Status; | |
27 | import org.eclipse.core.runtime.jobs.Job; | |
28 | import org.eclipse.jdt.annotation.Nullable; | |
03c96217 BH |
29 | import org.eclipse.swt.widgets.Composite; |
30 | import org.eclipse.swt.widgets.Display; | |
03c96217 | 31 | import org.eclipse.tracecompass.analysis.timing.core.segmentstore.IAnalysisProgressListener; |
0f769d2b | 32 | import org.eclipse.tracecompass.analysis.timing.core.segmentstore.ISegmentStoreProvider; |
21c917fe | 33 | import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.SubSecondTimeWithUnitFormat; |
03c96217 BH |
34 | import org.eclipse.tracecompass.common.core.NonNullUtils; |
35 | import org.eclipse.tracecompass.internal.analysis.timing.ui.Activator; | |
edded5c1 | 36 | import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter.Messages; |
21c917fe | 37 | import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.scatter.SegmentStoreScatterGraphTooltipProvider; |
03c96217 BH |
38 | import org.eclipse.tracecompass.segmentstore.core.ISegment; |
39 | import org.eclipse.tracecompass.segmentstore.core.ISegmentStore; | |
40 | import org.eclipse.tracecompass.segmentstore.core.SegmentComparators; | |
0f769d2b | 41 | import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule; |
03c96217 | 42 | import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; |
03c96217 BH |
43 | import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal; |
44 | import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal; | |
45 | import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal; | |
46 | import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal; | |
03c96217 BH |
47 | import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange; |
48 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
49 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; | |
03c96217 | 50 | import org.eclipse.tracecompass.tmf.ui.viewers.xycharts.linecharts.TmfCommonXLineChartViewer; |
03c96217 BH |
51 | import org.swtchart.ILineSeries; |
52 | import org.swtchart.ILineSeries.PlotSymbolType; | |
53 | import org.swtchart.ISeries.SeriesType; | |
54 | import org.swtchart.ISeriesSet; | |
55 | import org.swtchart.LineStyle; | |
85ca1cfe MK |
56 | |
57 | import com.google.common.primitives.Doubles; | |
03c96217 BH |
58 | |
59 | /** | |
0f769d2b | 60 | * Displays the segment store provider data in a scatter graph |
03c96217 BH |
61 | * |
62 | * @author France Lapointe Nguyen | |
63 | * @author Matthew Khouzam - reduced memory usage | |
64 | * @since 2.0 | |
65 | */ | |
66 | public abstract class AbstractSegmentStoreScatterGraphViewer extends TmfCommonXLineChartViewer { | |
03c96217 | 67 | |
21c917fe MK |
68 | private static final Format FORMAT = new SubSecondTimeWithUnitFormat(); |
69 | ||
e18d40d0 GB |
70 | private final AtomicInteger fDirty = new AtomicInteger(); |
71 | ||
03c96217 BH |
72 | private final class CompactingSegmentStoreQuery extends Job { |
73 | private static final long MAX_POINTS = 1000; | |
74 | private final TmfTimeRange fCurrentRange; | |
75 | ||
76 | private CompactingSegmentStoreQuery(TmfTimeRange currentRange) { | |
77 | super(Messages.SegmentStoreScatterGraphViewer_compactTitle); | |
78 | fCurrentRange = currentRange; | |
79 | } | |
80 | ||
81 | @Override | |
82 | protected IStatus run(@Nullable IProgressMonitor monitor) { | |
83 | final IProgressMonitor statusMonitor = monitor; | |
e18d40d0 GB |
84 | try { |
85 | if (statusMonitor == null) { | |
86 | return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Monitor is null"); //$NON-NLS-1$ | |
87 | } | |
03c96217 | 88 | |
e18d40d0 GB |
89 | ISegmentStoreProvider segmentProvider = getSegmentProvider(); |
90 | final long startTimeInNanos = fCurrentRange.getStartTime().toNanos(); | |
91 | final long endTimeInNanos = fCurrentRange.getEndTime().toNanos(); | |
92 | if (segmentProvider == null) { | |
93 | setWindowRange(startTimeInNanos, endTimeInNanos); | |
94 | redraw(statusMonitor, startTimeInNanos, startTimeInNanos, Collections.EMPTY_LIST); | |
95 | return new Status(IStatus.WARNING, Activator.PLUGIN_ID, "segment provider not available"); //$NON-NLS-1$ | |
96 | } | |
03c96217 | 97 | |
e18d40d0 GB |
98 | final ISegmentStore<ISegment> segStore = segmentProvider.getSegmentStore(); |
99 | if (segStore == null) { | |
100 | setWindowRange(startTimeInNanos, endTimeInNanos); | |
101 | redraw(statusMonitor, startTimeInNanos, startTimeInNanos, Collections.EMPTY_LIST); | |
102 | return new Status(IStatus.INFO, Activator.PLUGIN_ID, "Segment provider does not have segments"); //$NON-NLS-1$ | |
103 | } | |
03c96217 | 104 | |
e18d40d0 GB |
105 | final long startTime = fCurrentRange.getStartTime().getValue(); |
106 | final long endTime = fCurrentRange.getEndTime().getValue(); | |
107 | fPixelStart = startTime; | |
108 | fPixelSize = Math.max(1, (endTime - startTime) / MAX_POINTS); | |
109 | final Iterable<ISegment> intersectingElements = segStore.getIntersectingElements(startTime, endTime); | |
03c96217 | 110 | |
e18d40d0 GB |
111 | final List<ISegment> list = convertIterableToList(intersectingElements, statusMonitor); |
112 | final List<ISegment> displayData = (!list.isEmpty()) ? compactList(startTime, list, statusMonitor) : list; | |
03c96217 | 113 | |
e18d40d0 GB |
114 | setWindowRange(startTimeInNanos, endTimeInNanos); |
115 | redraw(statusMonitor, startTime, endTime, displayData); | |
03c96217 | 116 | |
e18d40d0 GB |
117 | if (statusMonitor.isCanceled()) { |
118 | return Status.CANCEL_STATUS; | |
119 | } | |
120 | return Status.OK_STATUS; | |
121 | } finally { | |
122 | /* | |
123 | * fDirty should have been incremented before creating a job, so | |
124 | * we decrement it once the job is done | |
125 | */ | |
126 | fDirty.decrementAndGet(); | |
03c96217 | 127 | } |
03c96217 BH |
128 | |
129 | } | |
130 | ||
131 | private void redraw(final IProgressMonitor statusMonitor, final long startTime, final long endTime, final List<ISegment> displayData) { | |
132 | fDisplayData = displayData; | |
e18d40d0 GB |
133 | /* |
134 | * Increment at every redraw, since the content of the view is not | |
135 | * current | |
136 | */ | |
137 | fDirty.incrementAndGet(); | |
03c96217 BH |
138 | Display.getDefault().asyncExec(new Runnable() { |
139 | ||
140 | @Override | |
141 | public void run() { | |
e18d40d0 GB |
142 | try { |
143 | updateData(startTime, endTime, displayData.size(), statusMonitor); | |
144 | } finally { | |
145 | /* Decrement once the redraw is done */ | |
146 | fDirty.decrementAndGet(); | |
147 | } | |
03c96217 BH |
148 | } |
149 | }); | |
150 | } | |
151 | ||
152 | private List<ISegment> compactList(final long startTime, final List<ISegment> listToCompact, final IProgressMonitor statusMonitor) { | |
153 | List<ISegment> displayData = new ArrayList<>(); | |
154 | ISegment last = listToCompact.get(0); | |
155 | if (last.getStart() >= startTime) { | |
156 | displayData.add(last); | |
157 | } | |
158 | for (ISegment next : listToCompact) { | |
159 | if (next.getStart() < startTime) { | |
160 | continue; | |
161 | } | |
162 | if (statusMonitor.isCanceled()) { | |
df2597e0 | 163 | return Collections.EMPTY_LIST; |
03c96217 BH |
164 | } |
165 | if (!overlaps(last, next)) { | |
166 | displayData.add(next); | |
167 | last = next; | |
168 | } | |
169 | } | |
170 | return displayData; | |
171 | } | |
172 | ||
173 | private List<ISegment> convertIterableToList(final Iterable<ISegment> iterable, final IProgressMonitor statusMonitor) { | |
174 | final List<ISegment> list = new ArrayList<>(); | |
175 | for (ISegment seg : iterable) { | |
176 | if (statusMonitor.isCanceled()) { | |
df2597e0 | 177 | return Collections.EMPTY_LIST; |
03c96217 BH |
178 | } |
179 | list.add(seg); | |
180 | } | |
181 | Collections.sort(list, SegmentComparators.INTERVAL_START_COMPARATOR); | |
182 | return list; | |
183 | } | |
184 | ||
185 | private boolean overlaps(ISegment last, ISegment next) { | |
186 | long timePerPix = fPixelSize; | |
187 | final long start = last.getStart(); | |
188 | final long pixelStart = fPixelStart; | |
189 | final long pixelDuration = start - pixelStart; | |
190 | long startPixBoundL = pixelDuration / timePerPix * timePerPix + pixelStart; | |
191 | long startPixBoundR = startPixBoundL + timePerPix; | |
192 | final long currentStart = next.getStart(); | |
193 | if (currentStart >= startPixBoundL && currentStart <= startPixBoundR) { | |
194 | long length = last.getLength(); | |
195 | long lengthNext = next.getLength(); | |
196 | long lengthLow = length / timePerPix * timePerPix; | |
197 | long lengthHigh = lengthLow + timePerPix; | |
198 | return (lengthNext >= lengthLow && lengthNext <= lengthHigh); | |
199 | } | |
200 | return false; | |
201 | } | |
202 | } | |
203 | ||
204 | // ------------------------------------------------------------------------ | |
205 | // Attributes | |
206 | // ------------------------------------------------------------------------ | |
207 | ||
208 | /** | |
0f769d2b MK |
209 | * Listener to update the model with the segment store provider results once |
210 | * its segment store is fully completed | |
03c96217 | 211 | */ |
0f769d2b | 212 | private final class SegmentStoreProviderProgressListener implements IAnalysisProgressListener { |
03c96217 BH |
213 | |
214 | @Override | |
0f769d2b | 215 | public void onComplete(ISegmentStoreProvider segmentProvider, ISegmentStore<ISegment> segmentStore) { |
03c96217 | 216 | // Only update the model if trace that was analyzed is active trace |
0f769d2b MK |
217 | if (segmentProvider.equals(getSegmentProvider())) { |
218 | updateModel(segmentStore); | |
03c96217 BH |
219 | } |
220 | } | |
221 | } | |
222 | ||
223 | private long fPixelSize = -1; | |
224 | ||
225 | private long fPixelStart = 0; | |
226 | /** | |
227 | * Data to display | |
228 | */ | |
df2597e0 | 229 | private Collection<ISegment> fDisplayData = Collections.EMPTY_LIST; |
03c96217 BH |
230 | |
231 | /** | |
0f769d2b | 232 | * Provider completion listener |
03c96217 | 233 | */ |
0f769d2b | 234 | private SegmentStoreProviderProgressListener fListener; |
03c96217 BH |
235 | |
236 | /** | |
0f769d2b | 237 | * Current segment provider |
03c96217 | 238 | */ |
0f769d2b | 239 | private @Nullable ISegmentStoreProvider fSegmentProvider; |
03c96217 BH |
240 | |
241 | private @Nullable Job fCompactingJob; | |
242 | ||
243 | // ------------------------------------------------------------------------ | |
244 | // Constructor | |
245 | // ------------------------------------------------------------------------ | |
246 | ||
247 | /** | |
248 | * Constructor | |
249 | * | |
250 | * @param parent | |
251 | * parent composite | |
252 | * @param title | |
253 | * name of the graph | |
254 | * @param xLabel | |
255 | * name of the x axis | |
256 | * @param yLabel | |
257 | * name of the y axis | |
258 | */ | |
259 | public AbstractSegmentStoreScatterGraphViewer(Composite parent, String title, String xLabel, String yLabel) { | |
260 | super(parent, title, xLabel, yLabel); | |
a2de198a | 261 | setTooltipProvider(new SegmentStoreScatterGraphTooltipProvider(this)); |
0f769d2b | 262 | fListener = new SegmentStoreProviderProgressListener(); |
03c96217 | 263 | ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace(); |
0f769d2b | 264 | initializeProvider(trace); |
03c96217 | 265 | getSwtChart().getLegend().setVisible(false); |
21c917fe | 266 | getSwtChart().getAxisSet().getYAxis(0).getTick().setFormat(FORMAT); |
03c96217 BH |
267 | } |
268 | ||
0f769d2b | 269 | private final void initializeProvider(@Nullable ITmfTrace trace) { |
03c96217 | 270 | if (trace != null) { |
0f769d2b MK |
271 | final ISegmentStoreProvider segmentStoreProvider = getSegmentStoreProvider(trace); |
272 | if (segmentStoreProvider != null) { | |
273 | segmentStoreProvider.addListener(fListener); | |
274 | setData(segmentStoreProvider); | |
03c96217 BH |
275 | } |
276 | } | |
277 | } | |
278 | ||
279 | // ------------------------------------------------------------------------ | |
280 | // Operations | |
281 | // ------------------------------------------------------------------------ | |
282 | ||
283 | /** | |
284 | * Update the data in the graph | |
285 | * | |
286 | * @param dataInput | |
287 | * new model | |
288 | */ | |
289 | public void updateModel(@Nullable ISegmentStore<ISegment> dataInput) { | |
290 | // Update new window range | |
291 | TmfTimeRange currentRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange(); | |
16801c72 MK |
292 | long currentStart = currentRange.getStartTime().toNanos(); |
293 | long currentEnd = currentRange.getEndTime().toNanos(); | |
03c96217 BH |
294 | if (dataInput == null) { |
295 | if (!getDisplay().isDisposed()) { | |
296 | Display.getDefault().syncExec(new Runnable() { | |
297 | @Override | |
298 | public void run() { | |
299 | clearContent(); | |
300 | } | |
301 | }); | |
302 | } | |
df2597e0 | 303 | fDisplayData = Collections.EMPTY_LIST; |
03c96217 BH |
304 | } else { |
305 | Collection<ISegment> elements = (Collection<ISegment>) dataInput.getIntersectingElements(currentStart, currentEnd); | |
306 | // getIntersectingElements can return an unsorted iterable, make | |
307 | // sure our collection is sorted | |
308 | ArrayList<ISegment> list = new ArrayList<>(elements); | |
309 | Collections.sort(list, SegmentComparators.INTERVAL_START_COMPARATOR); | |
310 | fDisplayData = list; | |
311 | } | |
312 | setWindowRange(currentStart, currentEnd); | |
313 | updateRange(currentRange); | |
314 | } | |
315 | ||
316 | @Override | |
317 | protected void initializeDataSource() { | |
318 | ITmfTrace trace = getTrace(); | |
0f769d2b | 319 | initializeProvider(trace); |
03c96217 | 320 | if (trace != null) { |
0f769d2b | 321 | setData(getSegmentStoreProvider(trace)); |
03c96217 BH |
322 | } |
323 | } | |
324 | ||
325 | @Override | |
326 | protected void updateData(final long start, final long end, int nb, @Nullable IProgressMonitor monitor) { | |
327 | // Third parameter is not used by implementation | |
328 | // Determine data that needs to be visible | |
329 | Collection<ISegment> data = fDisplayData; | |
330 | ||
331 | final int dataSize = (nb == 0) ? data.size() : nb; | |
44af9da9 | 332 | if (end == start) { |
03c96217 BH |
333 | return; |
334 | } | |
335 | ||
85ca1cfe MK |
336 | List<Double> xSeries = new ArrayList<>(dataSize); |
337 | List<Double> ySeries = new ArrayList<>(dataSize); | |
03c96217 BH |
338 | // For each visible segments, add start time to x value and duration |
339 | // for y value | |
340 | Iterator<ISegment> modelIter = data.iterator(); | |
85ca1cfe MK |
341 | while (modelIter.hasNext()) { |
342 | ISegment segment = modelIter.next(); | |
343 | xSeries.add((double) (segment.getStart() - start)); | |
344 | ySeries.add((double) segment.getLength()); | |
03c96217 | 345 | } |
85ca1cfe | 346 | setXAxis(Doubles.toArray(xSeries)); |
44af9da9 | 347 | setSeries(Messages.SegmentStoreScatterGraphViewer_legend, Doubles.toArray(ySeries)); |
85ca1cfe | 348 | updateDisplay(); |
03c96217 BH |
349 | } |
350 | ||
351 | @Override | |
352 | protected void setWindowRange(final long windowStartTime, final long windowEndTime) { | |
353 | super.setWindowRange(windowStartTime, windowEndTime); | |
354 | } | |
355 | ||
356 | @Override | |
357 | protected ILineSeries addSeries(@Nullable String seriesName) { | |
358 | ISeriesSet seriesSet = getSwtChart().getSeriesSet(); | |
359 | ILineSeries series = (ILineSeries) seriesSet.createSeries(SeriesType.LINE, seriesName); | |
360 | series.setVisible(true); | |
361 | series.enableArea(false); | |
362 | series.setLineStyle(LineStyle.NONE); | |
363 | series.setSymbolType(PlotSymbolType.DIAMOND); | |
364 | return series; | |
365 | } | |
366 | ||
367 | /** | |
0f769d2b MK |
368 | * Set the data into the viewer. If the provider is an analysis, it will |
369 | * update the model if the analysis is completed or run the analysis if not | |
370 | * completed | |
03c96217 | 371 | * |
0f769d2b MK |
372 | * @param provider |
373 | * Segment store provider | |
03c96217 | 374 | */ |
0f769d2b MK |
375 | public void setData(@Nullable ISegmentStoreProvider provider) { |
376 | if (provider == null) { | |
03c96217 BH |
377 | updateModel(null); |
378 | return; | |
379 | } | |
0f769d2b MK |
380 | ISegmentStore<ISegment> segStore = provider.getSegmentStore(); |
381 | // If results are not null, then segment store is completed and model | |
382 | // can be updated | |
73c74de7 JCK |
383 | if (segStore != null) { |
384 | updateModel(segStore); | |
0f769d2b | 385 | setSegmentProvider(provider); |
03c96217 BH |
386 | return; |
387 | } | |
388 | updateModel(null); | |
0f769d2b MK |
389 | provider.addListener(fListener); |
390 | if (provider instanceof IAnalysisModule) { | |
391 | ((IAnalysisModule) provider).schedule(); | |
392 | } | |
393 | setSegmentProvider(provider); | |
03c96217 BH |
394 | } |
395 | ||
396 | /** | |
0f769d2b | 397 | * Returns the segment store provider |
df2597e0 | 398 | * |
03c96217 BH |
399 | * @param trace |
400 | * The trace to consider | |
0f769d2b | 401 | * @return the segment store provider |
03c96217 | 402 | */ |
0f769d2b | 403 | protected @Nullable abstract ISegmentStoreProvider getSegmentStoreProvider(ITmfTrace trace); |
03c96217 | 404 | |
03c96217 BH |
405 | // ------------------------------------------------------------------------ |
406 | // Signal handlers | |
407 | // ------------------------------------------------------------------------ | |
408 | ||
409 | /** | |
410 | * @param signal | |
411 | * Signal received when a different trace is selected | |
412 | */ | |
413 | @Override | |
414 | @TmfSignalHandler | |
415 | public void traceSelected(@Nullable TmfTraceSelectedSignal signal) { | |
416 | super.traceSelected(signal); | |
417 | if (signal == null) { | |
418 | return; | |
419 | } | |
420 | ITmfTrace trace = signal.getTrace(); | |
421 | setTrace(trace); | |
422 | if (trace != null) { | |
423 | final TmfTimeRange timeRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange(); | |
424 | setWindowRange( | |
16801c72 MK |
425 | timeRange.getStartTime().toNanos(), |
426 | timeRange.getEndTime().toNanos()); | |
0f769d2b | 427 | setData(getSegmentStoreProvider(trace)); |
03c96217 BH |
428 | updateRange(timeRange); |
429 | } | |
430 | } | |
431 | ||
432 | /** | |
433 | * @param signal | |
434 | * Signal received when trace is opened | |
435 | */ | |
436 | @Override | |
437 | @TmfSignalHandler | |
438 | public void traceOpened(@Nullable TmfTraceOpenedSignal signal) { | |
439 | super.traceOpened(signal); | |
440 | if (signal == null) { | |
441 | return; | |
442 | } | |
443 | ITmfTrace trace = signal.getTrace(); | |
444 | setTrace(trace); | |
445 | if (trace != null) { | |
446 | ||
0f769d2b | 447 | final ISegmentStoreProvider segmentStoreProvider = getSegmentStoreProvider(trace); |
03c96217 BH |
448 | final TmfTimeRange timeRange = TmfTraceManager.getInstance().getCurrentTraceContext().getWindowRange(); |
449 | setWindowRange( | |
16801c72 MK |
450 | timeRange.getStartTime().toNanos(), |
451 | timeRange.getEndTime().toNanos()); | |
0f769d2b | 452 | setData(segmentStoreProvider); |
03c96217 BH |
453 | } |
454 | ||
455 | } | |
456 | ||
457 | private void updateRange(final @Nullable TmfTimeRange timeRange) { | |
e18d40d0 GB |
458 | /* |
459 | * Update is request, content is not up to date, fDirty will be | |
460 | * decremented in the compacting job | |
461 | */ | |
462 | fDirty.incrementAndGet(); | |
03c96217 BH |
463 | Job compactingJob = fCompactingJob; |
464 | if (compactingJob != null && compactingJob.getState() == Job.RUNNING) { | |
465 | compactingJob.cancel(); | |
466 | } | |
467 | compactingJob = new CompactingSegmentStoreQuery(NonNullUtils.checkNotNull(timeRange)); | |
468 | fCompactingJob = compactingJob; | |
469 | compactingJob.schedule(); | |
470 | } | |
471 | ||
472 | /** | |
473 | * @param signal | |
474 | * Signal received when last opened trace is closed | |
475 | */ | |
476 | @Override | |
477 | @TmfSignalHandler | |
478 | public void traceClosed(@Nullable TmfTraceClosedSignal signal) { | |
479 | super.traceClosed(signal); | |
480 | if (signal != null) { | |
481 | // Check if there is no more opened trace | |
482 | if (TmfTraceManager.getInstance().getActiveTrace() == null) { | |
0f769d2b MK |
483 | ISegmentStoreProvider provider = getSegmentProvider(); |
484 | if (provider != null) { | |
485 | provider.removeListener(fListener); | |
03c96217 BH |
486 | } |
487 | clearContent(); | |
488 | } | |
489 | } | |
490 | refresh(); | |
491 | } | |
492 | ||
493 | /** | |
494 | * @param signal | |
495 | * Signal received when window range is updated | |
496 | */ | |
497 | @Override | |
498 | @TmfSignalHandler | |
499 | public void windowRangeUpdated(@Nullable TmfWindowRangeUpdatedSignal signal) { | |
500 | super.windowRangeUpdated(signal); | |
501 | if (signal == null) { | |
502 | return; | |
503 | } | |
504 | if (getTrace() != null) { | |
505 | final TmfTimeRange currentRange = signal.getCurrentRange(); | |
506 | updateRange(currentRange); | |
507 | } else { | |
508 | Activator.getDefault().logInfo("No Trace to update"); //$NON-NLS-1$ | |
509 | } | |
510 | } | |
511 | ||
0f769d2b MK |
512 | private @Nullable ISegmentStoreProvider getSegmentProvider() { |
513 | return fSegmentProvider; | |
03c96217 BH |
514 | } |
515 | ||
0f769d2b MK |
516 | private void setSegmentProvider(ISegmentStoreProvider provider) { |
517 | fSegmentProvider = provider; | |
03c96217 | 518 | } |
e18d40d0 GB |
519 | |
520 | @Override | |
521 | public boolean isDirty() { | |
522 | /* Check the parent's or this view's own dirtiness */ | |
523 | return super.isDirty() || (fDirty.get() != 0); | |
524 | } | |
03c96217 | 525 | } |