tmf: Mark TmfTraceManager @NonNullByDefault
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / views / statesystem / TmfStateSystemViewer.java
CommitLineData
17c73d10 1/*******************************************************************************
ed48dc75 2 * Copyright (c) 2014, 2016 École Polytechnique de Montréal and others.
17c73d10
GB
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 * Florian Wininger - Initial API and implementation
11 * Alexandre Montplaisir - Refactoring, performance tweaks
12 * Bernd Hufmann - Updated signal handling
13 * Marc-Andre Laperle - Add time zone preference
14 * Geneviève Bastien - Moved state system explorer to use the abstract tree viewer
7c246810 15 * Patrick Tasse - Refactoring
17c73d10
GB
16 *******************************************************************************/
17
2bdf0193 18package org.eclipse.tracecompass.tmf.ui.views.statesystem;
17c73d10
GB
19
20import java.util.ArrayList;
21import java.util.List;
22
23import org.eclipse.jdt.annotation.NonNull;
24import org.eclipse.jface.viewers.AbstractTreeViewer;
25import org.eclipse.jface.viewers.Viewer;
26import org.eclipse.jface.viewers.ViewerComparator;
17c73d10
GB
27import org.eclipse.swt.SWT;
28import org.eclipse.swt.graphics.Color;
29import org.eclipse.swt.widgets.Composite;
30import org.eclipse.swt.widgets.Display;
e894a508 31import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem;
e894a508
AM
32import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException;
33import org.eclipse.tracecompass.statesystem.core.exceptions.TimeRangeException;
34import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval;
35import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue;
860b39d1 36import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule;
2bdf0193
AM
37import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler;
38import org.eclipse.tracecompass.tmf.core.signal.TmfTimestampFormatUpdateSignal;
39import org.eclipse.tracecompass.tmf.core.statesystem.ITmfAnalysisModuleWithStateSystems;
2bdf0193
AM
40import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
41import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
42import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
21852dfa 43import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext;
2bdf0193
AM
44import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager;
45import org.eclipse.tracecompass.tmf.ui.viewers.tree.AbstractTmfTreeViewer;
46import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeColumnDataProvider;
47import org.eclipse.tracecompass.tmf.ui.viewers.tree.ITmfTreeViewerEntry;
48import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeColumnData;
49import org.eclipse.tracecompass.tmf.ui.viewers.tree.TmfTreeViewerEntry;
17c73d10
GB
50
51/**
52 * Displays the content of the state systems at the current time
53 *
54 * @author Florian Wininger
55 * @author Alexandre Montplaisir
56 * @author Geneviève Bastien
17c73d10
GB
57 */
58public class TmfStateSystemViewer extends AbstractTmfTreeViewer {
59
60 private static final String EMPTY_STRING = ""; //$NON-NLS-1$
17c73d10 61 private static final int DEFAULT_AUTOEXPAND = 2;
7c246810
PT
62 private boolean fFilterStatus = false;
63 private long fSelection = 0;
17c73d10
GB
64
65 /* Order of columns */
66 private static final int ATTRIBUTE_NAME_COL = 0;
67 private static final int QUARK_COL = 1;
68 private static final int VALUE_COL = 2;
69 private static final int TYPE_COL = 3;
70 private static final int START_TIME_COL = 4;
71 private static final int END_TIME_COL = 5;
72 private static final int ATTRIBUTE_FULLPATH_COL = 6;
73
74 /**
75 * Base class to provide the labels for the tree viewer. Views extending
76 * this class typically need to override the getColumnText method if they
77 * have more than one column to display
78 */
79 protected static class StateSystemTreeLabelProvider extends TreeLabelProvider {
80
81 @Override
82 public String getColumnText(Object element, int columnIndex) {
7c246810
PT
83 if (element instanceof StateEntry) {
84 StateEntry entry = (StateEntry) element;
17c73d10
GB
85 switch (columnIndex) {
86 case ATTRIBUTE_NAME_COL:
87 return entry.getName();
88 case QUARK_COL:
89 return String.valueOf(entry.getQuark());
90 case VALUE_COL:
91 return entry.getValue();
92 case TYPE_COL:
93 return entry.getType();
94 case START_TIME_COL:
95 return entry.getStartTime();
96 case END_TIME_COL:
97 return entry.getEndTime();
98 case ATTRIBUTE_FULLPATH_COL:
99 return entry.getFullPath();
100 default:
101 return EMPTY_STRING;
102 }
103 }
104 return super.getColumnText(element, columnIndex);
105 }
106
107 @Override
108 public Color getBackground(Object element, int columnIndex) {
7c246810
PT
109 if (element instanceof StateEntry) {
110 if (((StateEntry) element).isModified()) {
17c73d10
GB
111 return Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW);
112 }
113 }
114 return super.getBackground(element, columnIndex);
115 }
116 }
117
118 /**
119 * Constructor
120 *
121 * @param parent
122 * The parent containing this viewer
123 */
124 public TmfStateSystemViewer(Composite parent) {
125 super(parent, false);
126 this.setLabelProvider(new StateSystemTreeLabelProvider());
127 getTreeViewer().setAutoExpandLevel(DEFAULT_AUTOEXPAND);
128 }
129
130 @Override
131 protected ITmfTreeColumnDataProvider getColumnDataProvider() {
132 return new ITmfTreeColumnDataProvider() {
133
134 @Override
135 public List<TmfTreeColumnData> getColumnData() {
136 List<TmfTreeColumnData> columns = new ArrayList<>();
137 TmfTreeColumnData column = new TmfTreeColumnData(Messages.TreeNodeColumnLabel);
138 columns.add(column);
139 column.setComparator(new ViewerComparator() {
140 @Override
141 public int compare(Viewer viewer, Object e1, Object e2) {
142 TmfTreeViewerEntry n1 = (TmfTreeViewerEntry) e1;
143 TmfTreeViewerEntry n2 = (TmfTreeViewerEntry) e2;
144
145 return n1.getName().compareTo(n2.getName());
146 }
147 });
148 columns.add(new TmfTreeColumnData(Messages.QuarkColumnLabel));
149 columns.add(new TmfTreeColumnData(Messages.ValueColumnLabel));
150 columns.add(new TmfTreeColumnData(Messages.TypeColumnLabel));
151 columns.add(new TmfTreeColumnData(Messages.StartTimeColumLabel));
152 columns.add(new TmfTreeColumnData(Messages.EndTimeColumLabel));
153 columns.add(new TmfTreeColumnData(Messages.AttributePathColumnLabel));
154 return columns;
155 }
156
157 };
158 }
159
160 // ------------------------------------------------------------------------
161 // Operations
162 // ------------------------------------------------------------------------
163
164 @Override
59c8ff34 165 protected ITmfTreeViewerEntry updateElements(long start, long end, boolean selection) {
7c246810
PT
166
167 if (selection) {
168 fSelection = start;
169 } else {
21852dfa 170 TmfTraceContext ctx = TmfTraceManager.getInstance().getCurrentTraceContext();
16801c72 171 fSelection = ctx.getSelectionRange().getStartTime().toNanos();
7c246810
PT
172 }
173
17c73d10
GB
174 if (getTrace() == null) {
175 return null;
176 }
177
59c8ff34 178 ITmfTreeViewerEntry root = getInput();
17c73d10 179
7c246810
PT
180 if (root == null) {
181 root = createRoot();
182 } else if (fFilterStatus) {
183 clearStateSystemEntries(root);
17c73d10
GB
184 }
185
186 /*
7c246810
PT
187 * Update the values of the elements of the state systems at the
188 * selection start time
17c73d10 189 */
7c246810 190 boolean changed = updateStateSystemEntries(root, fSelection);
17c73d10 191
7c246810 192 return selection || changed ? root : null;
17c73d10
GB
193 }
194
7c246810 195 private ITmfTreeViewerEntry createRoot() {
59c8ff34 196 // 'Fake' root node
7c246810 197 TmfTreeViewerEntry rootEntry = new TmfTreeViewerEntry("root"); //$NON-NLS-1$
59c8ff34 198
0f8687b4 199 for (final ITmfTrace trace : TmfTraceManager.getTraceSetWithExperiment(getTrace())) {
bcd8d4b1 200 rootEntry.addChild(createTraceEntry(trace));
17c73d10 201 }
7c246810 202 return rootEntry;
17c73d10
GB
203 }
204
7c246810 205 private static TmfTreeViewerEntry createTraceEntry(ITmfTrace trace) {
17c73d10 206 TmfTreeViewerEntry traceEntry = new TmfTreeViewerEntry(trace.getName());
860b39d1
MK
207 Iterable<IAnalysisModule> modules = trace.getAnalysisModules();
208 for (IAnalysisModule module : modules) {
209 if (module instanceof ITmfAnalysisModuleWithStateSystems) {
210 ITmfAnalysisModuleWithStateSystems moduleWithStateSystem = (ITmfAnalysisModuleWithStateSystems) module;
211 /*
212 * Just schedule the module, the data will be filled when
213 * available
214 */
215 moduleWithStateSystem.schedule();
216 if (!moduleWithStateSystem.waitForInitialization()) {
217 continue;
218 }
219 for (ITmfStateSystem ss : moduleWithStateSystem.getStateSystems()) {
220 traceEntry.addChild(new StateSystemEntry(ss));
221 }
17c73d10
GB
222 }
223 }
224 return traceEntry;
225 }
226
7c246810
PT
227 private static void clearStateSystemEntries(ITmfTreeViewerEntry root) {
228 for (ITmfTreeViewerEntry traceEntry : root.getChildren()) {
229 for (ITmfTreeViewerEntry ssEntry : traceEntry.getChildren()) {
230 ssEntry.getChildren().clear();
231 }
232 }
17c73d10
GB
233 }
234
7c246810
PT
235 private boolean updateStateSystemEntries(ITmfTreeViewerEntry root, long timestamp) {
236 boolean changed = false;
237 for (ITmfTreeViewerEntry traceEntry : root.getChildren()) {
238 for (ITmfTreeViewerEntry ssEntry : traceEntry.getChildren()) {
239 StateSystemEntry stateSystemEntry = (StateSystemEntry) ssEntry;
240 ITmfStateSystem ss = stateSystemEntry.getSS();
241 try {
242 List<ITmfStateInterval> fullState = ss.queryFullState(timestamp);
243 changed |= updateStateEntries(ss, fullState, stateSystemEntry, -1, timestamp);
244 } catch (TimeRangeException e) {
245 markOutOfRange(stateSystemEntry);
246 changed = true;
247 } catch (StateSystemDisposedException e) {
248 /* Ignored */
249 }
250 }
17c73d10 251 }
7c246810 252 return changed;
17c73d10
GB
253 }
254
7c246810
PT
255 private boolean updateStateEntries(ITmfStateSystem ss, List<ITmfStateInterval> fullState, TmfTreeViewerEntry parent, int parentQuark, long timestamp) {
256 boolean changed = false;
ed48dc75
PT
257 for (int quark : ss.getSubAttributes(parentQuark, false)) {
258 if (quark >= fullState.size()) {
259 // attribute was created after the full state query
260 continue;
261 }
262 ITmfStateInterval interval = fullState.get(quark);
263 StateEntry stateEntry = findStateEntry(parent, quark);
264 if (stateEntry == null) {
265 boolean modified = fFilterStatus ?
266 interval.getStartTime() == timestamp :
267 !interval.getStateValue().isNull();
268 stateEntry = new StateEntry(ss.getAttributeName(quark), quark, ss.getFullAttributePath(quark),
269 interval.getStateValue(),
270 TmfTimestamp.fromNanos(interval.getStartTime()),
271 TmfTimestamp.fromNanos(interval.getEndTime()),
272 modified);
273
274 // update children first to know if parent is really needed
275 updateStateEntries(ss, fullState, stateEntry, quark, timestamp);
17c73d10 276
ed48dc75
PT
277 /*
278 * Add this entry to parent if filtering is off, or
279 * if the entry has children to display, or
280 * if there is a state change at the current timestamp
281 */
282 if (!fFilterStatus || stateEntry.hasChildren() || interval.getStartTime() == timestamp) {
283 parent.addChild(stateEntry);
284 changed = true;
17c73d10 285 }
ed48dc75
PT
286 } else {
287 stateEntry.update(interval.getStateValue(),
288 TmfTimestamp.fromNanos(interval.getStartTime()),
289 TmfTimestamp.fromNanos(interval.getEndTime()));
17c73d10 290
ed48dc75
PT
291 // update children recursively
292 updateStateEntries(ss, fullState, stateEntry, quark, timestamp);
7c246810 293 }
ed48dc75 294
17c73d10 295 }
7c246810 296 return changed;
17c73d10
GB
297 }
298
7c246810
PT
299 private static StateEntry findStateEntry(TmfTreeViewerEntry parent, int quark) {
300 for (ITmfTreeViewerEntry child : parent.getChildren()) {
301 StateEntry stateEntry = (StateEntry) child;
302 if (stateEntry.getQuark() == quark) {
303 return stateEntry;
17c73d10
GB
304 }
305 }
7c246810 306 return null;
17c73d10 307 }
17c73d10
GB
308 /**
309 * Set the entries as out of range
310 */
7c246810
PT
311 private static void markOutOfRange(ITmfTreeViewerEntry parent) {
312 for (ITmfTreeViewerEntry entry : parent.getChildren()) {
313 if (entry instanceof StateEntry) {
314 ((StateEntry) entry).setOutOfRange();
17c73d10
GB
315
316 /* Update this node's children recursively */
317 markOutOfRange(entry);
318 }
319 }
320 }
321
322 /**
323 * Set the filter status of the viewer. By default, all entries of all state
324 * system are present, and the values that changed since last refresh are
325 * shown in yellow. When the filter status is true, only the entries with
326 * values modified at current time are displayed.
327 */
328 public void changeFilterStatus() {
329 fFilterStatus = !fFilterStatus;
330 if (fFilterStatus) {
331 getTreeViewer().setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
332 } else {
333 getTreeViewer().setAutoExpandLevel(DEFAULT_AUTOEXPAND);
334 clearContent();
335 }
336 updateContent(getSelectionBeginTime(), getSelectionEndTime(), true);
337 }
338
339 /**
340 * Update the display to use the updated timestamp format
341 *
342 * @param signal
343 * the incoming signal
344 */
345 @TmfSignalHandler
346 public void timestampFormatUpdated(TmfTimestampFormatUpdateSignal signal) {
347 updateContent(getSelectionBeginTime(), getSelectionEndTime(), true);
348 }
349
7c246810
PT
350 private static class StateSystemEntry extends TmfTreeViewerEntry {
351 private final @NonNull ITmfStateSystem fSS;
352
353 public StateSystemEntry(@NonNull ITmfStateSystem ss) {
354 super(ss.getSSID());
355 fSS = ss;
356 }
357
358 public @NonNull ITmfStateSystem getSS() {
359 return fSS;
360 }
361 }
362
363 private class StateEntry extends TmfTreeViewerEntry {
17c73d10
GB
364
365 private final int fQuark;
366 private final String fFullPath;
b2c971ec
MK
367 private @NonNull ITmfTimestamp fStart;
368 private @NonNull ITmfTimestamp fEnd;
17c73d10 369 private ITmfStateValue fValue;
7c246810 370 private boolean fModified;
17c73d10
GB
371 private boolean fOutOfRange = false;
372
b2c971ec 373 public StateEntry(String name, int quark, String fullPath, ITmfStateValue value, @NonNull ITmfTimestamp start, @NonNull ITmfTimestamp end, boolean modified) {
17c73d10
GB
374 super(name);
375 fQuark = quark;
376 fFullPath = fullPath;
377 fStart = start;
378 fEnd = end;
379 fValue = value;
7c246810 380 fModified = modified;
17c73d10
GB
381 }
382
383 public int getQuark() {
384 return fQuark;
385 }
386
387 public String getFullPath() {
388 return fFullPath;
389 }
390
391 public String getStartTime() {
392 if (fOutOfRange) {
393 return EMPTY_STRING;
394 }
395 return fStart.toString();
396 }
397
398 public String getEndTime() {
399 if (fOutOfRange) {
400 return EMPTY_STRING;
401 }
402 return fEnd.toString();
403 }
404
405 public String getValue() {
406 if (fOutOfRange) {
407 return Messages.OutOfRangeMsg;
408 }
409 switch (fValue.getType()) {
410 case INTEGER:
411 case LONG:
412 case DOUBLE:
413 case STRING:
7ef85bff 414 case CUSTOM:
17c73d10
GB
415 return fValue.toString();
416 case NULL:
417 default:
418 return EMPTY_STRING;
419 }
420 }
421
422 public String getType() {
423 if (fOutOfRange) {
424 return EMPTY_STRING;
425 }
426 switch (fValue.getType()) {
427 case INTEGER:
428 return Messages.TypeInteger;
429 case LONG:
430 return Messages.TypeLong;
431 case DOUBLE:
432 return Messages.TypeDouble;
433 case STRING:
434 return Messages.TypeString;
7ef85bff
GB
435 case CUSTOM:
436 return Messages.TypeCustom;
17c73d10
GB
437 case NULL:
438 default:
439 return EMPTY_STRING;
440 }
441 }
442
443 public boolean isModified() {
444 return fModified;
445 }
446
b2c971ec 447 public void update(ITmfStateValue value, @NonNull ITmfTimestamp start, @NonNull ITmfTimestamp end) {
17c73d10
GB
448 fModified = false;
449 fOutOfRange = false;
450 if (!start.equals(fStart)) {
451 fModified = true;
452 fStart = start;
453 fEnd = end;
454 fValue = value;
455 }
456 }
457
458 public void setOutOfRange() {
459 fModified = false;
460 fOutOfRange = true;
461 }
462 }
463}
This page took 0.098551 seconds and 5 git commands to generate.