1 /*******************************************************************************
2 * Copyright (c) 2012 Ericsson
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
10 * Patrick Tasse - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
;
15 import java
.util
.ArrayList
;
16 import java
.util
.Arrays
;
17 import java
.util
.HashMap
;
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
.MouseTrackAdapter
;
37 import org
.eclipse
.swt
.events
.MouseWheelListener
;
38 import org
.eclipse
.swt
.events
.PaintEvent
;
39 import org
.eclipse
.swt
.events
.PaintListener
;
40 import org
.eclipse
.swt
.events
.SelectionAdapter
;
41 import org
.eclipse
.swt
.events
.SelectionEvent
;
42 import org
.eclipse
.swt
.graphics
.Image
;
43 import org
.eclipse
.swt
.graphics
.Point
;
44 import org
.eclipse
.swt
.layout
.FillLayout
;
45 import org
.eclipse
.swt
.widgets
.Composite
;
46 import org
.eclipse
.swt
.widgets
.Display
;
47 import org
.eclipse
.swt
.widgets
.Event
;
48 import org
.eclipse
.swt
.widgets
.Listener
;
49 import org
.eclipse
.swt
.widgets
.Slider
;
50 import org
.eclipse
.swt
.widgets
.Tree
;
51 import org
.eclipse
.swt
.widgets
.TreeColumn
;
52 import org
.eclipse
.swt
.widgets
.TreeItem
;
55 * Time graph "combo" view (with the list/tree on the left and the gantt chart
59 * @author Patrick Tasse
61 public class TimeGraphCombo
extends Composite
{
63 // ------------------------------------------------------------------------
65 // ------------------------------------------------------------------------
67 private static final Object FILLER
= new Object();
69 // ------------------------------------------------------------------------
71 // ------------------------------------------------------------------------
74 private TreeViewer fTreeViewer
;
77 private TimeGraphViewer fTimeGraphViewer
;
79 // The selection listener map
80 private final HashMap
<ITimeGraphSelectionListener
, SelectionListenerWrapper
> fSelectionListenerMap
= new HashMap
<ITimeGraphSelectionListener
, SelectionListenerWrapper
>();
82 // Flag to block the tree selection changed listener when triggered by the time graph combo
83 private boolean fInhibitTreeSelection
= false;
85 // Number of filler rows used by the tree content provider
86 private int fNumFillerRows
;
88 // Calculated item height for Linux workaround
89 private int fLinuxItemHeight
= 0;
91 // ------------------------------------------------------------------------
93 // ------------------------------------------------------------------------
96 * The TreeContentProviderWrapper is used to insert filler items after
97 * the elements of the tree's real content provider.
99 private class TreeContentProviderWrapper
implements ITreeContentProvider
{
100 private final ITreeContentProvider contentProvider
;
102 public TreeContentProviderWrapper(ITreeContentProvider contentProvider
) {
103 this.contentProvider
= contentProvider
;
107 public void dispose() {
108 contentProvider
.dispose();
112 public void inputChanged(Viewer viewer
, Object oldInput
, Object newInput
) {
113 contentProvider
.inputChanged(viewer
, oldInput
, newInput
);
117 public Object
[] getElements(Object inputElement
) {
118 Object
[] elements
= contentProvider
.getElements(inputElement
);
119 // add filler elements to ensure alignment with time analysis viewer
120 Object
[] oElements
= Arrays
.copyOf(elements
, elements
.length
+ fNumFillerRows
, new Object
[0].getClass());
121 for (int i
= 0; i
< fNumFillerRows
; i
++) {
122 oElements
[elements
.length
+ i
] = FILLER
;
128 public Object
[] getChildren(Object parentElement
) {
129 if (parentElement
instanceof ITimeGraphEntry
) {
130 return contentProvider
.getChildren(parentElement
);
132 return new Object
[0];
136 public Object
getParent(Object element
) {
137 if (element
instanceof ITimeGraphEntry
) {
138 return contentProvider
.getParent(element
);
144 public boolean hasChildren(Object element
) {
145 if (element
instanceof ITimeGraphEntry
) {
146 return contentProvider
.hasChildren(element
);
153 * The TreeLabelProviderWrapper is used to intercept the filler items
154 * from the calls to the tree's real label provider.
156 private class TreeLabelProviderWrapper
implements ITableLabelProvider
{
157 private final ITableLabelProvider labelProvider
;
159 public TreeLabelProviderWrapper(ITableLabelProvider labelProvider
) {
160 this.labelProvider
= labelProvider
;
164 public void addListener(ILabelProviderListener listener
) {
165 labelProvider
.addListener(listener
);
169 public void dispose() {
170 labelProvider
.dispose();
174 public boolean isLabelProperty(Object element
, String property
) {
175 if (element
instanceof ITimeGraphEntry
) {
176 return labelProvider
.isLabelProperty(element
, property
);
182 public void removeListener(ILabelProviderListener listener
) {
183 labelProvider
.removeListener(listener
);
187 public Image
getColumnImage(Object element
, int columnIndex
) {
188 if (element
instanceof ITimeGraphEntry
) {
189 return labelProvider
.getColumnImage(element
, columnIndex
);
195 public String
getColumnText(Object element
, int columnIndex
) {
196 if (element
instanceof ITimeGraphEntry
) {
197 return labelProvider
.getColumnText(element
, columnIndex
);
205 * The SelectionListenerWrapper is used to intercept the filler items from
206 * the time graph combo's real selection listener, and to prevent double
207 * notifications from being sent when selection changes in both tree and
208 * time graph at the same time.
210 private class SelectionListenerWrapper
implements ISelectionChangedListener
, ITimeGraphSelectionListener
{
211 private final ITimeGraphSelectionListener listener
;
212 private ITimeGraphEntry selection
= null;
214 public SelectionListenerWrapper(ITimeGraphSelectionListener listener
) {
215 this.listener
= listener
;
219 public void selectionChanged(SelectionChangedEvent event
) {
220 if (fInhibitTreeSelection
) {
223 Object element
= ((IStructuredSelection
) event
.getSelection()).getFirstElement();
224 if (element
instanceof ITimeGraphEntry
) {
225 ITimeGraphEntry entry
= (ITimeGraphEntry
) element
;
226 if (entry
!= selection
) {
228 listener
.selectionChanged(new TimeGraphSelectionEvent(event
.getSource(), selection
));
234 public void selectionChanged(TimeGraphSelectionEvent event
) {
235 ITimeGraphEntry entry
= event
.getSelection();
236 if (entry
!= selection
) {
238 listener
.selectionChanged(new TimeGraphSelectionEvent(event
.getSource(), selection
));
243 // ------------------------------------------------------------------------
245 // ------------------------------------------------------------------------
248 * Constructs a new instance of this class given its parent
249 * and a style value describing its behavior and appearance.
251 * @param parent a widget which will be the parent of the new instance (cannot be null)
252 * @param style the style of widget to construct
254 public TimeGraphCombo(Composite parent
, int style
) {
255 super(parent
, style
);
256 setLayout(new FillLayout());
258 final SashForm sash
= new SashForm(this, SWT
.NONE
);
260 fTreeViewer
= new TreeViewer(sash
, SWT
.FULL_SELECTION
| SWT
.H_SCROLL
);
261 final Tree tree
= fTreeViewer
.getTree();
262 tree
.setHeaderVisible(true);
263 tree
.setLinesVisible(true);
265 fTimeGraphViewer
= new TimeGraphViewer(sash
, SWT
.NONE
);
266 fTimeGraphViewer
.setItemHeight(getItemHeight(tree
));
267 fTimeGraphViewer
.setHeaderHeight(tree
.getHeaderHeight());
268 fTimeGraphViewer
.setBorderWidth(tree
.getBorderWidth());
269 fTimeGraphViewer
.setNameWidthPref(0);
271 // Feature in Windows. The tree vertical bar reappears when
272 // the control is resized so we need to hide it again.
273 // Bug in Linux. The tree header height is 0 in constructor,
274 // so we need to reset it later when the control is resized.
275 tree
.addControlListener(new ControlAdapter() {
278 public void controlResized(ControlEvent e
) {
281 tree
.getVerticalBar().setEnabled(false);
282 // this can trigger controlResized recursively
283 tree
.getVerticalBar().setVisible(false);
286 fTimeGraphViewer
.setHeaderHeight(tree
.getHeaderHeight());
290 // ensure synchronization of expanded items between tree and time graph
291 fTreeViewer
.addTreeListener(new ITreeViewerListener() {
293 public void treeCollapsed(TreeExpansionEvent event
) {
294 fTimeGraphViewer
.setExpandedState((ITimeGraphEntry
) event
.getElement(), false);
295 ArrayList
<TreeItem
> treeItems
= getVisibleExpandedItems(tree
);
296 if (treeItems
.size() == 0) {
299 TreeItem treeItem
= treeItems
.get(fTimeGraphViewer
.getTopIndex());
300 tree
.setTopItem(treeItem
);
304 public void treeExpanded(TreeExpansionEvent event
) {
305 fTimeGraphViewer
.setExpandedState((ITimeGraphEntry
) event
.getElement(), true);
306 ArrayList
<TreeItem
> treeItems
= getVisibleExpandedItems(tree
);
307 if (treeItems
.size() == 0) {
310 final TreeItem treeItem
= treeItems
.get(fTimeGraphViewer
.getTopIndex());
311 // queue the top item update because the tree can change its top item
312 // autonomously immediately after the listeners have been notified
313 getDisplay().asyncExec(new Runnable() {
316 tree
.setTopItem(treeItem
);
321 // ensure synchronization of expanded items between tree and time graph
322 fTimeGraphViewer
.addTreeListener(new ITimeGraphTreeListener() {
324 public void treeCollapsed(TimeGraphTreeExpansionEvent event
) {
325 fTreeViewer
.setExpandedState(event
.getEntry(), false);
329 public void treeExpanded(TimeGraphTreeExpansionEvent event
) {
330 fTreeViewer
.setExpandedState(event
.getEntry(), true);
334 // prevent mouse button from selecting a filler tree item
335 tree
.addListener(SWT
.MouseDown
, new Listener() {
337 public void handleEvent(Event event
) {
338 TreeItem treeItem
= tree
.getItem(new Point(event
.x
, event
.y
));
339 if (treeItem
== null || treeItem
.getData() == FILLER
) {
341 ArrayList
<TreeItem
> treeItems
= getVisibleExpandedItems(tree
);
342 if (treeItems
.size() == 0) {
343 fTreeViewer
.setSelection(new StructuredSelection());
344 fTimeGraphViewer
.setSelection(null);
347 // this prevents from scrolling up when selecting
348 // the partially visible tree item at the bottom
349 tree
.select(treeItems
.get(treeItems
.size() - 1));
350 fTreeViewer
.setSelection(new StructuredSelection());
351 fTimeGraphViewer
.setSelection(null);
356 // prevent mouse wheel from scrolling down into filler tree items
357 tree
.addListener(SWT
.MouseWheel
, new Listener() {
359 public void handleEvent(Event event
) {
361 Slider scrollBar
= fTimeGraphViewer
.getVerticalBar();
362 fTimeGraphViewer
.setTopIndex(scrollBar
.getSelection() - event
.count
);
363 ArrayList
<TreeItem
> treeItems
= getVisibleExpandedItems(tree
);
364 if (treeItems
.size() == 0) {
367 TreeItem treeItem
= treeItems
.get(fTimeGraphViewer
.getTopIndex());
368 tree
.setTopItem(treeItem
);
372 // prevent key stroke from selecting a filler tree item
373 tree
.addListener(SWT
.KeyDown
, new Listener() {
375 public void handleEvent(Event event
) {
376 ArrayList
<TreeItem
> treeItems
= getVisibleExpandedItems(tree
);
377 if (treeItems
.size() == 0) {
378 fTreeViewer
.setSelection(new StructuredSelection());
382 if (event
.keyCode
== SWT
.ARROW_DOWN
) {
383 int index
= Math
.min(fTimeGraphViewer
.getSelectionIndex() + 1, treeItems
.size() - 1);
384 fTimeGraphViewer
.setSelection((ITimeGraphEntry
) treeItems
.get(index
).getData());
386 } else if (event
.keyCode
== SWT
.PAGE_DOWN
) {
387 int height
= tree
.getSize().y
- tree
.getHeaderHeight() - tree
.getHorizontalBar().getSize().y
;
388 int countPerPage
= height
/ getItemHeight(tree
);
389 int index
= Math
.min(fTimeGraphViewer
.getSelectionIndex() + countPerPage
- 1, treeItems
.size() - 1);
390 fTimeGraphViewer
.setSelection((ITimeGraphEntry
) treeItems
.get(index
).getData());
392 } else if (event
.keyCode
== SWT
.END
) {
393 fTimeGraphViewer
.setSelection((ITimeGraphEntry
) treeItems
.get(treeItems
.size() - 1).getData());
396 TreeItem treeItem
= treeItems
.get(fTimeGraphViewer
.getTopIndex());
397 tree
.setTopItem(treeItem
);
398 if (fTimeGraphViewer
.getSelectionIndex() >= 0) {
399 fTreeViewer
.setSelection(new StructuredSelection(fTimeGraphViewer
.getSelection()));
401 fTreeViewer
.setSelection(new StructuredSelection());
406 // ensure alignment of top item between tree and time graph
407 fTimeGraphViewer
.getTimeGraphControl().addControlListener(new ControlAdapter() {
409 public void controlResized(ControlEvent e
) {
410 ArrayList
<TreeItem
> treeItems
= getVisibleExpandedItems(tree
);
411 if (treeItems
.size() == 0) {
414 TreeItem treeItem
= treeItems
.get(fTimeGraphViewer
.getTopIndex());
415 tree
.setTopItem(treeItem
);
419 // ensure synchronization of selected item between tree and time graph
420 fTreeViewer
.addSelectionChangedListener(new ISelectionChangedListener() {
422 public void selectionChanged(SelectionChangedEvent event
) {
423 if (fInhibitTreeSelection
) {
426 if (event
.getSelection() instanceof IStructuredSelection
) {
427 Object selection
= ((IStructuredSelection
) event
.getSelection()).getFirstElement();
428 if (selection
instanceof ITimeGraphEntry
) {
429 fTimeGraphViewer
.setSelection((ITimeGraphEntry
) selection
);
431 ArrayList
<TreeItem
> treeItems
= getVisibleExpandedItems(tree
);
432 if (treeItems
.size() == 0) {
435 TreeItem treeItem
= treeItems
.get(fTimeGraphViewer
.getTopIndex());
436 tree
.setTopItem(treeItem
);
441 // ensure synchronization of selected item between tree and time graph
442 fTimeGraphViewer
.addSelectionListener(new ITimeGraphSelectionListener() {
444 public void selectionChanged(TimeGraphSelectionEvent event
) {
445 ITimeGraphEntry entry
= fTimeGraphViewer
.getSelection();
446 fInhibitTreeSelection
= true; // block the tree selection changed listener
448 StructuredSelection selection
= new StructuredSelection(entry
);
449 fTreeViewer
.setSelection(selection
);
451 fTreeViewer
.setSelection(new StructuredSelection());
453 fInhibitTreeSelection
= false;
454 ArrayList
<TreeItem
> treeItems
= getVisibleExpandedItems(tree
);
455 if (treeItems
.size() == 0) {
458 TreeItem treeItem
= treeItems
.get(fTimeGraphViewer
.getTopIndex());
459 tree
.setTopItem(treeItem
);
463 // ensure alignment of top item between tree and time graph
464 fTimeGraphViewer
.getVerticalBar().addSelectionListener(new SelectionAdapter() {
466 public void widgetSelected(SelectionEvent e
) {
467 ArrayList
<TreeItem
> treeItems
= getVisibleExpandedItems(tree
);
468 if (treeItems
.size() == 0) {
471 TreeItem treeItem
= treeItems
.get(fTimeGraphViewer
.getTopIndex());
472 tree
.setTopItem(treeItem
);
476 // ensure alignment of top item between tree and time graph
477 fTimeGraphViewer
.getTimeGraphControl().addMouseWheelListener(new MouseWheelListener() {
479 public void mouseScrolled(MouseEvent e
) {
480 ArrayList
<TreeItem
> treeItems
= getVisibleExpandedItems(tree
);
481 if (treeItems
.size() == 0) {
484 TreeItem treeItem
= treeItems
.get(fTimeGraphViewer
.getTopIndex());
485 tree
.setTopItem(treeItem
);
489 // ensure the tree has focus control when mouse is over it if the time graph had control
490 fTreeViewer
.getControl().addMouseTrackListener(new MouseTrackAdapter() {
492 public void mouseEnter(MouseEvent e
) {
493 if (fTimeGraphViewer
.getTimeGraphControl().isFocusControl()) {
494 fTreeViewer
.getControl().setFocus();
499 // ensure the time graph has focus control when mouse is over it if the tree had control
500 fTimeGraphViewer
.getTimeGraphControl().addMouseTrackListener(new MouseTrackAdapter() {
502 public void mouseEnter(MouseEvent e
) {
503 if (fTreeViewer
.getControl().isFocusControl()) {
504 fTimeGraphViewer
.getTimeGraphControl().setFocus();
508 fTimeGraphViewer
.getTimeGraphScale().addMouseTrackListener(new MouseTrackAdapter() {
510 public void mouseEnter(MouseEvent e
) {
511 if (fTreeViewer
.getControl().isFocusControl()) {
512 fTimeGraphViewer
.getTimeGraphControl().setFocus();
517 // The filler rows are required to ensure alignment when the tree does not have a
518 // visible horizontal scroll bar. The tree does not allow its top item to be set
519 // to a value that would cause blank space to be drawn at the bottom of the tree.
520 fNumFillerRows
= Display
.getDefault().getBounds().height
/ getItemHeight(tree
);
522 sash
.setWeights(new int[] { 1, 1 });
525 // ------------------------------------------------------------------------
527 // ------------------------------------------------------------------------
530 * Returns this time graph combo's tree viewer.
532 * @return the tree viewer
534 public TreeViewer
getTreeViewer() {
539 * Returns this time graph combo's time graph viewer.
541 * @return the time graph viewer
543 public TimeGraphViewer
getTimeGraphViewer() {
544 return fTimeGraphViewer
;
547 // ------------------------------------------------------------------------
549 // ------------------------------------------------------------------------
552 * @see org.eclipse.swt.widgets.Control#redraw()
555 public void redraw() {
556 fTimeGraphViewer
.getControl().redraw();
560 // ------------------------------------------------------------------------
562 // ------------------------------------------------------------------------
565 * Sets the tree content provider used by this time graph combo.
567 * @param contentProvider the tree content provider
569 public void setTreeContentProvider(ITreeContentProvider contentProvider
) {
570 fTreeViewer
.setContentProvider(new TreeContentProviderWrapper(contentProvider
));
574 * Sets the tree label provider used by this time graph combo.
576 * @param labelProvider the tree label provider
578 public void setTreeLabelProvider(ITableLabelProvider labelProvider
) {
579 fTreeViewer
.setLabelProvider(new TreeLabelProviderWrapper(labelProvider
));
583 * Sets the tree columns for this time graph combo.
585 * @param columnNames the tree column names
587 public void setTreeColumns(String
[] columnNames
) {
588 final Tree tree
= fTreeViewer
.getTree();
589 for (String columnName
: columnNames
) {
590 TreeColumn column
= new TreeColumn(tree
, SWT
.LEFT
);
591 column
.setText(columnName
);
597 * Sets the time graph provider used by this time graph combo.
599 * @param timeGraphProvider the time graph provider
601 public void setTimeGraphProvider(ITimeGraphPresentationProvider timeGraphProvider
) {
602 fTimeGraphViewer
.setTimeGraphProvider(timeGraphProvider
);
606 * Sets or clears the input for this time graph combo.
607 * The input array should only contain top-level elements.
609 * @param input the input of this time graph combo, or <code>null</code> if none
611 public void setInput(ITimeGraphEntry
[] input
) {
612 fInhibitTreeSelection
= true;
613 fTreeViewer
.setInput(input
);
614 for (SelectionListenerWrapper listenerWrapper
: fSelectionListenerMap
.values()) {
615 listenerWrapper
.selection
= null;
617 fInhibitTreeSelection
= false;
618 fTreeViewer
.expandAll();
619 fTreeViewer
.getTree().getVerticalBar().setEnabled(false);
620 fTreeViewer
.getTree().getVerticalBar().setVisible(false);
621 fTimeGraphViewer
.setItemHeight(getItemHeight(fTreeViewer
.getTree()));
622 fTimeGraphViewer
.setInput(input
);
626 * Refreshes this time graph completely with information freshly obtained from its model.
628 public void refresh() {
629 fInhibitTreeSelection
= true;
630 fTreeViewer
.refresh();
631 fTimeGraphViewer
.refresh();
632 fInhibitTreeSelection
= false;
636 * Adds a listener for selection changes in this time graph combo.
638 * @param listener a selection listener
640 public void addSelectionListener(ITimeGraphSelectionListener listener
) {
641 SelectionListenerWrapper listenerWrapper
= new SelectionListenerWrapper(listener
);
642 fTreeViewer
.addSelectionChangedListener(listenerWrapper
);
643 fSelectionListenerMap
.put(listener
, listenerWrapper
);
644 fTimeGraphViewer
.addSelectionListener(listenerWrapper
);
648 * Removes the given selection listener from this time graph combo.
650 * @param listener a selection changed listener
652 public void removeSelectionListener(ITimeGraphSelectionListener listener
) {
653 SelectionListenerWrapper listenerWrapper
= fSelectionListenerMap
.remove(listener
);
654 fTreeViewer
.removeSelectionChangedListener(listenerWrapper
);
655 fTimeGraphViewer
.removeSelectionListener(listenerWrapper
);
659 * Sets the current selection for this time graph combo.
661 * @param selection the new selection
663 public void setSelection(ITimeGraphEntry selection
) {
664 fTimeGraphViewer
.setSelection(selection
);
665 fInhibitTreeSelection
= true; // block the tree selection changed listener
666 if (selection
!= null) {
667 StructuredSelection structuredSelection
= new StructuredSelection(selection
);
668 fTreeViewer
.setSelection(structuredSelection
);
670 fTreeViewer
.setSelection(new StructuredSelection());
672 fInhibitTreeSelection
= false;
673 ArrayList
<TreeItem
> treeItems
= getVisibleExpandedItems(fTreeViewer
.getTree());
674 if (treeItems
.size() == 0) {
677 TreeItem treeItem
= treeItems
.get(fTimeGraphViewer
.getTopIndex());
678 fTreeViewer
.getTree().setTopItem(treeItem
);
682 * Set the expanded state of an entry
685 * The entry to expand/collapse
687 * True for expanded, false for collapsed
691 public void setExpandedState(ITimeGraphEntry entry
, boolean expanded
) {
692 fTimeGraphViewer
.setExpandedState(entry
, expanded
);
693 fTreeViewer
.setExpandedState(entry
, expanded
);
697 * Collapses all nodes of the viewer's tree, starting with the root.
701 public void collapseAll() {
702 fTimeGraphViewer
.collapseAll();
703 fTreeViewer
.collapseAll();
707 * Expands all nodes of the viewer's tree, starting with the root.
711 public void expandAll() {
712 fTimeGraphViewer
.expandAll();
713 fTreeViewer
.expandAll();
716 // ------------------------------------------------------------------------
718 // ------------------------------------------------------------------------
720 private ArrayList
<TreeItem
> getVisibleExpandedItems(Tree tree
) {
721 ArrayList
<TreeItem
> items
= new ArrayList
<TreeItem
>();
722 for (TreeItem item
: tree
.getItems()) {
723 if (item
.getData() == FILLER
) {
727 if (item
.getExpanded()) {
728 items
.addAll(getVisibleExpandedItems(item
));
734 private ArrayList
<TreeItem
> getVisibleExpandedItems(TreeItem treeItem
) {
735 ArrayList
<TreeItem
> items
= new ArrayList
<TreeItem
>();
736 for (TreeItem item
: treeItem
.getItems()) {
738 if (item
.getExpanded()) {
739 items
.addAll(getVisibleExpandedItems(item
));
745 private int getItemHeight(final Tree tree
) {
747 * Bug in Linux. The method getItemHeight doesn't always return the correct value.
749 if (fLinuxItemHeight
>= 0 && System
.getProperty("os.name").contains("Linux")) { //$NON-NLS-1$ //$NON-NLS-2$
750 if (fLinuxItemHeight
!= 0) {
751 return fLinuxItemHeight
;
753 ArrayList
<TreeItem
> treeItems
= getVisibleExpandedItems(tree
);
754 if (treeItems
.size() > 1) {
755 final TreeItem treeItem0
= treeItems
.get(0);
756 final TreeItem treeItem1
= treeItems
.get(1);
757 PaintListener paintListener
= new PaintListener() {
759 public void paintControl(PaintEvent e
) {
760 tree
.removePaintListener(this);
761 int y0
= treeItem0
.getBounds().y
;
762 int y1
= treeItem1
.getBounds().y
;
763 int itemHeight
= y1
- y0
;
764 if (itemHeight
> 0) {
765 fLinuxItemHeight
= itemHeight
;
766 fTimeGraphViewer
.setItemHeight(itemHeight
);
770 tree
.addPaintListener(paintListener
);
773 fLinuxItemHeight
= -1; // Not Linux, don't perform os.name check anymore
775 return tree
.getItemHeight();