Bug 378401: Implementation of time graph widget.
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / widgets / timegraph / TimeGraphCombo.java
1 /*******************************************************************************
2 * Copyright (c) 2012 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 * Patrick Tasse - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.linuxtools.tmf.ui.widgets.timegraph;
14
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.HashMap;
18
19 import org.eclipse.jface.viewers.ILabelProviderListener;
20 import org.eclipse.jface.viewers.ISelectionChangedListener;
21 import org.eclipse.jface.viewers.IStructuredSelection;
22 import org.eclipse.jface.viewers.ITableLabelProvider;
23 import org.eclipse.jface.viewers.ITreeContentProvider;
24 import org.eclipse.jface.viewers.ITreeViewerListener;
25 import org.eclipse.jface.viewers.SelectionChangedEvent;
26 import org.eclipse.jface.viewers.StructuredSelection;
27 import org.eclipse.jface.viewers.TreeExpansionEvent;
28 import org.eclipse.jface.viewers.TreeViewer;
29 import org.eclipse.jface.viewers.Viewer;
30 import org.eclipse.linuxtools.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
31 import org.eclipse.swt.SWT;
32 import org.eclipse.swt.custom.SashForm;
33 import org.eclipse.swt.events.ControlAdapter;
34 import org.eclipse.swt.events.ControlEvent;
35 import org.eclipse.swt.events.MouseEvent;
36 import org.eclipse.swt.events.MouseWheelListener;
37 import org.eclipse.swt.events.PaintEvent;
38 import org.eclipse.swt.events.PaintListener;
39 import org.eclipse.swt.events.SelectionAdapter;
40 import org.eclipse.swt.events.SelectionEvent;
41 import org.eclipse.swt.graphics.Image;
42 import org.eclipse.swt.graphics.Point;
43 import org.eclipse.swt.layout.FillLayout;
44 import org.eclipse.swt.widgets.Composite;
45 import org.eclipse.swt.widgets.Display;
46 import org.eclipse.swt.widgets.Event;
47 import org.eclipse.swt.widgets.Listener;
48 import org.eclipse.swt.widgets.Slider;
49 import org.eclipse.swt.widgets.Tree;
50 import org.eclipse.swt.widgets.TreeColumn;
51 import org.eclipse.swt.widgets.TreeItem;
52
53 public class TimeGraphCombo extends Composite {
54
55 // ------------------------------------------------------------------------
56 // Constants
57 // ------------------------------------------------------------------------
58
59 private static final Object FILLER = new Object();
60
61 // ------------------------------------------------------------------------
62 // Fields
63 // ------------------------------------------------------------------------
64
65 // The tree viewer
66 private TreeViewer fTreeViewer;
67
68 // The time viewer
69 private TimeGraphViewer fTimeGraphViewer;
70
71 // The selection listener map
72 private HashMap<ITimeGraphSelectionListener, SelectionListenerWrapper> fSelectionListenerMap = new HashMap<ITimeGraphSelectionListener, SelectionListenerWrapper>();
73
74 // Flag to block the tree selection changed listener when triggered by the time graph combo
75 private boolean fInhibitTreeSelection = false;
76
77 // Number of filler rows used by the tree content provider
78 private int fNumFillerRows;
79
80 // Calculated item height for Linux workaround
81 private int fLinuxItemHeight = 0;
82
83 // ------------------------------------------------------------------------
84 // Classes
85 // ------------------------------------------------------------------------
86
87 /**
88 * The TreeContentProviderWrapper is used to insert filler items after
89 * the elements of the tree's real content provider.
90 */
91 private class TreeContentProviderWrapper implements ITreeContentProvider {
92 private ITreeContentProvider contentProvider;
93
94 public TreeContentProviderWrapper(ITreeContentProvider contentProvider) {
95 this.contentProvider = contentProvider;
96 }
97
98 @Override
99 public void dispose() {
100 contentProvider.dispose();
101 }
102
103 @Override
104 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
105 contentProvider.inputChanged(viewer, oldInput, newInput);
106 }
107
108 @Override
109 public Object[] getElements(Object inputElement) {
110 Object[] elements = contentProvider.getElements(inputElement);
111 // add filler elements to ensure alignment with time analysis viewer
112 Object[] oElements = Arrays.copyOf(elements, elements.length + fNumFillerRows, new Object[0].getClass());
113 for (int i = 0; i < fNumFillerRows; i++) {
114 oElements[elements.length + i] = FILLER;
115 }
116 return oElements;
117 }
118
119 @Override
120 public Object[] getChildren(Object parentElement) {
121 if (parentElement instanceof ITimeGraphEntry) {
122 return contentProvider.getChildren(parentElement);
123 } else {
124 return new Object[0];
125 }
126 }
127
128 @Override
129 public Object getParent(Object element) {
130 if (element instanceof ITimeGraphEntry) {
131 return contentProvider.getParent(element);
132 } else {
133 return null;
134 }
135 }
136
137 @Override
138 public boolean hasChildren(Object element) {
139 if (element instanceof ITimeGraphEntry) {
140 return contentProvider.hasChildren(element);
141 } else {
142 return false;
143 }
144 }
145 }
146
147 /**
148 * The TreeLabelProviderWrapper is used to intercept the filler items
149 * from the calls to the tree's real label provider.
150 */
151 private class TreeLabelProviderWrapper implements ITableLabelProvider {
152 private ITableLabelProvider labelProvider;
153
154 public TreeLabelProviderWrapper(ITableLabelProvider labelProvider) {
155 this.labelProvider = labelProvider;
156 }
157
158 @Override
159 public void addListener(ILabelProviderListener listener) {
160 labelProvider.addListener(listener);
161 }
162
163 @Override
164 public void dispose() {
165 labelProvider.dispose();
166 }
167
168 @Override
169 public boolean isLabelProperty(Object element, String property) {
170 if (element instanceof ITimeGraphEntry) {
171 return labelProvider.isLabelProperty(element, property);
172 } else {
173 return false;
174 }
175 }
176
177 @Override
178 public void removeListener(ILabelProviderListener listener) {
179 labelProvider.removeListener(listener);
180 }
181
182 @Override
183 public Image getColumnImage(Object element, int columnIndex) {
184 if (element instanceof ITimeGraphEntry) {
185 return labelProvider.getColumnImage(element, columnIndex);
186 } else {
187 return null;
188 }
189 }
190
191 @Override
192 public String getColumnText(Object element, int columnIndex) {
193 if (element instanceof ITimeGraphEntry) {
194 return labelProvider.getColumnText(element, columnIndex);
195 } else {
196 return null;
197 }
198 }
199
200 }
201
202 /**
203 * The SelectionListenerWrapper is used to intercept the filler items from
204 * the time graph combo's real selection listener, and to prevent double
205 * notifications from being sent when selection changes in both tree and
206 * time graph at the same time.
207 */
208 private class SelectionListenerWrapper implements ISelectionChangedListener, ITimeGraphSelectionListener {
209 private ITimeGraphSelectionListener listener;
210 private ITimeGraphEntry selection = null;
211
212 public SelectionListenerWrapper(ITimeGraphSelectionListener listener) {
213 this.listener = listener;
214 }
215
216 @Override
217 public void selectionChanged(SelectionChangedEvent event) {
218 if (fInhibitTreeSelection) {
219 return;
220 }
221 Object element = ((IStructuredSelection) event.getSelection()).getFirstElement();
222 if (element instanceof ITimeGraphEntry) {
223 ITimeGraphEntry entry = (ITimeGraphEntry) element;
224 if (entry != selection) {
225 selection = entry;
226 listener.selectionChanged(new TimeGraphSelectionEvent(event.getSource(), selection));
227 }
228 }
229 }
230
231 @Override
232 public void selectionChanged(TimeGraphSelectionEvent event) {
233 ITimeGraphEntry entry = event.getSelection();
234 if (entry != selection) {
235 selection = entry;
236 listener.selectionChanged(new TimeGraphSelectionEvent(event.getSource(), selection));
237 }
238 }
239 }
240
241 // ------------------------------------------------------------------------
242 // Constructors
243 // ------------------------------------------------------------------------
244
245 /**
246 * Constructs a new instance of this class given its parent
247 * and a style value describing its behavior and appearance.
248 *
249 * @param parent a widget which will be the parent of the new instance (cannot be null)
250 * @param style the style of widget to construct
251 */
252 public TimeGraphCombo(Composite parent, int style) {
253 super(parent, style);
254 setLayout(new FillLayout());
255
256 final SashForm sash = new SashForm(this, SWT.NONE);
257
258 fTreeViewer = new TreeViewer(sash, SWT.FULL_SELECTION | SWT.H_SCROLL);
259 final Tree tree = fTreeViewer.getTree();
260 tree.setHeaderVisible(true);
261 tree.setLinesVisible(true);
262
263 fTimeGraphViewer = new TimeGraphViewer(sash, SWT.NONE);
264 fTimeGraphViewer.setItemHeight(getItemHeight(tree));
265 fTimeGraphViewer.setHeaderHeight(tree.getHeaderHeight());
266 fTimeGraphViewer.setBorderWidth(tree.getBorderWidth());
267 fTimeGraphViewer.setNameWidthPref(0);
268
269 // Feature in Windows. The tree vertical bar reappears when
270 // the control is resized so we need to hide it again.
271 // Bug in Linux. The tree header height is 0 in constructor,
272 // so we need to reset it later when the control is resized.
273 tree.addControlListener(new ControlAdapter() {
274 @Override
275 public void controlResized(ControlEvent e) {
276 fTreeViewer.getTree().getVerticalBar().setEnabled(false);
277 fTreeViewer.getTree().getVerticalBar().setVisible(false);
278 fTimeGraphViewer.setHeaderHeight(tree.getHeaderHeight());
279 }
280 });
281
282 // ensure synchronization of expanded items between tree and time graph
283 fTreeViewer.addTreeListener(new ITreeViewerListener() {
284 @Override
285 public void treeCollapsed(TreeExpansionEvent event) {
286 fTimeGraphViewer.setExpandedState((ITimeGraphEntry) event.getElement(), false);
287 }
288
289 @Override
290 public void treeExpanded(TreeExpansionEvent event) {
291 fTimeGraphViewer.setExpandedState((ITimeGraphEntry) event.getElement(), true);
292 }
293 });
294
295 // ensure synchronization of expanded items between tree and time graph
296 fTimeGraphViewer.addTreeListener(new ITimeGraphTreeListener() {
297 @Override
298 public void treeCollapsed(TimeGraphTreeExpansionEvent event) {
299 fTreeViewer.setExpandedState(event.getEntry(), false);
300 }
301
302 @Override
303 public void treeExpanded(TimeGraphTreeExpansionEvent event) {
304 fTreeViewer.setExpandedState(event.getEntry(), true);
305 }
306 });
307
308 // prevent mouse button from selecting a filler tree item
309 tree.addListener(SWT.MouseDown, new Listener() {
310 @Override
311 public void handleEvent(Event event) {
312 TreeItem treeItem = tree.getItem(new Point(event.x, event.y));
313 if (treeItem == null || treeItem.getData() == FILLER) {
314 event.doit = false;
315 ArrayList<TreeItem> treeItems = getVisibleExpandedItems(tree);
316 if (treeItems.size() == 0) {
317 fTreeViewer.setSelection(new StructuredSelection());
318 fTimeGraphViewer.setSelection(null);
319 return;
320 }
321 // this prevents from scrolling up when selecting
322 // the partially visible tree item at the bottom
323 tree.select(treeItems.get(treeItems.size() - 1));
324 fTreeViewer.setSelection(new StructuredSelection());
325 fTimeGraphViewer.setSelection(null);
326 }
327 }
328 });
329
330 // prevent mouse wheel from scrolling down into filler tree items
331 tree.addListener(SWT.MouseWheel, new Listener() {
332 @Override
333 public void handleEvent(Event event) {
334 event.doit = false;
335 Slider scrollBar = fTimeGraphViewer.getVerticalBar();
336 fTimeGraphViewer.setTopIndex(scrollBar.getSelection() - event.count);
337 ArrayList<TreeItem> treeItems = getVisibleExpandedItems(tree);
338 if (treeItems.size() == 0) {
339 return;
340 }
341 TreeItem treeItem = treeItems.get(fTimeGraphViewer.getTopIndex());
342 tree.setTopItem(treeItem);
343 }
344 });
345
346 // prevent key stroke from selecting a filler tree item
347 tree.addListener(SWT.KeyDown, new Listener() {
348 @Override
349 public void handleEvent(Event event) {
350 ArrayList<TreeItem> treeItems = getVisibleExpandedItems(tree);
351 if (treeItems.size() == 0) {
352 fTreeViewer.setSelection(new StructuredSelection());
353 event.doit = false;
354 return;
355 }
356 if (event.keyCode == SWT.ARROW_DOWN) {
357 int index = Math.min(fTimeGraphViewer.getSelectionIndex() + 1, treeItems.size() - 1);
358 fTimeGraphViewer.setSelection((ITimeGraphEntry) treeItems.get(index).getData());
359 event.doit = false;
360 } else if (event.keyCode == SWT.PAGE_DOWN) {
361 int height = tree.getSize().y - tree.getHeaderHeight() - tree.getHorizontalBar().getSize().y;
362 int countPerPage = height / getItemHeight(tree);
363 int index = Math.min(fTimeGraphViewer.getSelectionIndex() + countPerPage - 1, treeItems.size() - 1);
364 fTimeGraphViewer.setSelection((ITimeGraphEntry) treeItems.get(index).getData());
365 event.doit = false;
366 } else if (event.keyCode == SWT.END) {
367 fTimeGraphViewer.setSelection((ITimeGraphEntry) treeItems.get(treeItems.size() - 1).getData());
368 event.doit = false;
369 }
370 TreeItem treeItem = treeItems.get(fTimeGraphViewer.getTopIndex());
371 tree.setTopItem(treeItem);
372 if (fTimeGraphViewer.getSelectionIndex() >= 0) {
373 fTreeViewer.setSelection(new StructuredSelection(fTimeGraphViewer.getSelection()));
374 } else {
375 fTreeViewer.setSelection(new StructuredSelection());
376 }
377 }
378 });
379
380 // ensure alignment of top item between tree and time graph
381 fTimeGraphViewer.getTimeGraphControl().addControlListener(new ControlAdapter() {
382 @Override
383 public void controlResized(ControlEvent e) {
384 ArrayList<TreeItem> treeItems = getVisibleExpandedItems(tree);
385 if (treeItems.size() == 0) {
386 return;
387 }
388 TreeItem treeItem = treeItems.get(fTimeGraphViewer.getTopIndex());
389 tree.setTopItem(treeItem);
390 }
391 });
392
393 // ensure synchronization of selected item between tree and time graph
394 fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
395 @Override
396 public void selectionChanged(SelectionChangedEvent event) {
397 if (fInhibitTreeSelection) {
398 return;
399 }
400 if (event.getSelection() instanceof IStructuredSelection) {
401 Object selection = ((IStructuredSelection) event.getSelection()).getFirstElement();
402 if (selection instanceof ITimeGraphEntry) {
403 fTimeGraphViewer.setSelection((ITimeGraphEntry) selection);
404 }
405 ArrayList<TreeItem> treeItems = getVisibleExpandedItems(tree);
406 if (treeItems.size() == 0) {
407 return;
408 }
409 TreeItem treeItem = treeItems.get(fTimeGraphViewer.getTopIndex());
410 tree.setTopItem(treeItem);
411 }
412 }
413 });
414
415 // ensure synchronization of selected item between tree and time graph
416 fTimeGraphViewer.addSelectionListener(new ITimeGraphSelectionListener() {
417 @Override
418 public void selectionChanged(TimeGraphSelectionEvent event) {
419 ITimeGraphEntry entry = fTimeGraphViewer.getSelection();
420 fInhibitTreeSelection = true; // block the tree selection changed listener
421 if (entry != null) {
422 StructuredSelection selection = new StructuredSelection(entry);
423 fTreeViewer.setSelection(selection);
424 } else {
425 fTreeViewer.setSelection(new StructuredSelection());
426 }
427 fInhibitTreeSelection = false;
428 ArrayList<TreeItem> treeItems = getVisibleExpandedItems(tree);
429 if (treeItems.size() == 0) {
430 return;
431 }
432 TreeItem treeItem = treeItems.get(fTimeGraphViewer.getTopIndex());
433 tree.setTopItem(treeItem);
434 }
435 });
436
437 // ensure alignment of top item between tree and time graph
438 fTimeGraphViewer.getVerticalBar().addSelectionListener(new SelectionAdapter() {
439 @Override
440 public void widgetSelected(SelectionEvent e) {
441 ArrayList<TreeItem> treeItems = getVisibleExpandedItems(tree);
442 if (treeItems.size() == 0) {
443 return;
444 }
445 TreeItem treeItem = treeItems.get(fTimeGraphViewer.getTopIndex());
446 tree.setTopItem(treeItem);
447 }
448 });
449
450 // ensure alignment of top item between tree and time graph
451 fTimeGraphViewer.getTimeGraphControl().addMouseWheelListener(new MouseWheelListener() {
452 @Override
453 public void mouseScrolled(MouseEvent e) {
454 ArrayList<TreeItem> treeItems = getVisibleExpandedItems(tree);
455 if (treeItems.size() == 0) {
456 return;
457 }
458 TreeItem treeItem = treeItems.get(fTimeGraphViewer.getTopIndex());
459 tree.setTopItem(treeItem);
460 }
461 });
462
463 // The filler rows are required to ensure alignment when the tree does not have a
464 // visible horizontal scroll bar. The tree does not allow its top item to be set
465 // to a value that would cause blank space to be drawn at the bottom of the tree.
466 fNumFillerRows = Display.getDefault().getBounds().height / getItemHeight(tree);
467
468 sash.setWeights(new int[] { 1, 1 });
469 }
470
471 // ------------------------------------------------------------------------
472 // Accessors
473 // ------------------------------------------------------------------------
474
475 /**
476 * Returns this time graph combo's tree viewer.
477 *
478 * @return the tree viewer
479 */
480 public TreeViewer getTreeViewer() {
481 return fTreeViewer;
482 }
483
484 /**
485 * Returns this time graph combo's time graph viewer.
486 *
487 * @return the time graph viewer
488 */
489 public TimeGraphViewer getTimeGraphViewer() {
490 return fTimeGraphViewer;
491 }
492
493 // ------------------------------------------------------------------------
494 // Control
495 // ------------------------------------------------------------------------
496
497 /* (non-Javadoc)
498 * @see org.eclipse.swt.widgets.Control#redraw()
499 */
500 @Override
501 public void redraw() {
502 fTimeGraphViewer.getControl().redraw();
503 super.redraw();
504 }
505
506 // ------------------------------------------------------------------------
507 // Operations
508 // ------------------------------------------------------------------------
509
510 /**
511 * Sets the tree content provider used by this time graph combo.
512 *
513 * @param contentProvider the tree content provider
514 */
515 public void setTreeContentProvider(ITreeContentProvider contentProvider) {
516 fTreeViewer.setContentProvider(new TreeContentProviderWrapper(contentProvider));
517 }
518
519 /**
520 * Sets the tree label provider used by this time graph combo.
521 *
522 * @param treeLabelProvider the tree label provider
523 */
524 public void setTreeLabelProvider(ITableLabelProvider labelProvider) {
525 fTreeViewer.setLabelProvider(new TreeLabelProviderWrapper(labelProvider));
526 }
527
528 /**
529 * Sets the tree columns for this time graph combo.
530 *
531 * @param columnNames the tree column names
532 */
533 public void setTreeColumns(String[] columnNames) {
534 final Tree tree = fTreeViewer.getTree();
535 for (String columnName : columnNames) {
536 TreeColumn column = new TreeColumn(tree, SWT.LEFT);
537 column.setText(columnName);
538 column.pack();
539 }
540 }
541
542
543 /**
544 * Sets the time graph provider used by this time graph combo.
545 *
546 * @param timeGraphProvider the time graph provider
547 */
548 public void setTimeGraphProvider(ITimeGraphPresentationProvider timeGraphProvider) {
549 fTimeGraphViewer.setTimeGraphProvider(timeGraphProvider);
550 }
551
552 /**
553 * Sets or clears the input for this time graph combo.
554 * The input array should only contain top-level elements.
555 *
556 * @param input the input of this time graph combo, or <code>null</code> if none
557 */
558 public void setInput(ITimeGraphEntry[] input) {
559 fInhibitTreeSelection = true;
560 fTreeViewer.setInput(input);
561 fInhibitTreeSelection = true;
562 fTreeViewer.expandAll();
563 fTreeViewer.getTree().getVerticalBar().setEnabled(false);
564 fTreeViewer.getTree().getVerticalBar().setVisible(false);
565 fTimeGraphViewer.setItemHeight(getItemHeight(fTreeViewer.getTree()));
566 fTimeGraphViewer.setInput(input);
567 }
568
569 /**
570 * Refreshes this time graph completely with information freshly obtained from its model.
571 */
572 public void refresh() {
573 fTreeViewer.refresh();
574 fTimeGraphViewer.refresh();
575 }
576
577 /**
578 * Adds a listener for selection changes in this time graph combo.
579 *
580 * @param listener a selection listener
581 */
582 public void addSelectionListener(ITimeGraphSelectionListener listener) {
583 SelectionListenerWrapper listenerWrapper = new SelectionListenerWrapper(listener);
584 fTreeViewer.addSelectionChangedListener(listenerWrapper);
585 fSelectionListenerMap.put(listener, listenerWrapper);
586 fTimeGraphViewer.addSelectionListener(listenerWrapper);
587 }
588
589 /**
590 * Removes the given selection listener from this time graph combo.
591 *
592 * @param listener a selection changed listener
593 */
594 public void removeSelectionListener(ITimeGraphSelectionListener listener) {
595 SelectionListenerWrapper listenerWrapper = fSelectionListenerMap.remove(listener);
596 fTreeViewer.removeSelectionChangedListener(listenerWrapper);
597 fTimeGraphViewer.removeSelectionListener(listenerWrapper);
598 }
599
600 /**
601 * Sets the current selection for this time graph combo.
602 *
603 * @param selection the new selection
604 */
605 public void setSelection(ITimeGraphEntry selection) {
606 fTimeGraphViewer.setSelection(selection);
607 fInhibitTreeSelection = true; // block the tree selection changed listener
608 if (selection != null) {
609 StructuredSelection structuredSelection = new StructuredSelection(selection);
610 fTreeViewer.setSelection(structuredSelection);
611 } else {
612 fTreeViewer.setSelection(new StructuredSelection());
613 }
614 fInhibitTreeSelection = false;
615 ArrayList<TreeItem> treeItems = getVisibleExpandedItems(fTreeViewer.getTree());
616 if (treeItems.size() == 0) {
617 return;
618 }
619 TreeItem treeItem = treeItems.get(fTimeGraphViewer.getTopIndex());
620 fTreeViewer.getTree().setTopItem(treeItem);
621 }
622
623 // ------------------------------------------------------------------------
624 // Internal
625 // ------------------------------------------------------------------------
626
627 private ArrayList<TreeItem> getVisibleExpandedItems(Tree tree) {
628 ArrayList<TreeItem> items = new ArrayList<TreeItem>();
629 for (TreeItem item : tree.getItems()) {
630 if (item.getData() == FILLER) {
631 break;
632 }
633 items.add(item);
634 if (item.getExpanded()) {
635 items.addAll(getVisibleExpandedItems(item));
636 }
637 }
638 return items;
639 }
640
641 private ArrayList<TreeItem> getVisibleExpandedItems(TreeItem treeItem) {
642 ArrayList<TreeItem> items = new ArrayList<TreeItem>();
643 for (TreeItem item : treeItem.getItems()) {
644 items.add(item);
645 if (item.getExpanded()) {
646 items.addAll(getVisibleExpandedItems(item));
647 }
648 }
649 return items;
650 }
651
652 private int getItemHeight(final Tree tree) {
653 /*
654 * Bug in Linux. The method getItemHeight doesn't always return the correct value.
655 */
656 if (fLinuxItemHeight >= 0 && System.getProperty("os.name").contains("Linux")) { //$NON-NLS-1$ //$NON-NLS-2$
657 if (fLinuxItemHeight != 0) {
658 return fLinuxItemHeight;
659 }
660 ArrayList<TreeItem> treeItems = getVisibleExpandedItems(tree);
661 if (treeItems.size() > 1) {
662 final TreeItem treeItem0 = treeItems.get(0);
663 final TreeItem treeItem1 = treeItems.get(1);
664 PaintListener paintListener = new PaintListener() {
665 @Override
666 public void paintControl(PaintEvent e) {
667 tree.removePaintListener(this);
668 int y0 = treeItem0.getBounds().y;
669 int y1 = treeItem1.getBounds().y;
670 int itemHeight = y1 - y0;
671 if (itemHeight > 0) {
672 fLinuxItemHeight = itemHeight;
673 fTimeGraphViewer.setItemHeight(itemHeight);
674 }
675 }
676 };
677 tree.addPaintListener(paintListener);
678 }
679 } else {
680 fLinuxItemHeight = -1; // Not Linux, don't perform os.name check anymore
681 }
682 return tree.getItemHeight();
683 }
684
685 }
This page took 0.075511 seconds and 6 git commands to generate.