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