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