Commit | Line | Data |
---|---|---|
7b79ee46 FLN |
1 | /******************************************************************************* |
2 | * Copyright (c) 2015 Ericsson | |
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 | *******************************************************************************/ | |
12 | ||
13 | package org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency; | |
14 | ||
15 | import org.eclipse.jdt.annotation.Nullable; | |
21de574d BH |
16 | import org.eclipse.jface.action.Action; |
17 | import org.eclipse.jface.action.IAction; | |
18 | import org.eclipse.jface.action.IMenuManager; | |
7b79ee46 | 19 | import org.eclipse.jface.viewers.ColumnLabelProvider; |
21de574d | 20 | import org.eclipse.jface.viewers.IStructuredSelection; |
7b79ee46 FLN |
21 | import org.eclipse.jface.viewers.StructuredSelection; |
22 | import org.eclipse.jface.viewers.TableViewer; | |
23 | import org.eclipse.swt.events.SelectionAdapter; | |
24 | import org.eclipse.swt.events.SelectionEvent; | |
25 | import org.eclipse.swt.widgets.Display; | |
26 | import org.eclipse.tracecompass.analysis.os.linux.core.latency.LatencyAnalysis; | |
27 | import org.eclipse.tracecompass.analysis.os.linux.core.latency.LatencyAnalysisListener; | |
28 | import org.eclipse.tracecompass.common.core.NonNullUtils; | |
29 | import org.eclipse.tracecompass.segmentstore.core.ISegment; | |
30 | import org.eclipse.tracecompass.segmentstore.core.ISegmentStore; | |
31 | import org.eclipse.tracecompass.segmentstore.core.SegmentComparators; | |
32 | import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal; | |
33 | import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; | |
34 | import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; | |
35 | import org.eclipse.tracecompass.tmf.core.signal.TmfTraceClosedSignal; | |
36 | import org.eclipse.tracecompass.tmf.core.signal.TmfTraceOpenedSignal; | |
37 | import org.eclipse.tracecompass.tmf.core.signal.TmfTraceSelectedSignal; | |
38 | import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp; | |
39 | import org.eclipse.tracecompass.tmf.core.timestamp.TmfNanoTimestamp; | |
40 | import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestampFormat; | |
41 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
42 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; | |
43 | import org.eclipse.tracecompass.tmf.core.trace.TmfTraceUtils; | |
44 | import org.eclipse.tracecompass.tmf.ui.viewers.table.TmfSimpleTableViewer; | |
45 | ||
46 | /** | |
47 | * Displays the latency analysis data in a column table | |
48 | * | |
49 | * @author France Lapointe Nguyen | |
50 | */ | |
51 | public class LatencyTableViewer extends TmfSimpleTableViewer { | |
52 | ||
53 | // ------------------------------------------------------------------------ | |
54 | // Attributes | |
55 | // ------------------------------------------------------------------------ | |
56 | ||
a5c41909 | 57 | |
7b79ee46 FLN |
58 | /** |
59 | * Abstract class for the column label provider for the latency analysis | |
60 | * table viewer | |
61 | */ | |
62 | private abstract class LatencyTableColumnLabelProvider extends ColumnLabelProvider { | |
63 | ||
64 | @Override | |
65 | public String getText(@Nullable Object input) { | |
66 | if (!(input instanceof ISegment)) { | |
67 | /* Doubles as a null check */ | |
68 | return ""; //$NON-NLS-1$ | |
69 | } | |
70 | return getTextFoITimeRange((ISegment) input); | |
71 | } | |
72 | ||
73 | public abstract String getTextFoITimeRange(ISegment input); | |
74 | } | |
75 | ||
76 | /** | |
77 | * Listener to update the model with the latency analysis results once the | |
78 | * latency analysis is fully completed | |
79 | */ | |
80 | private final class LatencyListener implements LatencyAnalysisListener { | |
81 | @Override | |
82 | public void onComplete(LatencyAnalysis activeAnalysis, ISegmentStore<ISegment> data) { | |
83 | // Check if the active trace was changed while the analysis was | |
84 | // running | |
85 | if (activeAnalysis.equals(fAnalysisModule)) { | |
86 | updateModel(data); | |
87 | } | |
88 | } | |
89 | } | |
90 | ||
91 | /** | |
92 | * Listener to select a range in other viewers when a cell of the latency | |
93 | * table view is selected | |
94 | */ | |
95 | private class LatencyTableSelectionListener extends SelectionAdapter { | |
96 | @Override | |
97 | public void widgetSelected(@Nullable SelectionEvent e) { | |
98 | ISegment selectedSegment = ((ISegment) NonNullUtils.checkNotNull(e).item.getData()); | |
99 | ITmfTimestamp start = new TmfNanoTimestamp(selectedSegment.getStart()); | |
100 | ITmfTimestamp end = new TmfNanoTimestamp(selectedSegment.getEnd()); | |
101 | TmfSignalManager.dispatchSignal(new TmfSelectionRangeUpdatedSignal(LatencyTableViewer.this, start, end)); | |
102 | } | |
103 | } | |
104 | ||
105 | /** | |
106 | * Current latency analysis module | |
107 | */ | |
108 | private @Nullable LatencyAnalysis fAnalysisModule = null; | |
109 | ||
110 | /** | |
111 | * Latency analysis completion listener | |
112 | */ | |
113 | private LatencyListener fListener; | |
114 | ||
115 | // ------------------------------------------------------------------------ | |
116 | // Constructor | |
117 | // ------------------------------------------------------------------------ | |
118 | ||
119 | /** | |
120 | * Constructor | |
121 | * | |
122 | * @param tableViewer | |
123 | * Table viewer of the view | |
124 | */ | |
125 | public LatencyTableViewer(TableViewer tableViewer) { | |
126 | super(tableViewer); | |
127 | // Sort order of the content provider is by start time by default | |
128 | getTableViewer().setContentProvider(new LatencyContentProvider()); | |
129 | ITmfTrace trace = TmfTraceManager.getInstance().getActiveTrace(); | |
130 | if (trace != null) { | |
131 | fAnalysisModule = TmfTraceUtils.getAnalysisModuleOfClass(trace, LatencyAnalysis.class, LatencyAnalysis.ID); | |
132 | } | |
133 | createColumns(); | |
134 | getTableViewer().getTable().addSelectionListener(new LatencyTableSelectionListener()); | |
135 | fListener = new LatencyListener(); | |
136 | } | |
137 | ||
138 | // ------------------------------------------------------------------------ | |
139 | // Operations | |
140 | // ------------------------------------------------------------------------ | |
141 | ||
142 | /** | |
143 | * Create columns for start time, end time and duration | |
144 | */ | |
145 | private void createColumns() { | |
146 | createColumn(Messages.LatencyTableViewer_startTime, new LatencyTableColumnLabelProvider() { | |
147 | @Override | |
148 | public String getTextFoITimeRange(ISegment input) { | |
149 | return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getStart())); | |
150 | } | |
151 | }, SegmentComparators.INTERVAL_START_COMPARATOR); | |
152 | ||
153 | createColumn(Messages.LatencyTableViewer_endTime, new LatencyTableColumnLabelProvider() { | |
154 | @Override | |
155 | public String getTextFoITimeRange(ISegment input) { | |
156 | return NonNullUtils.nullToEmptyString(TmfTimestampFormat.getDefaulTimeFormat().format(input.getEnd())); | |
157 | } | |
158 | }, SegmentComparators.INTERVAL_END_COMPARATOR); | |
159 | ||
160 | createColumn(Messages.LatencyTableViewer_duration, new LatencyTableColumnLabelProvider() { | |
161 | @Override | |
162 | public String getTextFoITimeRange(ISegment input) { | |
163 | return NonNullUtils.nullToEmptyString(Long.toString(input.getLength())); | |
164 | } | |
165 | }, SegmentComparators.INTERVAL_LENGTH_COMPARATOR); | |
166 | } | |
167 | ||
168 | /** | |
169 | * Update the data in the table viewer | |
170 | * | |
171 | * @param dataInput | |
172 | * New data input | |
173 | */ | |
174 | public void updateModel(final @Nullable ISegmentStore<ISegment> dataInput) { | |
175 | final TableViewer tableViewer = getTableViewer(); | |
176 | Display.getDefault().asyncExec(new Runnable() { | |
177 | @Override | |
178 | public void run() { | |
179 | if (!tableViewer.getTable().isDisposed()) { | |
180 | // Go to the top of the table | |
181 | tableViewer.getTable().setTopIndex(0); | |
182 | // Reset selected row | |
183 | tableViewer.setSelection(StructuredSelection.EMPTY); | |
184 | if (dataInput == null) { | |
185 | tableViewer.setInput(null); | |
186 | tableViewer.setItemCount(0); | |
187 | return; | |
188 | } | |
189 | tableViewer.setInput(dataInput); | |
190 | LatencyContentProvider latencyContentProvider = (LatencyContentProvider) getTableViewer().getContentProvider(); | |
191 | tableViewer.setItemCount(latencyContentProvider.getSegmentCount()); | |
192 | } | |
193 | } | |
194 | }); | |
195 | } | |
196 | ||
197 | /** | |
198 | * Set the data into the viewer. Will update model is analysis is completed | |
199 | * or run analysis if not completed | |
200 | * | |
201 | * @param analysis | |
202 | * Latency analysis module | |
203 | */ | |
204 | public void setData(@Nullable LatencyAnalysis analysis) { | |
205 | // Set the current latency analysis module | |
206 | fAnalysisModule = analysis; | |
207 | if (analysis == null) { | |
208 | updateModel(null); | |
209 | return; | |
210 | } | |
211 | ISegmentStore<ISegment> results = analysis.getResults(); | |
212 | // If results are not null, then analysis is completed and model can be | |
213 | // updated | |
214 | if (results != null) { | |
215 | updateModel(results); | |
216 | return; | |
217 | } | |
218 | // If results are null, then add completion listener and run analysis | |
219 | updateModel(null); | |
220 | analysis.addListener(fListener); | |
221 | analysis.schedule(); | |
222 | } | |
223 | ||
21de574d BH |
224 | @Override |
225 | protected void appendToTablePopupMenu(IMenuManager manager, IStructuredSelection sel) { | |
226 | final ISegment segment = (ISegment) sel.getFirstElement(); | |
227 | ||
228 | IAction gotoStartTime = new Action(Messages.LatencyView_goToStartEvent) { | |
229 | @Override | |
230 | public void run() { | |
231 | broadcast(new TmfSelectionRangeUpdatedSignal(LatencyTableViewer.this, new TmfNanoTimestamp(segment.getStart()))); | |
232 | } | |
233 | }; | |
234 | ||
235 | IAction gotoEndTime = new Action(Messages.LatencyView_goToEndEvent) { | |
236 | @Override | |
237 | public void run() { | |
238 | broadcast(new TmfSelectionRangeUpdatedSignal(LatencyTableViewer.this, new TmfNanoTimestamp(segment.getEnd()))); | |
239 | } | |
240 | }; | |
241 | ||
242 | manager.add(gotoStartTime); | |
243 | manager.add(gotoEndTime); | |
244 | } | |
245 | ||
7b79ee46 FLN |
246 | // ------------------------------------------------------------------------ |
247 | // Getters | |
248 | // ------------------------------------------------------------------------ | |
249 | ||
250 | /** | |
251 | * Get current latency analysis module | |
252 | * | |
253 | * @return current latency analysis module | |
254 | */ | |
255 | public @Nullable LatencyAnalysis getAnalysisModule() { | |
256 | return fAnalysisModule; | |
257 | } | |
258 | ||
259 | // ------------------------------------------------------------------------ | |
260 | // Signal handlers | |
261 | // ------------------------------------------------------------------------ | |
262 | ||
263 | /** | |
264 | * Trace selected handler | |
265 | * | |
266 | * @param signal | |
267 | * Different opened trace (on which latency analysis as already | |
268 | * been performed) has been selected | |
269 | */ | |
270 | @TmfSignalHandler | |
271 | public void traceSelected(TmfTraceSelectedSignal signal) { | |
272 | ITmfTrace trace = signal.getTrace(); | |
273 | if (trace != null) { | |
274 | setData(TmfTraceUtils.getAnalysisModuleOfClass(trace, LatencyAnalysis.class, LatencyAnalysis.ID)); | |
275 | } | |
276 | } | |
277 | ||
278 | /** | |
279 | * Trace opened handler | |
280 | * | |
281 | * @param signal | |
282 | * New trace (on which latency analysis has not been performed) | |
283 | * is opened | |
284 | */ | |
285 | @TmfSignalHandler | |
286 | public void traceOpened(TmfTraceOpenedSignal signal) { | |
287 | ITmfTrace trace = signal.getTrace(); | |
288 | if (trace != null) { | |
289 | setData(TmfTraceUtils.getAnalysisModuleOfClass(trace, LatencyAnalysis.class, LatencyAnalysis.ID)); | |
290 | } | |
291 | } | |
292 | ||
293 | /** | |
294 | * Trace closed handler | |
295 | * | |
296 | * @param signal | |
297 | * Last opened trace was closed | |
298 | */ | |
299 | @TmfSignalHandler | |
300 | public void traceClosed(TmfTraceClosedSignal signal) { | |
301 | // Check if there is no more opened trace | |
302 | if (TmfTraceManager.getInstance().getActiveTrace() == null) { | |
303 | if (!getTableViewer().getTable().isDisposed()) { | |
304 | getTableViewer().setInput(null); | |
305 | refresh(); | |
306 | } | |
307 | } | |
308 | } | |
309 | } |