tmf: Fix TimeGraphCombo item height synchronization issues
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / widgets / timegraph / TimeGraphCombo.java
CommitLineData
837a2f8c 1/*******************************************************************************
d2e4afa7 2 * Copyright (c) 2012, 2015 Ericsson, others
837a2f8c
PT
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
f8840316 11 * François Rajotte - Filter implementation
bec1f1ac 12 * Geneviève Bastien - Add event links between entries
b97d61f0 13 * Christian Mansky - Add check active / uncheck inactive buttons
837a2f8c
PT
14 *******************************************************************************/
15
2bdf0193 16package org.eclipse.tracecompass.tmf.ui.widgets.timegraph;
837a2f8c
PT
17
18import java.util.ArrayList;
19import java.util.Arrays;
20import java.util.HashMap;
70e10acc 21import java.util.HashSet;
6ac5a950
AM
22import java.util.List;
23import java.util.Map;
70e10acc 24import java.util.Set;
837a2f8c 25
dfa0ef96 26import org.eclipse.jdt.annotation.NonNull;
6ac5a950 27import org.eclipse.jface.action.Action;
4c9c0c87 28import org.eclipse.jface.viewers.AbstractTreeViewer;
837a2f8c
PT
29import org.eclipse.jface.viewers.ILabelProviderListener;
30import org.eclipse.jface.viewers.ISelectionChangedListener;
31import org.eclipse.jface.viewers.IStructuredSelection;
32import org.eclipse.jface.viewers.ITableLabelProvider;
33import org.eclipse.jface.viewers.ITreeContentProvider;
34import org.eclipse.jface.viewers.ITreeViewerListener;
35import org.eclipse.jface.viewers.SelectionChangedEvent;
36import org.eclipse.jface.viewers.StructuredSelection;
37import org.eclipse.jface.viewers.TreeExpansionEvent;
38import org.eclipse.jface.viewers.TreeViewer;
39import org.eclipse.jface.viewers.Viewer;
6ac5a950 40import org.eclipse.jface.viewers.ViewerFilter;
837a2f8c
PT
41import org.eclipse.swt.SWT;
42import org.eclipse.swt.custom.SashForm;
43import org.eclipse.swt.events.ControlAdapter;
44import org.eclipse.swt.events.ControlEvent;
45import org.eclipse.swt.events.MouseEvent;
46import org.eclipse.swt.events.MouseTrackAdapter;
47import org.eclipse.swt.events.MouseWheelListener;
48import org.eclipse.swt.events.PaintEvent;
49import org.eclipse.swt.events.PaintListener;
50import org.eclipse.swt.events.SelectionAdapter;
51import org.eclipse.swt.events.SelectionEvent;
52import org.eclipse.swt.graphics.Image;
53import org.eclipse.swt.graphics.Point;
588dff10 54import org.eclipse.swt.graphics.Rectangle;
837a2f8c 55import org.eclipse.swt.layout.FillLayout;
d2e4afa7 56import org.eclipse.swt.layout.GridLayout;
837a2f8c 57import org.eclipse.swt.widgets.Composite;
d2e4afa7 58import org.eclipse.swt.widgets.Control;
837a2f8c
PT
59import org.eclipse.swt.widgets.Display;
60import org.eclipse.swt.widgets.Event;
61import org.eclipse.swt.widgets.Listener;
d2e4afa7 62import org.eclipse.swt.widgets.Sash;
837a2f8c
PT
63import org.eclipse.swt.widgets.Slider;
64import org.eclipse.swt.widgets.Tree;
65import org.eclipse.swt.widgets.TreeColumn;
66import org.eclipse.swt.widgets.TreeItem;
2bdf0193
AM
67import org.eclipse.tracecompass.internal.tmf.ui.Activator;
68import org.eclipse.tracecompass.internal.tmf.ui.ITmfImageConstants;
69import org.eclipse.tracecompass.internal.tmf.ui.Messages;
d2e4afa7
MAL
70import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
71import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
72import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentSignal;
73import org.eclipse.tracecompass.tmf.ui.views.ITmfTimeAligned;
b97d61f0 74import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.ITimeGraphEntryActiveProvider;
2bdf0193
AM
75import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.TimeGraphFilterDialog;
76import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent;
77import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
837a2f8c
PT
78
79/**
80 * Time graph "combo" view (with the list/tree on the left and the gantt chart
81 * on the right)
82 *
837a2f8c
PT
83 * @author Patrick Tasse
84 */
85public class TimeGraphCombo extends Composite {
86
87 // ------------------------------------------------------------------------
88 // Constants
89 // ------------------------------------------------------------------------
90
ae09c4ad 91 /** Constant indicating that all levels of the time graph should be expanded */
f4617471
PT
92 public static final int ALL_LEVELS = AbstractTreeViewer.ALL_LEVELS;
93
837a2f8c
PT
94 private static final Object FILLER = new Object();
95
96 // ------------------------------------------------------------------------
97 // Fields
98 // ------------------------------------------------------------------------
99
4999a196 100 /** The tree viewer */
837a2f8c
PT
101 private TreeViewer fTreeViewer;
102
4999a196 103 /** The time viewer */
dfa0ef96 104 private @NonNull TimeGraphViewer fTimeGraphViewer;
837a2f8c 105
4999a196 106 /** The selection listener map */
507b1336 107 private final Map<ITimeGraphSelectionListener, SelectionListenerWrapper> fSelectionListenerMap = new HashMap<>();
837a2f8c 108
4999a196 109 /** The map of viewer filters */
507b1336 110 private final Map<ViewerFilter, ViewerFilter> fViewerFilterMap = new HashMap<>();
6ac5a950 111
4999a196
GB
112 /**
113 * Flag to block the tree selection changed listener when triggered by the
114 * time graph combo
115 */
837a2f8c
PT
116 private boolean fInhibitTreeSelection = false;
117
4999a196 118 /** Number of filler rows used by the tree content provider */
837a2f8c
PT
119 private int fNumFillerRows;
120
4999a196 121 /** Calculated item height for Linux workaround */
837a2f8c
PT
122 private int fLinuxItemHeight = 0;
123
4999a196 124 /** The button that opens the filter dialog */
6ac5a950
AM
125 private Action showFilterAction;
126
4999a196 127 /** The filter dialog */
6ac5a950
AM
128 private TimeGraphFilterDialog fFilterDialog;
129
4999a196 130 /** The filter generated from the filter dialog */
6ac5a950
AM
131 private RawViewerFilter fFilter;
132
4999a196
GB
133 /** Default weight of each part of the sash */
134 private static final int[] DEFAULT_WEIGHTS = { 1, 1 };
135
588dff10
PT
136 /** List of all expanded items whose parents are also expanded */
137 private List<TreeItem> fVisibleExpandedItems = null;
138
d2e4afa7
MAL
139 private Listener fSashDragListener;
140 private SashForm fSashForm;
141
837a2f8c
PT
142 // ------------------------------------------------------------------------
143 // Classes
144 // ------------------------------------------------------------------------
145
146 /**
147 * The TreeContentProviderWrapper is used to insert filler items after
148 * the elements of the tree's real content provider.
149 */
150 private class TreeContentProviderWrapper implements ITreeContentProvider {
151 private final ITreeContentProvider contentProvider;
152
153 public TreeContentProviderWrapper(ITreeContentProvider contentProvider) {
154 this.contentProvider = contentProvider;
155 }
156
157 @Override
158 public void dispose() {
159 contentProvider.dispose();
160 }
161
162 @Override
163 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
164 contentProvider.inputChanged(viewer, oldInput, newInput);
165 }
166
167 @Override
168 public Object[] getElements(Object inputElement) {
169 Object[] elements = contentProvider.getElements(inputElement);
170 // add filler elements to ensure alignment with time analysis viewer
f1fae91f 171 Object[] oElements = Arrays.copyOf(elements, elements.length + fNumFillerRows, Object[].class);
837a2f8c
PT
172 for (int i = 0; i < fNumFillerRows; i++) {
173 oElements[elements.length + i] = FILLER;
174 }
175 return oElements;
176 }
177
178 @Override
179 public Object[] getChildren(Object parentElement) {
180 if (parentElement instanceof ITimeGraphEntry) {
181 return contentProvider.getChildren(parentElement);
182 }
183 return new Object[0];
184 }
185
186 @Override
187 public Object getParent(Object element) {
188 if (element instanceof ITimeGraphEntry) {
189 return contentProvider.getParent(element);
190 }
191 return null;
192 }
193
194 @Override
195 public boolean hasChildren(Object element) {
196 if (element instanceof ITimeGraphEntry) {
197 return contentProvider.hasChildren(element);
198 }
199 return false;
200 }
201 }
202
203 /**
204 * The TreeLabelProviderWrapper is used to intercept the filler items
205 * from the calls to the tree's real label provider.
206 */
207 private class TreeLabelProviderWrapper implements ITableLabelProvider {
208 private final ITableLabelProvider labelProvider;
209
210 public TreeLabelProviderWrapper(ITableLabelProvider labelProvider) {
211 this.labelProvider = labelProvider;
212 }
213
214 @Override
215 public void addListener(ILabelProviderListener listener) {
216 labelProvider.addListener(listener);
217 }
218
219 @Override
220 public void dispose() {
221 labelProvider.dispose();
222 }
223
224 @Override
225 public boolean isLabelProperty(Object element, String property) {
226 if (element instanceof ITimeGraphEntry) {
227 return labelProvider.isLabelProperty(element, property);
228 }
229 return false;
230 }
231
232 @Override
233 public void removeListener(ILabelProviderListener listener) {
234 labelProvider.removeListener(listener);
235 }
236
237 @Override
238 public Image getColumnImage(Object element, int columnIndex) {
239 if (element instanceof ITimeGraphEntry) {
240 return labelProvider.getColumnImage(element, columnIndex);
241 }
242 return null;
243 }
244
245 @Override
246 public String getColumnText(Object element, int columnIndex) {
247 if (element instanceof ITimeGraphEntry) {
248 return labelProvider.getColumnText(element, columnIndex);
249 }
250 return null;
251 }
252
253 }
254
255 /**
256 * The SelectionListenerWrapper is used to intercept the filler items from
257 * the time graph combo's real selection listener, and to prevent double
258 * notifications from being sent when selection changes in both tree and
259 * time graph at the same time.
260 */
261 private class SelectionListenerWrapper implements ISelectionChangedListener, ITimeGraphSelectionListener {
262 private final ITimeGraphSelectionListener listener;
263 private ITimeGraphEntry selection = null;
264
265 public SelectionListenerWrapper(ITimeGraphSelectionListener listener) {
266 this.listener = listener;
267 }
268
269 @Override
270 public void selectionChanged(SelectionChangedEvent event) {
271 if (fInhibitTreeSelection) {
272 return;
273 }
274 Object element = ((IStructuredSelection) event.getSelection()).getFirstElement();
275 if (element instanceof ITimeGraphEntry) {
276 ITimeGraphEntry entry = (ITimeGraphEntry) element;
277 if (entry != selection) {
278 selection = entry;
279 listener.selectionChanged(new TimeGraphSelectionEvent(event.getSource(), selection));
280 }
281 }
282 }
283
284 @Override
285 public void selectionChanged(TimeGraphSelectionEvent event) {
286 ITimeGraphEntry entry = event.getSelection();
287 if (entry != selection) {
288 selection = entry;
289 listener.selectionChanged(new TimeGraphSelectionEvent(event.getSource(), selection));
290 }
291 }
292 }
293
6ac5a950
AM
294 /**
295 * The ViewerFilterWrapper is used to intercept the filler items from
296 * the time graph combo's real ViewerFilters. These filler items should
297 * always be visible.
298 */
299 private class ViewerFilterWrapper extends ViewerFilter {
300
f1fae91f 301 private ViewerFilter fWrappedFilter;
6ac5a950
AM
302
303 ViewerFilterWrapper(ViewerFilter filter) {
304 super();
305 this.fWrappedFilter = filter;
306 }
307
308 @Override
309 public boolean select(Viewer viewer, Object parentElement, Object element) {
310 if (element instanceof ITimeGraphEntry) {
311 return fWrappedFilter.select(viewer, parentElement, element);
312 }
313 return true;
314 }
315
316 }
317
318 /**
f8840316
FR
319 * This filter simply keeps a list of elements that should be filtered out.
320 * All the other elements will be shown.
8f28f9d8 321 * By default and when the list is set to null, all elements are shown.
6ac5a950
AM
322 */
323 private class RawViewerFilter extends ViewerFilter {
324
f8840316 325 private List<Object> fFiltered = null;
6ac5a950 326
f8840316
FR
327 public void setFiltered(List<Object> objects) {
328 fFiltered = objects;
6ac5a950
AM
329 }
330
f8840316
FR
331 public List<Object> getFiltered() {
332 return fFiltered;
6ac5a950
AM
333 }
334
335 @Override
336 public boolean select(Viewer viewer, Object parentElement, Object element) {
f8840316 337 if (fFiltered == null) {
8f28f9d8
PT
338 return true;
339 }
f8840316 340 return !fFiltered.contains(element);
6ac5a950
AM
341 }
342 }
343
837a2f8c
PT
344 // ------------------------------------------------------------------------
345 // Constructors
346 // ------------------------------------------------------------------------
347
348 /**
349 * Constructs a new instance of this class given its parent
350 * and a style value describing its behavior and appearance.
351 *
352 * @param parent a widget which will be the parent of the new instance (cannot be null)
353 * @param style the style of widget to construct
354 */
355 public TimeGraphCombo(Composite parent, int style) {
4999a196
GB
356 this(parent, style, DEFAULT_WEIGHTS);
357 }
358
359 /**
360 * Constructs a new instance of this class given its parent and a style
361 * value describing its behavior and appearance.
362 *
363 * @param parent
364 * a widget which will be the parent of the new instance (cannot
365 * be null)
366 * @param style
367 * the style of widget to construct
368 * @param weights
d2e4afa7 369 * The array (length 2) of relative weights of each side of the sash form
4999a196
GB
370 */
371 public TimeGraphCombo(Composite parent, int style, int[] weights) {
837a2f8c
PT
372 super(parent, style);
373 setLayout(new FillLayout());
374
d2e4afa7 375 fSashForm = new SashForm(this, SWT.NONE);
837a2f8c 376
d2e4afa7 377 fTreeViewer = new TreeViewer(fSashForm, SWT.FULL_SELECTION | SWT.H_SCROLL);
4c9c0c87 378 fTreeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);
837a2f8c
PT
379 final Tree tree = fTreeViewer.getTree();
380 tree.setHeaderVisible(true);
381 tree.setLinesVisible(true);
382
d2e4afa7 383 fTimeGraphViewer = new TimeGraphViewer(fSashForm, SWT.NONE);
837a2f8c
PT
384 fTimeGraphViewer.setItemHeight(getItemHeight(tree));
385 fTimeGraphViewer.setHeaderHeight(tree.getHeaderHeight());
386 fTimeGraphViewer.setBorderWidth(tree.getBorderWidth());
387 fTimeGraphViewer.setNameWidthPref(0);
388
6ac5a950
AM
389 fFilter = new RawViewerFilter();
390 addFilter(fFilter);
391
392 fFilterDialog = new TimeGraphFilterDialog(getShell());
393
837a2f8c
PT
394 // Feature in Windows. The tree vertical bar reappears when
395 // the control is resized so we need to hide it again.
837a2f8c 396 tree.addControlListener(new ControlAdapter() {
f1fae91f 397 private int depth = 0;
837a2f8c
PT
398 @Override
399 public void controlResized(ControlEvent e) {
400 if (depth == 0) {
401 depth++;
402 tree.getVerticalBar().setEnabled(false);
403 // this can trigger controlResized recursively
404 tree.getVerticalBar().setVisible(false);
405 depth--;
406 }
3573a01c
MAL
407 }
408 });
409 // Bug in Linux. The tree header height is 0 in constructor,
410 // so we need to reset it later when the control is painted.
411 // This work around used to be done on control resized but the header
412 // height was not initialized on the initial resize on GTK3.
413 tree.addPaintListener(new PaintListener() {
414 @Override
415 public void paintControl(PaintEvent e) {
416 int headerHeight = tree.getHeaderHeight();
417 if (headerHeight > 0) {
418 fTimeGraphViewer.setHeaderHeight(headerHeight);
419 tree.removePaintListener(this);
420 }
837a2f8c
PT
421 }
422 });
423
424 // ensure synchronization of expanded items between tree and time graph
425 fTreeViewer.addTreeListener(new ITreeViewerListener() {
426 @Override
427 public void treeCollapsed(TreeExpansionEvent event) {
428 fTimeGraphViewer.setExpandedState((ITimeGraphEntry) event.getElement(), false);
588dff10
PT
429 // queue the alignment update because the tree items may only be
430 // actually collapsed after the listeners have been notified
431 fVisibleExpandedItems = null; // invalidate the cache
432 getDisplay().asyncExec(new Runnable() {
433 @Override
434 public void run() {
435 alignTreeItems(true);
436 }});
837a2f8c
PT
437 }
438
439 @Override
440 public void treeExpanded(TreeExpansionEvent event) {
e7708b02
PT
441 ITimeGraphEntry entry = (ITimeGraphEntry) event.getElement();
442 fTimeGraphViewer.setExpandedState(entry, true);
70e10acc 443 Set<Object> expandedElements = new HashSet<>(Arrays.asList(fTreeViewer.getExpandedElements()));
e7708b02 444 for (ITimeGraphEntry child : entry.getChildren()) {
70e10acc
PT
445 if (child.hasChildren()) {
446 boolean expanded = expandedElements.contains(child);
447 fTimeGraphViewer.setExpandedState(child, expanded);
448 }
e7708b02 449 }
588dff10
PT
450 // queue the alignment update because the tree items may only be
451 // actually expanded after the listeners have been notified
452 fVisibleExpandedItems = null; // invalidate the cache
837a2f8c
PT
453 getDisplay().asyncExec(new Runnable() {
454 @Override
455 public void run() {
588dff10 456 alignTreeItems(true);
837a2f8c
PT
457 }});
458 }
459 });
460
461 // ensure synchronization of expanded items between tree and time graph
462 fTimeGraphViewer.addTreeListener(new ITimeGraphTreeListener() {
463 @Override
464 public void treeCollapsed(TimeGraphTreeExpansionEvent event) {
465 fTreeViewer.setExpandedState(event.getEntry(), false);
588dff10 466 alignTreeItems(true);
837a2f8c
PT
467 }
468
469 @Override
470 public void treeExpanded(TimeGraphTreeExpansionEvent event) {
e7708b02
PT
471 ITimeGraphEntry entry = event.getEntry();
472 fTreeViewer.setExpandedState(entry, true);
70e10acc 473 Set<Object> expandedElements = new HashSet<>(Arrays.asList(fTreeViewer.getExpandedElements()));
e7708b02 474 for (ITimeGraphEntry child : entry.getChildren()) {
70e10acc
PT
475 if (child.hasChildren()) {
476 boolean expanded = expandedElements.contains(child);
477 fTimeGraphViewer.setExpandedState(child, expanded);
478 }
e7708b02 479 }
588dff10 480 alignTreeItems(true);
837a2f8c
PT
481 }
482 });
483
484 // prevent mouse button from selecting a filler tree item
485 tree.addListener(SWT.MouseDown, new Listener() {
486 @Override
487 public void handleEvent(Event event) {
488 TreeItem treeItem = tree.getItem(new Point(event.x, event.y));
489 if (treeItem == null || treeItem.getData() == FILLER) {
490 event.doit = false;
588dff10 491 List<TreeItem> treeItems = getVisibleExpandedItems(tree, false);
837a2f8c
PT
492 if (treeItems.size() == 0) {
493 fTreeViewer.setSelection(new StructuredSelection());
494 fTimeGraphViewer.setSelection(null);
495 return;
496 }
497 // this prevents from scrolling up when selecting
498 // the partially visible tree item at the bottom
499 tree.select(treeItems.get(treeItems.size() - 1));
500 fTreeViewer.setSelection(new StructuredSelection());
501 fTimeGraphViewer.setSelection(null);
502 }
503 }
504 });
505
506 // prevent mouse wheel from scrolling down into filler tree items
507 tree.addListener(SWT.MouseWheel, new Listener() {
508 @Override
509 public void handleEvent(Event event) {
510 event.doit = false;
511 Slider scrollBar = fTimeGraphViewer.getVerticalBar();
512 fTimeGraphViewer.setTopIndex(scrollBar.getSelection() - event.count);
588dff10 513 alignTreeItems(false);
837a2f8c
PT
514 }
515 });
516
517 // prevent key stroke from selecting a filler tree item
518 tree.addListener(SWT.KeyDown, new Listener() {
519 @Override
520 public void handleEvent(Event event) {
588dff10 521 List<TreeItem> treeItems = getVisibleExpandedItems(tree, false);
837a2f8c
PT
522 if (treeItems.size() == 0) {
523 fTreeViewer.setSelection(new StructuredSelection());
524 event.doit = false;
525 return;
526 }
527 if (event.keyCode == SWT.ARROW_DOWN) {
528 int index = Math.min(fTimeGraphViewer.getSelectionIndex() + 1, treeItems.size() - 1);
529 fTimeGraphViewer.setSelection((ITimeGraphEntry) treeItems.get(index).getData());
530 event.doit = false;
531 } else if (event.keyCode == SWT.PAGE_DOWN) {
532 int height = tree.getSize().y - tree.getHeaderHeight() - tree.getHorizontalBar().getSize().y;
533 int countPerPage = height / getItemHeight(tree);
534 int index = Math.min(fTimeGraphViewer.getSelectionIndex() + countPerPage - 1, treeItems.size() - 1);
535 fTimeGraphViewer.setSelection((ITimeGraphEntry) treeItems.get(index).getData());
536 event.doit = false;
537 } else if (event.keyCode == SWT.END) {
538 fTimeGraphViewer.setSelection((ITimeGraphEntry) treeItems.get(treeItems.size() - 1).getData());
539 event.doit = false;
540 }
837a2f8c
PT
541 if (fTimeGraphViewer.getSelectionIndex() >= 0) {
542 fTreeViewer.setSelection(new StructuredSelection(fTimeGraphViewer.getSelection()));
543 } else {
544 fTreeViewer.setSelection(new StructuredSelection());
545 }
588dff10 546 alignTreeItems(false);
837a2f8c
PT
547 }
548 });
549
550 // ensure alignment of top item between tree and time graph
551 fTimeGraphViewer.getTimeGraphControl().addControlListener(new ControlAdapter() {
552 @Override
553 public void controlResized(ControlEvent e) {
588dff10 554 alignTreeItems(false);
837a2f8c
PT
555 }
556 });
557
558 // ensure synchronization of selected item between tree and time graph
559 fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
560 @Override
561 public void selectionChanged(SelectionChangedEvent event) {
562 if (fInhibitTreeSelection) {
563 return;
564 }
565 if (event.getSelection() instanceof IStructuredSelection) {
566 Object selection = ((IStructuredSelection) event.getSelection()).getFirstElement();
567 if (selection instanceof ITimeGraphEntry) {
568 fTimeGraphViewer.setSelection((ITimeGraphEntry) selection);
569 }
588dff10 570 alignTreeItems(false);
837a2f8c
PT
571 }
572 }
573 });
574
575 // ensure synchronization of selected item between tree and time graph
576 fTimeGraphViewer.addSelectionListener(new ITimeGraphSelectionListener() {
577 @Override
578 public void selectionChanged(TimeGraphSelectionEvent event) {
579 ITimeGraphEntry entry = fTimeGraphViewer.getSelection();
580 fInhibitTreeSelection = true; // block the tree selection changed listener
581 if (entry != null) {
582 StructuredSelection selection = new StructuredSelection(entry);
583 fTreeViewer.setSelection(selection);
584 } else {
585 fTreeViewer.setSelection(new StructuredSelection());
586 }
587 fInhibitTreeSelection = false;
588dff10 588 alignTreeItems(false);
837a2f8c
PT
589 }
590 });
591
592 // ensure alignment of top item between tree and time graph
593 fTimeGraphViewer.getVerticalBar().addSelectionListener(new SelectionAdapter() {
594 @Override
595 public void widgetSelected(SelectionEvent e) {
588dff10 596 alignTreeItems(false);
837a2f8c
PT
597 }
598 });
599
600 // ensure alignment of top item between tree and time graph
601 fTimeGraphViewer.getTimeGraphControl().addMouseWheelListener(new MouseWheelListener() {
602 @Override
603 public void mouseScrolled(MouseEvent e) {
588dff10 604 alignTreeItems(false);
837a2f8c
PT
605 }
606 });
607
608 // ensure the tree has focus control when mouse is over it if the time graph had control
609 fTreeViewer.getControl().addMouseTrackListener(new MouseTrackAdapter() {
610 @Override
611 public void mouseEnter(MouseEvent e) {
612 if (fTimeGraphViewer.getTimeGraphControl().isFocusControl()) {
613 fTreeViewer.getControl().setFocus();
614 }
615 }
616 });
617
618 // ensure the time graph has focus control when mouse is over it if the tree had control
619 fTimeGraphViewer.getTimeGraphControl().addMouseTrackListener(new MouseTrackAdapter() {
620 @Override
621 public void mouseEnter(MouseEvent e) {
622 if (fTreeViewer.getControl().isFocusControl()) {
623 fTimeGraphViewer.getTimeGraphControl().setFocus();
624 }
625 }
626 });
627 fTimeGraphViewer.getTimeGraphScale().addMouseTrackListener(new MouseTrackAdapter() {
628 @Override
629 public void mouseEnter(MouseEvent e) {
630 if (fTreeViewer.getControl().isFocusControl()) {
631 fTimeGraphViewer.getTimeGraphControl().setFocus();
632 }
633 }
634 });
635
636 // The filler rows are required to ensure alignment when the tree does not have a
637 // visible horizontal scroll bar. The tree does not allow its top item to be set
638 // to a value that would cause blank space to be drawn at the bottom of the tree.
639 fNumFillerRows = Display.getDefault().getBounds().height / getItemHeight(tree);
640
d2e4afa7
MAL
641 fSashForm.setWeights(weights);
642
643 fTimeGraphViewer.getTimeGraphControl().addPaintListener(new PaintListener() {
644 @Override
645 public void paintControl(PaintEvent e) {
646 // Sashes in a SashForm are being created on layout so add the
647 // drag listener here
648 if (fSashDragListener == null) {
649 for (Control control : fSashForm.getChildren()) {
650 if (control instanceof Sash) {
651 fSashDragListener = new Listener() {
652
653 @Override
654 public void handleEvent(Event event) {
655 sendTimeViewAlignmentChanged();
656
657 }
658 };
659 control.removePaintListener(this);
660 control.addListener(SWT.Selection, fSashDragListener);
661 // There should be only one sash
662 break;
663 }
664 }
665 }
666 }
667 });
668 }
669
670 private void sendTimeViewAlignmentChanged() {
671 TmfSignalManager.dispatchSignal(new TmfTimeViewAlignmentSignal(fSashForm, getTimeViewAlignmentInfo()));
837a2f8c
PT
672 }
673
674 // ------------------------------------------------------------------------
675 // Accessors
676 // ------------------------------------------------------------------------
677
678 /**
679 * Returns this time graph combo's tree viewer.
680 *
681 * @return the tree viewer
682 */
683 public TreeViewer getTreeViewer() {
684 return fTreeViewer;
685 }
686
687 /**
688 * Returns this time graph combo's time graph viewer.
689 *
690 * @return the time graph viewer
691 */
dfa0ef96 692 public @NonNull TimeGraphViewer getTimeGraphViewer() {
837a2f8c
PT
693 return fTimeGraphViewer;
694 }
695
6ac5a950
AM
696 /**
697 * Callback for the show filter action
6ac5a950
AM
698 */
699 public void showFilterDialog() {
4c9c0c87
PT
700 ITimeGraphEntry[] topInput = fTimeGraphViewer.getTimeGraphContentProvider().getElements(fTimeGraphViewer.getInput());
701 if (topInput != null) {
702 List<? extends ITimeGraphEntry> allElements = listAllInputs(Arrays.asList(topInput));
703 fFilterDialog.setInput(fTimeGraphViewer.getInput());
6ac5a950
AM
704 fFilterDialog.setTitle(Messages.TmfTimeFilterDialog_WINDOW_TITLE);
705 fFilterDialog.setMessage(Messages.TmfTimeFilterDialog_MESSAGE);
8f28f9d8 706 fFilterDialog.setExpandedElements(allElements.toArray());
f8840316 707 if (fFilter.getFiltered() != null) {
507b1336 708 ArrayList<? extends ITimeGraphEntry> nonFilteredElements = new ArrayList<>(allElements);
f8840316
FR
709 nonFilteredElements.removeAll(fFilter.getFiltered());
710 fFilterDialog.setInitialElementSelections(nonFilteredElements);
8f28f9d8
PT
711 } else {
712 fFilterDialog.setInitialElementSelections(allElements);
713 }
6ac5a950
AM
714 fFilterDialog.create();
715 fFilterDialog.open();
716 // Process selected elements
717 if (fFilterDialog.getResult() != null) {
718 fInhibitTreeSelection = true;
8f28f9d8 719 if (fFilterDialog.getResult().length != allElements.size()) {
f8840316
FR
720 ArrayList<Object> filteredElements = new ArrayList<Object>(allElements);
721 filteredElements.removeAll(Arrays.asList(fFilterDialog.getResult()));
722 fFilter.setFiltered(filteredElements);
8f28f9d8 723 } else {
f8840316 724 fFilter.setFiltered(null);
8f28f9d8 725 }
6ac5a950
AM
726 fTreeViewer.refresh();
727 fTreeViewer.expandAll();
728 fTimeGraphViewer.refresh();
ece2fc5f 729 fTimeGraphViewer.expandAll();
6ac5a950 730 fInhibitTreeSelection = false;
588dff10 731 alignTreeItems(true);
40b7b614 732 // Reset selection
6ac5a950 733 if (fFilterDialog.getResult().length > 0) {
40b7b614 734 setSelection(null);
6ac5a950
AM
735 }
736 }
737 }
738 }
739
740 /**
741 * Get the show filter action.
742 *
743 * @return The Action object
6ac5a950
AM
744 */
745 public Action getShowFilterAction() {
746 if (showFilterAction == null) {
747 // showFilter
748 showFilterAction = new Action() {
749 @Override
750 public void run() {
751 showFilterDialog();
752 }
753 };
754 showFilterAction.setText(Messages.TmfTimeGraphCombo_FilterActionNameText);
755 showFilterAction.setToolTipText(Messages.TmfTimeGraphCombo_FilterActionToolTipText);
756 // TODO find a nice, distinctive icon
757 showFilterAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_FILTERS));
758 }
759
760 return showFilterAction;
761 }
762
837a2f8c
PT
763 // ------------------------------------------------------------------------
764 // Control
765 // ------------------------------------------------------------------------
766
837a2f8c
PT
767 @Override
768 public void redraw() {
769 fTimeGraphViewer.getControl().redraw();
770 super.redraw();
771 }
772
773 // ------------------------------------------------------------------------
774 // Operations
775 // ------------------------------------------------------------------------
776
777 /**
778 * Sets the tree content provider used by this time graph combo.
779 *
780 * @param contentProvider the tree content provider
781 */
782 public void setTreeContentProvider(ITreeContentProvider contentProvider) {
783 fTreeViewer.setContentProvider(new TreeContentProviderWrapper(contentProvider));
784 }
785
786 /**
787 * Sets the tree label provider used by this time graph combo.
788 *
789 * @param labelProvider the tree label provider
790 */
791 public void setTreeLabelProvider(ITableLabelProvider labelProvider) {
792 fTreeViewer.setLabelProvider(new TreeLabelProviderWrapper(labelProvider));
793 }
794
6ac5a950
AM
795 /**
796 * Sets the tree content provider used by the filter dialog
797 *
798 * @param contentProvider the tree content provider
6ac5a950
AM
799 */
800 public void setFilterContentProvider(ITreeContentProvider contentProvider) {
801 fFilterDialog.setContentProvider(contentProvider);
802 }
803
804 /**
805 * Sets the tree label provider used by the filter dialog
806 *
807 * @param labelProvider the tree label provider
6ac5a950
AM
808 */
809 public void setFilterLabelProvider(ITableLabelProvider labelProvider) {
810 fFilterDialog.setLabelProvider(labelProvider);
811 }
812
b97d61f0
CM
813 /**
814 * Adds a "check active" button used by the filter dialog
815 *
816 * @param activeProvider
817 * Additional button info specific to a certain view.
818 * @since 1.0
819 */
820 public void addTimeGraphFilterCheckActiveButton(ITimeGraphEntryActiveProvider activeProvider) {
821 fFilterDialog.addTimeGraphFilterCheckActiveButton(activeProvider);
822 }
823
824 /**
825 * Adds an "uncheck inactive" button used by the filter dialog
826 *
827 * @param inactiveProvider
828 * Additional button info specific to a certain view.
829 * @since 1.0
830 */
831 public void addTimeGraphFilterUncheckInactiveButton(ITimeGraphEntryActiveProvider inactiveProvider) {
832 fFilterDialog.addTimeGraphFilterUncheckInactiveButton(inactiveProvider);
833 }
834
837a2f8c
PT
835 /**
836 * Sets the tree columns for this time graph combo.
837 *
838 * @param columnNames the tree column names
839 */
840 public void setTreeColumns(String[] columnNames) {
841 final Tree tree = fTreeViewer.getTree();
842 for (String columnName : columnNames) {
843 TreeColumn column = new TreeColumn(tree, SWT.LEFT);
844 column.setText(columnName);
845 column.pack();
846 }
847 }
848
6ac5a950
AM
849 /**
850 * Sets the tree columns for this time graph combo's filter dialog.
851 *
852 * @param columnNames the tree column names
6ac5a950
AM
853 */
854 public void setFilterColumns(String[] columnNames) {
855 fFilterDialog.setColumnNames(columnNames);
856 }
857
837a2f8c 858 /**
4c9c0c87
PT
859 * Sets the time graph content provider used by this time graph combo.
860 *
861 * @param timeGraphContentProvider
862 * the time graph content provider
4c9c0c87
PT
863 */
864 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider) {
865 fTimeGraphViewer.setTimeGraphContentProvider(timeGraphContentProvider);
866 }
867
868 /**
869 * Sets the time graph presentation provider used by this time graph combo.
837a2f8c
PT
870 *
871 * @param timeGraphProvider the time graph provider
872 */
873 public void setTimeGraphProvider(ITimeGraphPresentationProvider timeGraphProvider) {
874 fTimeGraphViewer.setTimeGraphProvider(timeGraphProvider);
875 }
876
877 /**
878 * Sets or clears the input for this time graph combo.
837a2f8c
PT
879 *
880 * @param input the input of this time graph combo, or <code>null</code> if none
881 */
4c9c0c87 882 public void setInput(Object input) {
f8840316 883 fFilter.setFiltered(null);
837a2f8c
PT
884 fInhibitTreeSelection = true;
885 fTreeViewer.setInput(input);
886 for (SelectionListenerWrapper listenerWrapper : fSelectionListenerMap.values()) {
887 listenerWrapper.selection = null;
888 }
889 fInhibitTreeSelection = false;
837a2f8c
PT
890 fTreeViewer.getTree().getVerticalBar().setEnabled(false);
891 fTreeViewer.getTree().getVerticalBar().setVisible(false);
837a2f8c 892 fTimeGraphViewer.setInput(input);
63b93cd6 893 fTimeGraphViewer.setItemHeight(getItemHeight(fTreeViewer.getTree()));
588dff10
PT
894 // queue the alignment update because in Linux the item bounds are not
895 // set properly until the tree has been painted at least once
896 fVisibleExpandedItems = null; // invalidate the cache
897 getDisplay().asyncExec(new Runnable() {
898 @Override
899 public void run() {
900 alignTreeItems(true);
901 }});
837a2f8c
PT
902 }
903
4c9c0c87
PT
904 /**
905 * Gets the input for this time graph combo.
906 *
907 * @return The input of this time graph combo, or <code>null</code> if none
4c9c0c87
PT
908 */
909 public Object getInput() {
910 return fTreeViewer.getInput();
911 }
912
bec1f1ac
GB
913 /**
914 * Sets or clears the list of links to display on this combo
915 *
916 * @param links the links to display in this time graph combo
bec1f1ac
GB
917 */
918 public void setLinks(List<ILinkEvent> links) {
919 fTimeGraphViewer.setLinks(links);
920 }
921
6ac5a950
AM
922 /**
923 * @param filter The filter object to be attached to the view
6ac5a950
AM
924 */
925 public void addFilter(ViewerFilter filter) {
926 ViewerFilter wrapper = new ViewerFilterWrapper(filter);
927 fTreeViewer.addFilter(wrapper);
928 fTimeGraphViewer.addFilter(wrapper);
929 fViewerFilterMap.put(filter, wrapper);
588dff10 930 alignTreeItems(true);
6ac5a950
AM
931 }
932
933 /**
934 * @param filter The filter object to be removed from the view
6ac5a950
AM
935 */
936 public void removeFilter(ViewerFilter filter) {
937 ViewerFilter wrapper = fViewerFilterMap.get(filter);
938 fTreeViewer.removeFilter(wrapper);
939 fTimeGraphViewer.removeFilter(wrapper);
940 fViewerFilterMap.remove(filter);
588dff10 941 alignTreeItems(true);
6ac5a950
AM
942 }
943
837a2f8c
PT
944 /**
945 * Refreshes this time graph completely with information freshly obtained from its model.
946 */
947 public void refresh() {
948 fInhibitTreeSelection = true;
4c9c0c87 949 Tree tree = fTreeViewer.getTree();
ece2fc5f
PT
950 try {
951 tree.setRedraw(false);
952 fTreeViewer.refresh();
ece2fc5f
PT
953 } finally {
954 tree.setRedraw(true);
955 }
837a2f8c 956 fTimeGraphViewer.refresh();
588dff10 957 alignTreeItems(true);
837a2f8c
PT
958 fInhibitTreeSelection = false;
959 }
960
961 /**
962 * Adds a listener for selection changes in this time graph combo.
963 *
964 * @param listener a selection listener
965 */
966 public void addSelectionListener(ITimeGraphSelectionListener listener) {
967 SelectionListenerWrapper listenerWrapper = new SelectionListenerWrapper(listener);
968 fTreeViewer.addSelectionChangedListener(listenerWrapper);
969 fSelectionListenerMap.put(listener, listenerWrapper);
970 fTimeGraphViewer.addSelectionListener(listenerWrapper);
971 }
972
973 /**
974 * Removes the given selection listener from this time graph combo.
975 *
976 * @param listener a selection changed listener
977 */
978 public void removeSelectionListener(ITimeGraphSelectionListener listener) {
979 SelectionListenerWrapper listenerWrapper = fSelectionListenerMap.remove(listener);
980 fTreeViewer.removeSelectionChangedListener(listenerWrapper);
981 fTimeGraphViewer.removeSelectionListener(listenerWrapper);
982 }
983
984 /**
985 * Sets the current selection for this time graph combo.
986 *
987 * @param selection the new selection
988 */
989 public void setSelection(ITimeGraphEntry selection) {
990 fTimeGraphViewer.setSelection(selection);
991 fInhibitTreeSelection = true; // block the tree selection changed listener
992 if (selection != null) {
993 StructuredSelection structuredSelection = new StructuredSelection(selection);
994 fTreeViewer.setSelection(structuredSelection);
995 } else {
996 fTreeViewer.setSelection(new StructuredSelection());
997 }
998 fInhibitTreeSelection = false;
588dff10 999 alignTreeItems(false);
837a2f8c
PT
1000 }
1001
f4617471 1002 /**
df0e3d5f
PT
1003 * Sets the auto-expand level to be used for new entries discovered when
1004 * calling {@link #setInput(Object)} or {@link #refresh()}. The value 0
1005 * means that there is no auto-expand; 1 means that top-level entries are
1006 * expanded, but not their children; 2 means that top-level entries are
1007 * expanded, and their children, but not grand-children; and so on.
f4617471
PT
1008 * <p>
1009 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
1010 * </p>
df0e3d5f 1011 *
f4617471
PT
1012 * @param level
1013 * non-negative level, or <code>ALL_LEVELS</code> to expand all
1014 * levels of the tree
f4617471
PT
1015 */
1016 public void setAutoExpandLevel(int level) {
1017 fTimeGraphViewer.setAutoExpandLevel(level);
1018 if (level <= 0) {
1019 fTreeViewer.setAutoExpandLevel(level);
1020 } else {
1021 fTreeViewer.setAutoExpandLevel(level + 1);
1022 }
1023 }
1024
1025 /**
1026 * Returns the auto-expand level.
1027 *
1028 * @return non-negative level, or <code>ALL_LEVELS</code> if all levels of
1029 * the tree are expanded automatically
1030 * @see #setAutoExpandLevel
f4617471
PT
1031 */
1032 public int getAutoExpandLevel() {
1033 return fTimeGraphViewer.getAutoExpandLevel();
1034 }
1035
837a2f8c
PT
1036 /**
1037 * Set the expanded state of an entry
1038 *
1039 * @param entry
1040 * The entry to expand/collapse
1041 * @param expanded
1042 * True for expanded, false for collapsed
837a2f8c
PT
1043 */
1044 public void setExpandedState(ITimeGraphEntry entry, boolean expanded) {
1045 fTimeGraphViewer.setExpandedState(entry, expanded);
1046 fTreeViewer.setExpandedState(entry, expanded);
588dff10 1047 alignTreeItems(true);
837a2f8c
PT
1048 }
1049
1050 /**
1051 * Collapses all nodes of the viewer's tree, starting with the root.
837a2f8c
PT
1052 */
1053 public void collapseAll() {
1054 fTimeGraphViewer.collapseAll();
1055 fTreeViewer.collapseAll();
588dff10 1056 alignTreeItems(true);
837a2f8c
PT
1057 }
1058
1059 /**
1060 * Expands all nodes of the viewer's tree, starting with the root.
837a2f8c
PT
1061 */
1062 public void expandAll() {
1063 fTimeGraphViewer.expandAll();
1064 fTreeViewer.expandAll();
588dff10 1065 alignTreeItems(true);
837a2f8c
PT
1066 }
1067
1068 // ------------------------------------------------------------------------
1069 // Internal
1070 // ------------------------------------------------------------------------
1071
588dff10
PT
1072 private List<TreeItem> getVisibleExpandedItems(Tree tree, boolean refresh) {
1073 if (fVisibleExpandedItems == null || refresh) {
df0e3d5f
PT
1074 List<TreeItem> visibleExpandedItems = new ArrayList<>();
1075 addVisibleExpandedItems(visibleExpandedItems, tree.getItems());
1076 fVisibleExpandedItems = visibleExpandedItems;
837a2f8c 1077 }
588dff10 1078 return fVisibleExpandedItems;
837a2f8c
PT
1079 }
1080
df0e3d5f
PT
1081 private void addVisibleExpandedItems(List<TreeItem> visibleExpandedItems, TreeItem[] items) {
1082 for (TreeItem item : items) {
1083 Object data = item.getData();
1084 if (data == FILLER) {
1085 break;
1086 }
1087 visibleExpandedItems.add(item);
1088 boolean expandedState = fTimeGraphViewer.getExpandedState((ITimeGraphEntry) data);
1089 if (item.getExpanded() != expandedState) {
1090 /* synchronize the expanded state of both viewers */
1091 fTreeViewer.setExpandedState(data, expandedState);
1092 }
1093 if (expandedState) {
1094 addVisibleExpandedItems(visibleExpandedItems, item.getItems());
837a2f8c
PT
1095 }
1096 }
837a2f8c
PT
1097 }
1098
6ac5a950
AM
1099 /**
1100 * Explores the list of top-level inputs and returns all the inputs
1101 *
1102 * @param inputs The top-level inputs
1103 * @return All the inputs
1104 */
1105 private List<? extends ITimeGraphEntry> listAllInputs(List<? extends ITimeGraphEntry> inputs) {
507b1336 1106 ArrayList<ITimeGraphEntry> items = new ArrayList<>();
6ac5a950
AM
1107 for (ITimeGraphEntry entry : inputs) {
1108 items.add(entry);
1109 if (entry.hasChildren()) {
1110 items.addAll(listAllInputs(entry.getChildren()));
1111 }
1112 }
1113 return items;
1114 }
1115
837a2f8c
PT
1116 private int getItemHeight(final Tree tree) {
1117 /*
1118 * Bug in Linux. The method getItemHeight doesn't always return the correct value.
1119 */
1120 if (fLinuxItemHeight >= 0 && System.getProperty("os.name").contains("Linux")) { //$NON-NLS-1$ //$NON-NLS-2$
1121 if (fLinuxItemHeight != 0) {
1122 return fLinuxItemHeight;
1123 }
ff2990ed
BH
1124
1125 if (getVisibleExpandedItems(tree, true).size() > 1) {
837a2f8c
PT
1126 PaintListener paintListener = new PaintListener() {
1127 @Override
1128 public void paintControl(PaintEvent e) {
ff2990ed
BH
1129 // get the treeItems here to have all items
1130 List<TreeItem> treeItems = getVisibleExpandedItems(tree, true);
1131 if (treeItems.size() < 2) {
1132 return;
1133 }
1134 final TreeItem treeItem0 = treeItems.get(0);
1135 final TreeItem treeItem1 = treeItems.get(1);
837a2f8c
PT
1136 tree.removePaintListener(this);
1137 int y0 = treeItem0.getBounds().y;
1138 int y1 = treeItem1.getBounds().y;
1139 int itemHeight = y1 - y0;
1140 if (itemHeight > 0) {
1141 fLinuxItemHeight = itemHeight;
1142 fTimeGraphViewer.setItemHeight(itemHeight);
1143 }
1144 }
1145 };
1146 tree.addPaintListener(paintListener);
1147 }
1148 } else {
1149 fLinuxItemHeight = -1; // Not Linux, don't perform os.name check anymore
1150 }
1151 return tree.getItemHeight();
1152 }
1153
588dff10
PT
1154 private void alignTreeItems(boolean refreshExpandedItems) {
1155 // align the tree top item with the time graph top item
1156 Tree tree = fTreeViewer.getTree();
1157 List<TreeItem> treeItems = getVisibleExpandedItems(tree, refreshExpandedItems);
1158 int topIndex = fTimeGraphViewer.getTopIndex();
1159 if (topIndex >= treeItems.size()) {
1160 return;
1161 }
1162 TreeItem item = treeItems.get(topIndex);
1163 tree.setTopItem(item);
1164
1165 // ensure the time graph item heights are equal to the tree item heights
1166 int treeHeight = fTreeViewer.getTree().getBounds().height;
1167 int index = topIndex;
1168 Rectangle bounds = item.getBounds();
1169 while (index < treeItems.size() - 1) {
1170 if (bounds.y > treeHeight) {
1171 break;
1172 }
1173 /*
1174 * Bug in Linux. The method getBounds doesn't always return the correct height.
1175 * Use the difference of y position between items to calculate the height.
1176 */
1177 TreeItem nextItem = treeItems.get(index + 1);
1178 Rectangle nextBounds = nextItem.getBounds();
1179 Integer itemHeight = nextBounds.y - bounds.y;
63b93cd6 1180 if (itemHeight > 0) {
588dff10 1181 ITimeGraphEntry entry = (ITimeGraphEntry) item.getData();
63b93cd6 1182 fTimeGraphViewer.getTimeGraphControl().setItemHeight(entry, itemHeight);
588dff10
PT
1183 }
1184 index++;
1185 item = nextItem;
1186 bounds = nextBounds;
1187 }
1188 }
1189
d2e4afa7
MAL
1190 /**
1191 * Return the time alignment information
1192 *
1193 * @return the time alignment information
1194 *
1195 * @see ITmfTimeAligned
1196 *
1197 * @since 1.0
1198 */
1199 public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
d2e4afa7 1200 Point location = fSashForm.toDisplay(0, 0);
2e23a015
PT
1201 int timeAxisOffset = fTreeViewer.getControl().getSize().x + fSashForm.getSashWidth();
1202 return new TmfTimeViewAlignmentInfo(fSashForm.getShell(), location, timeAxisOffset);
d2e4afa7
MAL
1203 }
1204
1205 /**
1206 * Return the available width for the time-axis.
1207 *
1208 * @see ITmfTimeAligned
1209 *
1210 * @param requestedOffset
1211 * the requested offset
1212 * @return the available width for the time-axis
1213 *
1214 * @since 1.0
1215 */
1216 public int getAvailableWidth(int requestedOffset) {
89316ebe 1217 int vBarWidth = ((fTimeGraphViewer.getVerticalBar() != null) && (fTimeGraphViewer.getVerticalBar().isVisible())) ? fTimeGraphViewer.getVerticalBar().getSize().x : 0;
d2e4afa7 1218 int totalWidth = fSashForm.getBounds().width;
89316ebe 1219 return Math.min(totalWidth, Math.max(0, totalWidth - requestedOffset - vBarWidth));
d2e4afa7
MAL
1220 }
1221
1222 /**
1223 * Perform the alignment operation.
1224 *
1225 * @param offset
1226 * the alignment offset
1227 * @param width
1228 * the alignment width
1229 *
1230 * @see ITmfTimeAligned
1231 *
1232 * @since 1.0
1233 */
1234 public void performAlign(int offset, int width) {
1235 int total = fSashForm.getBounds().width;
1236 int timeAxisOffset = Math.min(offset, total);
c34ab48a
PT
1237 int width1 = Math.max(0, timeAxisOffset - fSashForm.getSashWidth());
1238 int width2 = total - timeAxisOffset;
1239 fSashForm.setWeights(new int[] { width1, width2 });
d2e4afa7
MAL
1240 fSashForm.layout();
1241
1242 Composite composite = fTimeGraphViewer.getTimeAlignedComposite();
1243 GridLayout layout = (GridLayout) composite.getLayout();
1244 int timeBasedControlsWidth = composite.getSize().x;
1245 int marginSize = timeBasedControlsWidth - width;
1246 layout.marginRight = Math.max(0, marginSize);
1247 composite.layout();
1248 }
837a2f8c 1249}
This page took 0.163028 seconds and 5 git commands to generate.