tmf: Align the time-axis of time chart views
[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.
398 // Bug in Linux. The tree header height is 0 in constructor,
399 // so we need to reset it later when the control is resized.
400 tree.addControlListener(new ControlAdapter() {
f1fae91f 401 private int depth = 0;
837a2f8c
PT
402 @Override
403 public void controlResized(ControlEvent e) {
404 if (depth == 0) {
405 depth++;
406 tree.getVerticalBar().setEnabled(false);
407 // this can trigger controlResized recursively
408 tree.getVerticalBar().setVisible(false);
409 depth--;
410 }
411 fTimeGraphViewer.setHeaderHeight(tree.getHeaderHeight());
412 }
413 });
414
415 // ensure synchronization of expanded items between tree and time graph
416 fTreeViewer.addTreeListener(new ITreeViewerListener() {
417 @Override
418 public void treeCollapsed(TreeExpansionEvent event) {
419 fTimeGraphViewer.setExpandedState((ITimeGraphEntry) event.getElement(), false);
588dff10
PT
420 // queue the alignment update because the tree items may only be
421 // actually collapsed after the listeners have been notified
422 fVisibleExpandedItems = null; // invalidate the cache
423 getDisplay().asyncExec(new Runnable() {
424 @Override
425 public void run() {
426 alignTreeItems(true);
427 }});
837a2f8c
PT
428 }
429
430 @Override
431 public void treeExpanded(TreeExpansionEvent event) {
e7708b02
PT
432 ITimeGraphEntry entry = (ITimeGraphEntry) event.getElement();
433 fTimeGraphViewer.setExpandedState(entry, true);
70e10acc 434 Set<Object> expandedElements = new HashSet<>(Arrays.asList(fTreeViewer.getExpandedElements()));
e7708b02 435 for (ITimeGraphEntry child : entry.getChildren()) {
70e10acc
PT
436 if (child.hasChildren()) {
437 boolean expanded = expandedElements.contains(child);
438 fTimeGraphViewer.setExpandedState(child, expanded);
439 }
e7708b02 440 }
588dff10
PT
441 // queue the alignment update because the tree items may only be
442 // actually expanded after the listeners have been notified
443 fVisibleExpandedItems = null; // invalidate the cache
837a2f8c
PT
444 getDisplay().asyncExec(new Runnable() {
445 @Override
446 public void run() {
588dff10 447 alignTreeItems(true);
837a2f8c
PT
448 }});
449 }
450 });
451
452 // ensure synchronization of expanded items between tree and time graph
453 fTimeGraphViewer.addTreeListener(new ITimeGraphTreeListener() {
454 @Override
455 public void treeCollapsed(TimeGraphTreeExpansionEvent event) {
456 fTreeViewer.setExpandedState(event.getEntry(), false);
588dff10 457 alignTreeItems(true);
837a2f8c
PT
458 }
459
460 @Override
461 public void treeExpanded(TimeGraphTreeExpansionEvent event) {
e7708b02
PT
462 ITimeGraphEntry entry = event.getEntry();
463 fTreeViewer.setExpandedState(entry, true);
70e10acc 464 Set<Object> expandedElements = new HashSet<>(Arrays.asList(fTreeViewer.getExpandedElements()));
e7708b02 465 for (ITimeGraphEntry child : entry.getChildren()) {
70e10acc
PT
466 if (child.hasChildren()) {
467 boolean expanded = expandedElements.contains(child);
468 fTimeGraphViewer.setExpandedState(child, expanded);
469 }
e7708b02 470 }
588dff10 471 alignTreeItems(true);
837a2f8c
PT
472 }
473 });
474
475 // prevent mouse button from selecting a filler tree item
476 tree.addListener(SWT.MouseDown, new Listener() {
477 @Override
478 public void handleEvent(Event event) {
479 TreeItem treeItem = tree.getItem(new Point(event.x, event.y));
480 if (treeItem == null || treeItem.getData() == FILLER) {
481 event.doit = false;
588dff10 482 List<TreeItem> treeItems = getVisibleExpandedItems(tree, false);
837a2f8c
PT
483 if (treeItems.size() == 0) {
484 fTreeViewer.setSelection(new StructuredSelection());
485 fTimeGraphViewer.setSelection(null);
486 return;
487 }
488 // this prevents from scrolling up when selecting
489 // the partially visible tree item at the bottom
490 tree.select(treeItems.get(treeItems.size() - 1));
491 fTreeViewer.setSelection(new StructuredSelection());
492 fTimeGraphViewer.setSelection(null);
493 }
494 }
495 });
496
497 // prevent mouse wheel from scrolling down into filler tree items
498 tree.addListener(SWT.MouseWheel, new Listener() {
499 @Override
500 public void handleEvent(Event event) {
501 event.doit = false;
502 Slider scrollBar = fTimeGraphViewer.getVerticalBar();
503 fTimeGraphViewer.setTopIndex(scrollBar.getSelection() - event.count);
588dff10 504 alignTreeItems(false);
837a2f8c
PT
505 }
506 });
507
508 // prevent key stroke from selecting a filler tree item
509 tree.addListener(SWT.KeyDown, new Listener() {
510 @Override
511 public void handleEvent(Event event) {
588dff10 512 List<TreeItem> treeItems = getVisibleExpandedItems(tree, false);
837a2f8c
PT
513 if (treeItems.size() == 0) {
514 fTreeViewer.setSelection(new StructuredSelection());
515 event.doit = false;
516 return;
517 }
518 if (event.keyCode == SWT.ARROW_DOWN) {
519 int index = Math.min(fTimeGraphViewer.getSelectionIndex() + 1, treeItems.size() - 1);
520 fTimeGraphViewer.setSelection((ITimeGraphEntry) treeItems.get(index).getData());
521 event.doit = false;
522 } else if (event.keyCode == SWT.PAGE_DOWN) {
523 int height = tree.getSize().y - tree.getHeaderHeight() - tree.getHorizontalBar().getSize().y;
524 int countPerPage = height / getItemHeight(tree);
525 int index = Math.min(fTimeGraphViewer.getSelectionIndex() + countPerPage - 1, treeItems.size() - 1);
526 fTimeGraphViewer.setSelection((ITimeGraphEntry) treeItems.get(index).getData());
527 event.doit = false;
528 } else if (event.keyCode == SWT.END) {
529 fTimeGraphViewer.setSelection((ITimeGraphEntry) treeItems.get(treeItems.size() - 1).getData());
530 event.doit = false;
531 }
837a2f8c
PT
532 if (fTimeGraphViewer.getSelectionIndex() >= 0) {
533 fTreeViewer.setSelection(new StructuredSelection(fTimeGraphViewer.getSelection()));
534 } else {
535 fTreeViewer.setSelection(new StructuredSelection());
536 }
588dff10 537 alignTreeItems(false);
837a2f8c
PT
538 }
539 });
540
541 // ensure alignment of top item between tree and time graph
542 fTimeGraphViewer.getTimeGraphControl().addControlListener(new ControlAdapter() {
543 @Override
544 public void controlResized(ControlEvent e) {
588dff10 545 alignTreeItems(false);
837a2f8c
PT
546 }
547 });
548
549 // ensure synchronization of selected item between tree and time graph
550 fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
551 @Override
552 public void selectionChanged(SelectionChangedEvent event) {
553 if (fInhibitTreeSelection) {
554 return;
555 }
556 if (event.getSelection() instanceof IStructuredSelection) {
557 Object selection = ((IStructuredSelection) event.getSelection()).getFirstElement();
558 if (selection instanceof ITimeGraphEntry) {
559 fTimeGraphViewer.setSelection((ITimeGraphEntry) selection);
560 }
588dff10 561 alignTreeItems(false);
837a2f8c
PT
562 }
563 }
564 });
565
566 // ensure synchronization of selected item between tree and time graph
567 fTimeGraphViewer.addSelectionListener(new ITimeGraphSelectionListener() {
568 @Override
569 public void selectionChanged(TimeGraphSelectionEvent event) {
570 ITimeGraphEntry entry = fTimeGraphViewer.getSelection();
571 fInhibitTreeSelection = true; // block the tree selection changed listener
572 if (entry != null) {
573 StructuredSelection selection = new StructuredSelection(entry);
574 fTreeViewer.setSelection(selection);
575 } else {
576 fTreeViewer.setSelection(new StructuredSelection());
577 }
578 fInhibitTreeSelection = false;
588dff10 579 alignTreeItems(false);
837a2f8c
PT
580 }
581 });
582
583 // ensure alignment of top item between tree and time graph
584 fTimeGraphViewer.getVerticalBar().addSelectionListener(new SelectionAdapter() {
585 @Override
586 public void widgetSelected(SelectionEvent e) {
588dff10 587 alignTreeItems(false);
837a2f8c
PT
588 }
589 });
590
591 // ensure alignment of top item between tree and time graph
592 fTimeGraphViewer.getTimeGraphControl().addMouseWheelListener(new MouseWheelListener() {
593 @Override
594 public void mouseScrolled(MouseEvent e) {
588dff10 595 alignTreeItems(false);
837a2f8c
PT
596 }
597 });
598
599 // ensure the tree has focus control when mouse is over it if the time graph had control
600 fTreeViewer.getControl().addMouseTrackListener(new MouseTrackAdapter() {
601 @Override
602 public void mouseEnter(MouseEvent e) {
603 if (fTimeGraphViewer.getTimeGraphControl().isFocusControl()) {
604 fTreeViewer.getControl().setFocus();
605 }
606 }
607 });
608
609 // ensure the time graph has focus control when mouse is over it if the tree had control
610 fTimeGraphViewer.getTimeGraphControl().addMouseTrackListener(new MouseTrackAdapter() {
611 @Override
612 public void mouseEnter(MouseEvent e) {
613 if (fTreeViewer.getControl().isFocusControl()) {
614 fTimeGraphViewer.getTimeGraphControl().setFocus();
615 }
616 }
617 });
618 fTimeGraphViewer.getTimeGraphScale().addMouseTrackListener(new MouseTrackAdapter() {
619 @Override
620 public void mouseEnter(MouseEvent e) {
621 if (fTreeViewer.getControl().isFocusControl()) {
622 fTimeGraphViewer.getTimeGraphControl().setFocus();
623 }
624 }
625 });
626
627 // The filler rows are required to ensure alignment when the tree does not have a
628 // visible horizontal scroll bar. The tree does not allow its top item to be set
629 // to a value that would cause blank space to be drawn at the bottom of the tree.
630 fNumFillerRows = Display.getDefault().getBounds().height / getItemHeight(tree);
631
d2e4afa7
MAL
632 fSashForm.setWeights(weights);
633
634 fTimeGraphViewer.getTimeGraphControl().addPaintListener(new PaintListener() {
635 @Override
636 public void paintControl(PaintEvent e) {
637 // Sashes in a SashForm are being created on layout so add the
638 // drag listener here
639 if (fSashDragListener == null) {
640 for (Control control : fSashForm.getChildren()) {
641 if (control instanceof Sash) {
642 fSashDragListener = new Listener() {
643
644 @Override
645 public void handleEvent(Event event) {
646 sendTimeViewAlignmentChanged();
647
648 }
649 };
650 control.removePaintListener(this);
651 control.addListener(SWT.Selection, fSashDragListener);
652 // There should be only one sash
653 break;
654 }
655 }
656 }
657 }
658 });
659 }
660
661 private void sendTimeViewAlignmentChanged() {
662 TmfSignalManager.dispatchSignal(new TmfTimeViewAlignmentSignal(fSashForm, getTimeViewAlignmentInfo()));
837a2f8c
PT
663 }
664
665 // ------------------------------------------------------------------------
666 // Accessors
667 // ------------------------------------------------------------------------
668
669 /**
670 * Returns this time graph combo's tree viewer.
671 *
672 * @return the tree viewer
673 */
674 public TreeViewer getTreeViewer() {
675 return fTreeViewer;
676 }
677
678 /**
679 * Returns this time graph combo's time graph viewer.
680 *
681 * @return the time graph viewer
682 */
dfa0ef96 683 public @NonNull TimeGraphViewer getTimeGraphViewer() {
837a2f8c
PT
684 return fTimeGraphViewer;
685 }
686
6ac5a950
AM
687 /**
688 * Callback for the show filter action
6ac5a950
AM
689 */
690 public void showFilterDialog() {
4c9c0c87
PT
691 ITimeGraphEntry[] topInput = fTimeGraphViewer.getTimeGraphContentProvider().getElements(fTimeGraphViewer.getInput());
692 if (topInput != null) {
693 List<? extends ITimeGraphEntry> allElements = listAllInputs(Arrays.asList(topInput));
694 fFilterDialog.setInput(fTimeGraphViewer.getInput());
6ac5a950
AM
695 fFilterDialog.setTitle(Messages.TmfTimeFilterDialog_WINDOW_TITLE);
696 fFilterDialog.setMessage(Messages.TmfTimeFilterDialog_MESSAGE);
8f28f9d8 697 fFilterDialog.setExpandedElements(allElements.toArray());
f8840316 698 if (fFilter.getFiltered() != null) {
507b1336 699 ArrayList<? extends ITimeGraphEntry> nonFilteredElements = new ArrayList<>(allElements);
f8840316
FR
700 nonFilteredElements.removeAll(fFilter.getFiltered());
701 fFilterDialog.setInitialElementSelections(nonFilteredElements);
8f28f9d8
PT
702 } else {
703 fFilterDialog.setInitialElementSelections(allElements);
704 }
6ac5a950
AM
705 fFilterDialog.create();
706 fFilterDialog.open();
707 // Process selected elements
708 if (fFilterDialog.getResult() != null) {
709 fInhibitTreeSelection = true;
8f28f9d8 710 if (fFilterDialog.getResult().length != allElements.size()) {
f8840316
FR
711 ArrayList<Object> filteredElements = new ArrayList<Object>(allElements);
712 filteredElements.removeAll(Arrays.asList(fFilterDialog.getResult()));
713 fFilter.setFiltered(filteredElements);
8f28f9d8 714 } else {
f8840316 715 fFilter.setFiltered(null);
8f28f9d8 716 }
6ac5a950
AM
717 fTreeViewer.refresh();
718 fTreeViewer.expandAll();
719 fTimeGraphViewer.refresh();
ece2fc5f 720 fTimeGraphViewer.expandAll();
6ac5a950 721 fInhibitTreeSelection = false;
588dff10 722 alignTreeItems(true);
40b7b614 723 // Reset selection
6ac5a950 724 if (fFilterDialog.getResult().length > 0) {
40b7b614 725 setSelection(null);
6ac5a950
AM
726 }
727 }
728 }
729 }
730
731 /**
732 * Get the show filter action.
733 *
734 * @return The Action object
6ac5a950
AM
735 */
736 public Action getShowFilterAction() {
737 if (showFilterAction == null) {
738 // showFilter
739 showFilterAction = new Action() {
740 @Override
741 public void run() {
742 showFilterDialog();
743 }
744 };
745 showFilterAction.setText(Messages.TmfTimeGraphCombo_FilterActionNameText);
746 showFilterAction.setToolTipText(Messages.TmfTimeGraphCombo_FilterActionToolTipText);
747 // TODO find a nice, distinctive icon
748 showFilterAction.setImageDescriptor(Activator.getDefault().getImageDescripterFromPath(ITmfImageConstants.IMG_UI_FILTERS));
749 }
750
751 return showFilterAction;
752 }
753
837a2f8c
PT
754 // ------------------------------------------------------------------------
755 // Control
756 // ------------------------------------------------------------------------
757
837a2f8c
PT
758 @Override
759 public void redraw() {
760 fTimeGraphViewer.getControl().redraw();
761 super.redraw();
762 }
763
764 // ------------------------------------------------------------------------
765 // Operations
766 // ------------------------------------------------------------------------
767
768 /**
769 * Sets the tree content provider used by this time graph combo.
770 *
771 * @param contentProvider the tree content provider
772 */
773 public void setTreeContentProvider(ITreeContentProvider contentProvider) {
774 fTreeViewer.setContentProvider(new TreeContentProviderWrapper(contentProvider));
775 }
776
777 /**
778 * Sets the tree label provider used by this time graph combo.
779 *
780 * @param labelProvider the tree label provider
781 */
782 public void setTreeLabelProvider(ITableLabelProvider labelProvider) {
783 fTreeViewer.setLabelProvider(new TreeLabelProviderWrapper(labelProvider));
784 }
785
6ac5a950
AM
786 /**
787 * Sets the tree content provider used by the filter dialog
788 *
789 * @param contentProvider the tree content provider
6ac5a950
AM
790 */
791 public void setFilterContentProvider(ITreeContentProvider contentProvider) {
792 fFilterDialog.setContentProvider(contentProvider);
793 }
794
795 /**
796 * Sets the tree label provider used by the filter dialog
797 *
798 * @param labelProvider the tree label provider
6ac5a950
AM
799 */
800 public void setFilterLabelProvider(ITableLabelProvider labelProvider) {
801 fFilterDialog.setLabelProvider(labelProvider);
802 }
803
b97d61f0
CM
804 /**
805 * Adds a "check active" button used by the filter dialog
806 *
807 * @param activeProvider
808 * Additional button info specific to a certain view.
809 * @since 1.0
810 */
811 public void addTimeGraphFilterCheckActiveButton(ITimeGraphEntryActiveProvider activeProvider) {
812 fFilterDialog.addTimeGraphFilterCheckActiveButton(activeProvider);
813 }
814
815 /**
816 * Adds an "uncheck inactive" button used by the filter dialog
817 *
818 * @param inactiveProvider
819 * Additional button info specific to a certain view.
820 * @since 1.0
821 */
822 public void addTimeGraphFilterUncheckInactiveButton(ITimeGraphEntryActiveProvider inactiveProvider) {
823 fFilterDialog.addTimeGraphFilterUncheckInactiveButton(inactiveProvider);
824 }
825
837a2f8c
PT
826 /**
827 * Sets the tree columns for this time graph combo.
828 *
829 * @param columnNames the tree column names
830 */
831 public void setTreeColumns(String[] columnNames) {
832 final Tree tree = fTreeViewer.getTree();
833 for (String columnName : columnNames) {
834 TreeColumn column = new TreeColumn(tree, SWT.LEFT);
835 column.setText(columnName);
836 column.pack();
837 }
838 }
839
6ac5a950
AM
840 /**
841 * Sets the tree columns for this time graph combo's filter dialog.
842 *
843 * @param columnNames the tree column names
6ac5a950
AM
844 */
845 public void setFilterColumns(String[] columnNames) {
846 fFilterDialog.setColumnNames(columnNames);
847 }
848
837a2f8c 849 /**
4c9c0c87
PT
850 * Sets the time graph content provider used by this time graph combo.
851 *
852 * @param timeGraphContentProvider
853 * the time graph content provider
4c9c0c87
PT
854 */
855 public void setTimeGraphContentProvider(ITimeGraphContentProvider timeGraphContentProvider) {
856 fTimeGraphViewer.setTimeGraphContentProvider(timeGraphContentProvider);
857 }
858
859 /**
860 * Sets the time graph presentation provider used by this time graph combo.
837a2f8c
PT
861 *
862 * @param timeGraphProvider the time graph provider
863 */
864 public void setTimeGraphProvider(ITimeGraphPresentationProvider timeGraphProvider) {
865 fTimeGraphViewer.setTimeGraphProvider(timeGraphProvider);
866 }
867
868 /**
869 * Sets or clears the input for this time graph combo.
837a2f8c
PT
870 *
871 * @param input the input of this time graph combo, or <code>null</code> if none
872 */
4c9c0c87 873 public void setInput(Object input) {
f8840316 874 fFilter.setFiltered(null);
837a2f8c
PT
875 fInhibitTreeSelection = true;
876 fTreeViewer.setInput(input);
877 for (SelectionListenerWrapper listenerWrapper : fSelectionListenerMap.values()) {
878 listenerWrapper.selection = null;
879 }
880 fInhibitTreeSelection = false;
837a2f8c
PT
881 fTreeViewer.getTree().getVerticalBar().setEnabled(false);
882 fTreeViewer.getTree().getVerticalBar().setVisible(false);
883 fTimeGraphViewer.setItemHeight(getItemHeight(fTreeViewer.getTree()));
884 fTimeGraphViewer.setInput(input);
588dff10
PT
885 // queue the alignment update because in Linux the item bounds are not
886 // set properly until the tree has been painted at least once
887 fVisibleExpandedItems = null; // invalidate the cache
888 getDisplay().asyncExec(new Runnable() {
889 @Override
890 public void run() {
891 alignTreeItems(true);
892 }});
837a2f8c
PT
893 }
894
4c9c0c87
PT
895 /**
896 * Gets the input for this time graph combo.
897 *
898 * @return The input of this time graph combo, or <code>null</code> if none
4c9c0c87
PT
899 */
900 public Object getInput() {
901 return fTreeViewer.getInput();
902 }
903
bec1f1ac
GB
904 /**
905 * Sets or clears the list of links to display on this combo
906 *
907 * @param links the links to display in this time graph combo
bec1f1ac
GB
908 */
909 public void setLinks(List<ILinkEvent> links) {
910 fTimeGraphViewer.setLinks(links);
911 }
912
6ac5a950
AM
913 /**
914 * @param filter The filter object to be attached to the view
6ac5a950
AM
915 */
916 public void addFilter(ViewerFilter filter) {
917 ViewerFilter wrapper = new ViewerFilterWrapper(filter);
918 fTreeViewer.addFilter(wrapper);
919 fTimeGraphViewer.addFilter(wrapper);
920 fViewerFilterMap.put(filter, wrapper);
588dff10 921 alignTreeItems(true);
6ac5a950
AM
922 }
923
924 /**
925 * @param filter The filter object to be removed from the view
6ac5a950
AM
926 */
927 public void removeFilter(ViewerFilter filter) {
928 ViewerFilter wrapper = fViewerFilterMap.get(filter);
929 fTreeViewer.removeFilter(wrapper);
930 fTimeGraphViewer.removeFilter(wrapper);
931 fViewerFilterMap.remove(filter);
588dff10 932 alignTreeItems(true);
6ac5a950
AM
933 }
934
837a2f8c
PT
935 /**
936 * Refreshes this time graph completely with information freshly obtained from its model.
937 */
938 public void refresh() {
939 fInhibitTreeSelection = true;
4c9c0c87 940 Tree tree = fTreeViewer.getTree();
ece2fc5f
PT
941 try {
942 tree.setRedraw(false);
943 fTreeViewer.refresh();
944 fTreeViewer.expandToLevel(fTreeViewer.getAutoExpandLevel());
945 } finally {
946 tree.setRedraw(true);
947 }
837a2f8c 948 fTimeGraphViewer.refresh();
588dff10 949 alignTreeItems(true);
837a2f8c
PT
950 fInhibitTreeSelection = false;
951 }
952
953 /**
954 * Adds a listener for selection changes in this time graph combo.
955 *
956 * @param listener a selection listener
957 */
958 public void addSelectionListener(ITimeGraphSelectionListener listener) {
959 SelectionListenerWrapper listenerWrapper = new SelectionListenerWrapper(listener);
960 fTreeViewer.addSelectionChangedListener(listenerWrapper);
961 fSelectionListenerMap.put(listener, listenerWrapper);
962 fTimeGraphViewer.addSelectionListener(listenerWrapper);
963 }
964
965 /**
966 * Removes the given selection listener from this time graph combo.
967 *
968 * @param listener a selection changed listener
969 */
970 public void removeSelectionListener(ITimeGraphSelectionListener listener) {
971 SelectionListenerWrapper listenerWrapper = fSelectionListenerMap.remove(listener);
972 fTreeViewer.removeSelectionChangedListener(listenerWrapper);
973 fTimeGraphViewer.removeSelectionListener(listenerWrapper);
974 }
975
976 /**
977 * Sets the current selection for this time graph combo.
978 *
979 * @param selection the new selection
980 */
981 public void setSelection(ITimeGraphEntry selection) {
982 fTimeGraphViewer.setSelection(selection);
983 fInhibitTreeSelection = true; // block the tree selection changed listener
984 if (selection != null) {
985 StructuredSelection structuredSelection = new StructuredSelection(selection);
986 fTreeViewer.setSelection(structuredSelection);
987 } else {
988 fTreeViewer.setSelection(new StructuredSelection());
989 }
990 fInhibitTreeSelection = false;
588dff10 991 alignTreeItems(false);
837a2f8c
PT
992 }
993
f4617471
PT
994 /**
995 * Sets the auto-expand level to be used when the input of the viewer is set
996 * using {@link #setInput(Object)}. The value 0 means that there is no
997 * auto-expand; 1 means that top-level elements are expanded, but not their
998 * children; 2 means that top-level elements are expanded, and their
999 * children, but not grand-children; and so on.
1000 * <p>
1001 * The value {@link #ALL_LEVELS} means that all subtrees should be expanded.
1002 * </p>
1003 * @param level
1004 * non-negative level, or <code>ALL_LEVELS</code> to expand all
1005 * levels of the tree
f4617471
PT
1006 */
1007 public void setAutoExpandLevel(int level) {
1008 fTimeGraphViewer.setAutoExpandLevel(level);
1009 if (level <= 0) {
1010 fTreeViewer.setAutoExpandLevel(level);
1011 } else {
1012 fTreeViewer.setAutoExpandLevel(level + 1);
1013 }
1014 }
1015
1016 /**
1017 * Returns the auto-expand level.
1018 *
1019 * @return non-negative level, or <code>ALL_LEVELS</code> if all levels of
1020 * the tree are expanded automatically
1021 * @see #setAutoExpandLevel
f4617471
PT
1022 */
1023 public int getAutoExpandLevel() {
1024 return fTimeGraphViewer.getAutoExpandLevel();
1025 }
1026
837a2f8c
PT
1027 /**
1028 * Set the expanded state of an entry
1029 *
1030 * @param entry
1031 * The entry to expand/collapse
1032 * @param expanded
1033 * True for expanded, false for collapsed
837a2f8c
PT
1034 */
1035 public void setExpandedState(ITimeGraphEntry entry, boolean expanded) {
1036 fTimeGraphViewer.setExpandedState(entry, expanded);
1037 fTreeViewer.setExpandedState(entry, expanded);
588dff10 1038 alignTreeItems(true);
837a2f8c
PT
1039 }
1040
1041 /**
1042 * Collapses all nodes of the viewer's tree, starting with the root.
837a2f8c
PT
1043 */
1044 public void collapseAll() {
1045 fTimeGraphViewer.collapseAll();
1046 fTreeViewer.collapseAll();
588dff10 1047 alignTreeItems(true);
837a2f8c
PT
1048 }
1049
1050 /**
1051 * Expands all nodes of the viewer's tree, starting with the root.
837a2f8c
PT
1052 */
1053 public void expandAll() {
1054 fTimeGraphViewer.expandAll();
1055 fTreeViewer.expandAll();
588dff10 1056 alignTreeItems(true);
837a2f8c
PT
1057 }
1058
1059 // ------------------------------------------------------------------------
1060 // Internal
1061 // ------------------------------------------------------------------------
1062
588dff10
PT
1063 private List<TreeItem> getVisibleExpandedItems(Tree tree, boolean refresh) {
1064 if (fVisibleExpandedItems == null || refresh) {
1065 ArrayList<TreeItem> items = new ArrayList<>();
1066 for (TreeItem item : tree.getItems()) {
1067 if (item.getData() == FILLER) {
1068 break;
1069 }
1070 items.add(item);
1071 if (item.getExpanded()) {
1072 addVisibleExpandedItems(items, item);
1073 }
837a2f8c 1074 }
588dff10 1075 fVisibleExpandedItems = items;
837a2f8c 1076 }
588dff10 1077 return fVisibleExpandedItems;
837a2f8c
PT
1078 }
1079
588dff10 1080 private void addVisibleExpandedItems(List<TreeItem> items, TreeItem treeItem) {
837a2f8c
PT
1081 for (TreeItem item : treeItem.getItems()) {
1082 items.add(item);
1083 if (item.getExpanded()) {
588dff10 1084 addVisibleExpandedItems(items, item);
837a2f8c
PT
1085 }
1086 }
837a2f8c
PT
1087 }
1088
6ac5a950
AM
1089 /**
1090 * Explores the list of top-level inputs and returns all the inputs
1091 *
1092 * @param inputs The top-level inputs
1093 * @return All the inputs
1094 */
1095 private List<? extends ITimeGraphEntry> listAllInputs(List<? extends ITimeGraphEntry> inputs) {
507b1336 1096 ArrayList<ITimeGraphEntry> items = new ArrayList<>();
6ac5a950
AM
1097 for (ITimeGraphEntry entry : inputs) {
1098 items.add(entry);
1099 if (entry.hasChildren()) {
1100 items.addAll(listAllInputs(entry.getChildren()));
1101 }
1102 }
1103 return items;
1104 }
1105
837a2f8c
PT
1106 private int getItemHeight(final Tree tree) {
1107 /*
1108 * Bug in Linux. The method getItemHeight doesn't always return the correct value.
1109 */
1110 if (fLinuxItemHeight >= 0 && System.getProperty("os.name").contains("Linux")) { //$NON-NLS-1$ //$NON-NLS-2$
1111 if (fLinuxItemHeight != 0) {
1112 return fLinuxItemHeight;
1113 }
588dff10 1114 List<TreeItem> treeItems = getVisibleExpandedItems(tree, true);
837a2f8c
PT
1115 if (treeItems.size() > 1) {
1116 final TreeItem treeItem0 = treeItems.get(0);
1117 final TreeItem treeItem1 = treeItems.get(1);
1118 PaintListener paintListener = new PaintListener() {
1119 @Override
1120 public void paintControl(PaintEvent e) {
1121 tree.removePaintListener(this);
1122 int y0 = treeItem0.getBounds().y;
1123 int y1 = treeItem1.getBounds().y;
1124 int itemHeight = y1 - y0;
1125 if (itemHeight > 0) {
1126 fLinuxItemHeight = itemHeight;
1127 fTimeGraphViewer.setItemHeight(itemHeight);
1128 }
1129 }
1130 };
1131 tree.addPaintListener(paintListener);
1132 }
1133 } else {
1134 fLinuxItemHeight = -1; // Not Linux, don't perform os.name check anymore
1135 }
1136 return tree.getItemHeight();
1137 }
1138
588dff10
PT
1139 private void alignTreeItems(boolean refreshExpandedItems) {
1140 // align the tree top item with the time graph top item
1141 Tree tree = fTreeViewer.getTree();
1142 List<TreeItem> treeItems = getVisibleExpandedItems(tree, refreshExpandedItems);
1143 int topIndex = fTimeGraphViewer.getTopIndex();
1144 if (topIndex >= treeItems.size()) {
1145 return;
1146 }
1147 TreeItem item = treeItems.get(topIndex);
1148 tree.setTopItem(item);
1149
1150 // ensure the time graph item heights are equal to the tree item heights
1151 int treeHeight = fTreeViewer.getTree().getBounds().height;
1152 int index = topIndex;
1153 Rectangle bounds = item.getBounds();
1154 while (index < treeItems.size() - 1) {
1155 if (bounds.y > treeHeight) {
1156 break;
1157 }
1158 /*
1159 * Bug in Linux. The method getBounds doesn't always return the correct height.
1160 * Use the difference of y position between items to calculate the height.
1161 */
1162 TreeItem nextItem = treeItems.get(index + 1);
1163 Rectangle nextBounds = nextItem.getBounds();
1164 Integer itemHeight = nextBounds.y - bounds.y;
1165 if (itemHeight > 0 && !itemHeight.equals(item.getData(ITEM_HEIGHT))) {
1166 ITimeGraphEntry entry = (ITimeGraphEntry) item.getData();
1167 if (fTimeGraphViewer.getTimeGraphControl().setItemHeight(entry, itemHeight)) {
1168 item.setData(ITEM_HEIGHT, itemHeight);
1169 }
1170 }
1171 index++;
1172 item = nextItem;
1173 bounds = nextBounds;
1174 }
1175 }
1176
d2e4afa7
MAL
1177 /**
1178 * Return the time alignment information
1179 *
1180 * @return the time alignment information
1181 *
1182 * @see ITmfTimeAligned
1183 *
1184 * @since 1.0
1185 */
1186 public TmfTimeViewAlignmentInfo getTimeViewAlignmentInfo() {
1187 int[] weights = fSashForm.getWeights();
1188 int leftWidth = (int) (((float) weights[0] / (weights[0] + weights[1])) * fSashForm.getBounds().width) + fSashForm.getSashWidth();
1189 Point location = fSashForm.toDisplay(0, 0);
1190 return new TmfTimeViewAlignmentInfo(fSashForm.getShell(), location, leftWidth);
1191 }
1192
1193 /**
1194 * Return the available width for the time-axis.
1195 *
1196 * @see ITmfTimeAligned
1197 *
1198 * @param requestedOffset
1199 * the requested offset
1200 * @return the available width for the time-axis
1201 *
1202 * @since 1.0
1203 */
1204 public int getAvailableWidth(int requestedOffset) {
1205 int totalWidth = fSashForm.getBounds().width;
1206 int timeWidth = totalWidth - requestedOffset;
1207 return timeWidth;
1208 }
1209
1210 /**
1211 * Perform the alignment operation.
1212 *
1213 * @param offset
1214 * the alignment offset
1215 * @param width
1216 * the alignment width
1217 *
1218 * @see ITmfTimeAligned
1219 *
1220 * @since 1.0
1221 */
1222 public void performAlign(int offset, int width) {
1223 int total = fSashForm.getBounds().width;
1224 int timeAxisOffset = Math.min(offset, total);
1225 int sash1Width = (int) (timeAxisOffset / (float) total * 1000);
1226 int sash2Width = (int) ((total - timeAxisOffset) / (float) total * 1000);
1227 fSashForm.setWeights(new int[] { sash1Width, sash2Width });
1228 fSashForm.layout();
1229
1230 Composite composite = fTimeGraphViewer.getTimeAlignedComposite();
1231 GridLayout layout = (GridLayout) composite.getLayout();
1232 int timeBasedControlsWidth = composite.getSize().x;
1233 int marginSize = timeBasedControlsWidth - width;
1234 layout.marginRight = Math.max(0, marginSize);
1235 composite.layout();
1236 }
837a2f8c 1237}
This page took 0.129365 seconds and 5 git commands to generate.