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