gdbtrace: Use preference for gdb path
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / viewers / tree / AbstractTmfTreeViewer.java
CommitLineData
c0188b25
GB
1/*******************************************************************************
2 * Copyright (c) 2014 École Polytechnique de Montréal
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 * Geneviève Bastien - Initial API and implementation
11 *******************************************************************************/
12
13package org.eclipse.linuxtools.tmf.ui.viewers.tree;
14
15import java.util.List;
16
17import org.eclipse.jface.viewers.AbstractTreeViewer;
18import org.eclipse.jface.viewers.IBaseLabelProvider;
19import org.eclipse.jface.viewers.ILabelProviderListener;
20import org.eclipse.jface.viewers.ISelectionChangedListener;
21import org.eclipse.jface.viewers.ITableColorProvider;
22import org.eclipse.jface.viewers.ITableFontProvider;
23import org.eclipse.jface.viewers.ITableLabelProvider;
24import org.eclipse.jface.viewers.ITreeContentProvider;
25import org.eclipse.jface.viewers.TreeViewer;
26import org.eclipse.jface.viewers.Viewer;
27import org.eclipse.linuxtools.tmf.core.signal.TmfRangeSynchSignal;
28import org.eclipse.linuxtools.tmf.core.signal.TmfSignalHandler;
29import org.eclipse.linuxtools.tmf.core.signal.TmfTimeSynchSignal;
30import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
31import org.eclipse.linuxtools.tmf.ui.viewers.TmfTimeViewer;
32import org.eclipse.swt.SWT;
33import org.eclipse.swt.graphics.Color;
34import org.eclipse.swt.graphics.Font;
35import org.eclipse.swt.graphics.Image;
36import org.eclipse.swt.widgets.Composite;
37import org.eclipse.swt.widgets.Control;
38import org.eclipse.swt.widgets.Display;
39import org.eclipse.swt.widgets.Event;
40import org.eclipse.swt.widgets.Listener;
41import org.eclipse.swt.widgets.Tree;
42import org.eclipse.swt.widgets.TreeColumn;
43
44/**
45 * Abstract class for viewers who will display data using a TreeViewer. It
46 * automatically synchronizes with time information of the UI. It also
47 * implements some common functionalities for all tree viewer, such as managing
48 * the column data, content initialization and update. The viewer implementing
49 * this does not have to worry about whether some code runs in the UI thread or
50 * not.
51 *
52 * @author Geneviève Bastien
53 * @since 3.0
54 */
55public abstract class AbstractTmfTreeViewer extends TmfTimeViewer {
56
57 private final TreeViewer fTreeViewer;
58
59 // ------------------------------------------------------------------------
60 // Internal classes
61 // ------------------------------------------------------------------------
62
63 /* The elements of the tree viewer are of type ITmfTreeViewerEntry */
64 private class TreeContentProvider implements ITreeContentProvider {
65
66 @Override
67 public void dispose() {
68 }
69
70 @Override
71 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
72 }
73
74 @Override
75 public Object[] getElements(Object inputElement) {
76 if (inputElement != null) {
77 try {
78 return ((List<?>) inputElement).toArray(new ITmfTreeViewerEntry[0]);
79 } catch (ClassCastException e) {
80 }
81 }
82 return new ITmfTreeViewerEntry[0];
83 }
84
85 @Override
86 public Object[] getChildren(Object parentElement) {
87 ITmfTreeViewerEntry entry = (ITmfTreeViewerEntry) parentElement;
88 List<? extends ITmfTreeViewerEntry> children = entry.getChildren();
89 return children.toArray(new ITmfTreeViewerEntry[children.size()]);
90 }
91
92 @Override
93 public Object getParent(Object element) {
94 ITmfTreeViewerEntry entry = (ITmfTreeViewerEntry) element;
95 return entry.getParent();
96 }
97
98 @Override
99 public boolean hasChildren(Object element) {
100 ITmfTreeViewerEntry entry = (ITmfTreeViewerEntry) element;
101 return entry.hasChildren();
102 }
103
104 }
105
106 /**
107 * Base class to provide the labels for the tree viewer. Views extending
108 * this class typically need to override the getColumnText method if they
109 * have more than one column to display. It also allows to change the font
110 * and colors of the cells.
111 */
112 protected static class TreeLabelProvider implements ITableLabelProvider, ITableFontProvider, ITableColorProvider {
113
114 @Override
115 public void addListener(ILabelProviderListener listener) {
116 }
117
118 @Override
119 public void dispose() {
120 }
121
122 @Override
123 public boolean isLabelProperty(Object element, String property) {
124 return false;
125 }
126
127 @Override
128 public void removeListener(ILabelProviderListener listener) {
129 }
130
131 @Override
132 public Image getColumnImage(Object element, int columnIndex) {
133 return null;
134 }
135
136 @Override
137 public String getColumnText(Object element, int columnIndex) {
138 if ((element instanceof ITmfTreeViewerEntry) && (columnIndex == 0)) {
139 ITmfTreeViewerEntry entry = (ITmfTreeViewerEntry) element;
140 return entry.getName();
141 }
142 return new String();
143 }
144
145 @Override
146 public Color getForeground(Object element, int columnIndex) {
147 return Display.getCurrent().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
148 }
149
150 @Override
151 public Color getBackground(Object element, int columnIndex) {
152 return Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
153 }
154
155 @Override
156 public Font getFont(Object element, int columnIndex) {
157 return null;
158 }
159
160 }
161
162 // ------------------------------------------------------------------------
163 // Constructors and initialization methods
164 // ------------------------------------------------------------------------
165
166 /**
167 * Constructor
168 *
169 * @param parent
170 * The parent composite that holds this viewer
171 * @param allowMultiSelect
172 * Whether multiple selections are allowed
173 */
174 public AbstractTmfTreeViewer(Composite parent, boolean allowMultiSelect) {
175 super(parent);
176
177 int flags = SWT.FULL_SELECTION | SWT.H_SCROLL;
178 if (allowMultiSelect) {
179 flags |= SWT.MULTI;
180 }
181
182 /* Build the tree viewer part of the view */
183 fTreeViewer = new TreeViewer(parent, flags);
184 fTreeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
185 final Tree tree = fTreeViewer.getTree();
186 tree.setHeaderVisible(true);
187 tree.setLinesVisible(true);
188 fTreeViewer.setContentProvider(new TreeContentProvider());
189 fTreeViewer.setLabelProvider(new TreeLabelProvider());
190 List<TmfTreeColumnData> columns = getColumnDataProvider().getColumnData();
191 this.setTreeColumns(columns);
192 }
193
194 /**
195 * Get the column data provider that will contain the list of columns to be
196 * part of this viewer. It is called once during the constructor.
197 *
198 * @return The tree column data provider for this viewer.
199 */
200 protected abstract ITmfTreeColumnDataProvider getColumnDataProvider();
201
202 /**
203 * Sets the tree columns for this tree viewer
204 *
205 * @param columns
206 * The tree column data
207 */
208 public void setTreeColumns(final List<TmfTreeColumnData> columns) {
209 boolean hasPercentProvider = false;
210 for (final TmfTreeColumnData columnData : columns) {
211 columnData.createColumn(fTreeViewer);
212 hasPercentProvider |= (columnData.getPercentageProvider() != null);
213 }
214
215 if (hasPercentProvider) {
216 /*
217 * Handler that will draw bar charts in the cell using a percentage
218 * value.
219 */
220 fTreeViewer.getTree().addListener(SWT.EraseItem, new Listener() {
221 @Override
222 public void handleEvent(Event event) {
223 if (columns.get(event.index).getPercentageProvider() != null) {
224
225 double percentage = columns.get(event.index).getPercentageProvider().getPercentage(event.item.getData());
226 if (percentage == 0) { // No bar to draw
227 return;
228 }
229
230 if ((event.detail & SWT.SELECTED) > 0) {
231 /*
232 * The item is selected. Draw our own background to
233 * avoid overwriting the bar.
234 */
235 event.gc.fillRectangle(event.x, event.y, event.width, event.height);
236 event.detail &= ~SWT.SELECTED;
237 }
238
239 int barWidth = (int) ((fTreeViewer.getTree().getColumn(event.index).getWidth() - 8) * percentage);
240 int oldAlpha = event.gc.getAlpha();
241 Color oldForeground = event.gc.getForeground();
242 Color oldBackground = event.gc.getBackground();
243 /*
244 * Draws a transparent gradient rectangle from the color
245 * of foreground and background.
246 */
247 event.gc.setAlpha(64);
248 event.gc.setForeground(event.item.getDisplay().getSystemColor(SWT.COLOR_BLUE));
249 event.gc.setBackground(event.item.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
250 event.gc.fillGradientRectangle(event.x, event.y, barWidth, event.height, true);
251 event.gc.drawRectangle(event.x, event.y, barWidth, event.height);
252 /* Restores old values */
253 event.gc.setForeground(oldForeground);
254 event.gc.setBackground(oldBackground);
255 event.gc.setAlpha(oldAlpha);
256 event.detail &= ~SWT.BACKGROUND;
257 }
258 }
259 });
260 }
261 }
262
263 /**
264 * Set the label provider that will fill the columns of the tree viewer
265 *
266 * @param labelProvider
267 * The label provider to fill the columns
268 */
269 protected void setLabelProvider(IBaseLabelProvider labelProvider) {
270 fTreeViewer.setLabelProvider(labelProvider);
271 }
272
273 /**
274 * Get the tree viewer object
275 *
276 * @return The tree viewer object displayed by this viewer
277 */
278 protected TreeViewer getTreeViewer() {
279 return fTreeViewer;
280 }
281
282 // ------------------------------------------------------------------------
283 // ITmfViewer
284 // ------------------------------------------------------------------------
285
286 @Override
287 public Control getControl() {
288 return fTreeViewer.getControl();
289 }
290
291 @Override
292 public void refresh() {
293 Tree tree = fTreeViewer.getTree();
294 tree.setRedraw(false);
295 fTreeViewer.refresh();
296 fTreeViewer.expandAll();
297 tree.setRedraw(true);
298 }
299
300 @Override
301 public void loadTrace(ITmfTrace trace) {
302 super.loadTrace(trace);
303 Thread thread = new Thread() {
304 @Override
305 public void run() {
306 initializeDataSource();
307 Display.getDefault().asyncExec(new Runnable() {
308 @Override
309 public void run() {
310 clearContent();
311 updateContent(getWindowStartTime(), getWindowEndTime(), false);
312 }
313 });
314 }
315 };
316 thread.start();
317 }
318
319 // ------------------------------------------------------------------------
320 // Operations
321 // ------------------------------------------------------------------------
322
323 /**
324 * Add a selection listener to the tree viewer. This will be called when the
325 * selection changes and contain all the selected items.
326 *
327 * The selection change listener can be used like this:
328 *
329 * <pre>
330 * getTreeViewer().addSelectionChangeListener(new ISelectionChangedListener() {
331 * &#064;Override
332 * public void selectionChanged(SelectionChangedEvent event) {
333 * if (event.getSelection() instanceof IStructuredSelection) {
334 * Object selection = ((IStructuredSelection) event.getSelection()).getFirstElement();
335 * if (selection instanceof ITmfTreeViewerEntry) {
336 * // Do something
337 * }
338 * }
339 * }
340 * });
341 * </pre>
342 *
343 * @param listener
344 * The {@link ISelectionChangedListener}
345 */
346 public void addSelectionChangeListener(ISelectionChangedListener listener) {
347 fTreeViewer.addSelectionChangedListener(listener);
348 }
349
350 /**
351 * Method called when the trace is loaded, to initialize any data once the
352 * trace has been set, but before the first call to update the content of
353 * the viewer.
354 */
355 protected void initializeDataSource() {
356
357 }
358
359 /**
360 * Clears the current content of the viewer.
361 */
362 protected void clearContent() {
363 fTreeViewer.setInput(null);
364 }
365
366 /**
367 * Requests an update of the viewer's content in a given time range or
368 * selection time range. An extra parameter defines whether these times
369 * correspond to the selection or the visible range, as the viewer may
370 * update differently in those cases.
371 *
372 * @param start
373 * The start time of the requested content
374 * @param end
375 * The end time of the requested content
376 * @param isSelection
377 * <code>true</code> if this time range is for a selection,
378 * <code>false</code> for the visible time range
379 */
380 protected void updateContent(final long start, final long end, final boolean isSelection) {
381 Thread thread = new Thread() {
382 @Override
383 public void run() {
384 final List<ITmfTreeViewerEntry> entries = updateElements(start, end, isSelection);
385 /* Set the input in main thread only if it didn't change */
386 if (entries != null) {
387 Display.getDefault().asyncExec(new Runnable() {
388 @Override
389 public void run() {
390 if (entries != fTreeViewer.getInput()) {
391 fTreeViewer.setInput(entries);
392 } else {
393 fTreeViewer.refresh();
394 }
395 // FIXME should add a bit of padding
396 for (TreeColumn column : fTreeViewer.getTree().getColumns()) {
397 column.pack();
398 }
399 }
400 });
401 }
402 }
403 };
404 thread.start();
405 }
406
407 /**
408 * Update the entries to the given start/end time. An extra parameter
409 * defines whether these times correspond to the selection or the visible
410 * range, as the viewer may update differently in those cases. If no update
411 * is necessary, the method should return <code>null</code>. To empty the
412 * tree, an empty list should be returned.
413 *
414 * This method is not called in the UI thread when using the default viewer
415 * content update. Resource-intensive calculations here should not block the
416 * UI.
417 *
418 * @param start
419 * The start time of the requested content
420 * @param end
421 * The end time of the requested content
422 * @param isSelection
423 * <code>true</code> if this time range is for a selection,
424 * <code>false</code> for the visible time range
425 * @return The list of entries to display or <code>null</code> if no update
426 * necessary
427 */
428 protected abstract List<ITmfTreeViewerEntry> updateElements(long start, long end, boolean isSelection);
429
430 /**
431 * Get the current input displayed by the viewer
432 *
433 * @return The input of the tree viewer
434 */
435 protected Object getInput() {
436 return fTreeViewer.getInput();
437 }
438
439 // ------------------------------------------------------------------------
440 // Signal Handler
441 // ------------------------------------------------------------------------
442
443 /**
444 * Signal handler for handling of the time synch signal. The times
445 * correspond to the selection by the user, not the visible time range.
446 *
447 * @param signal
448 * The time synch signal {@link TmfTimeSynchSignal}
449 */
450 @Override
451 @TmfSignalHandler
452 public void selectionRangeUpdated(TmfTimeSynchSignal signal) {
453 super.selectionRangeUpdated(signal);
454 if ((signal.getSource() != this) && (getTrace() != null)) {
455 updateContent(this.getSelectionBeginTime(), this.getSelectionEndTime(), true);
456 }
457 }
458
459 /**
460 * Signal handler for handling of the time range synch signal. This time
461 * range is the visible zone of the view.
462 *
463 * @param signal
464 * The time range synch signal {@link TmfRangeSynchSignal}
465 */
466 @Override
467 @TmfSignalHandler
468 public void timeRangeUpdated(TmfRangeSynchSignal signal) {
469 super.timeRangeUpdated(signal);
470 updateContent(this.getWindowStartTime(), this.getWindowEndTime(), false);
471 }
472
473}
This page took 0.043536 seconds and 5 git commands to generate.