Remove all existing @since annotations
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / widgets / timegraph / dialogs / TimeGraphFilterDialog.java
CommitLineData
8f91a789 1/*******************************************************************************
ed902a2b 2 * Copyright (c) 2000, 2014 IBM Corporation and others.
8f91a789
AM
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog font should be
11 * activated and used by other components.
12 * Lubomir Marinov <lubomir.marinov@gmail.com> - Fix for bug 182122 -[Dialogs]
13 * CheckedTreeSelectionDialog#createSelectionButtons(Composite) fails to
14 * align the selection buttons to the right
15 * François Rajotte - Support for multiple columns + selection control
f1fae91f 16 * Patrick Tasse - Fix Sonar warnings
40b7b614 17 * Generoso Pagano - Add tree filter
8f91a789
AM
18 *******************************************************************************/
19
2bdf0193 20package org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs;
8f91a789
AM
21
22import java.util.ArrayList;
23import java.util.Arrays;
24import java.util.List;
25
26import org.eclipse.core.runtime.IStatus;
27import org.eclipse.core.runtime.Status;
28import org.eclipse.jface.dialogs.IDialogConstants;
29import org.eclipse.jface.viewers.CheckStateChangedEvent;
30import org.eclipse.jface.viewers.CheckboxTreeViewer;
31import org.eclipse.jface.viewers.IBaseLabelProvider;
32import org.eclipse.jface.viewers.ICheckStateListener;
33import org.eclipse.jface.viewers.ITreeContentProvider;
8906e53c 34import org.eclipse.jface.viewers.TreeSelection;
8f91a789
AM
35import org.eclipse.jface.viewers.ViewerComparator;
36import org.eclipse.jface.viewers.ViewerFilter;
8f91a789
AM
37import org.eclipse.swt.SWT;
38import org.eclipse.swt.custom.BusyIndicator;
39import org.eclipse.swt.events.SelectionAdapter;
40import org.eclipse.swt.events.SelectionEvent;
8f91a789
AM
41import org.eclipse.swt.layout.GridData;
42import org.eclipse.swt.layout.GridLayout;
43import org.eclipse.swt.widgets.Button;
44import org.eclipse.swt.widgets.Composite;
45import org.eclipse.swt.widgets.Control;
46import org.eclipse.swt.widgets.Label;
47import org.eclipse.swt.widgets.Shell;
48import org.eclipse.swt.widgets.Tree;
49import org.eclipse.swt.widgets.TreeColumn;
2bdf0193
AM
50import org.eclipse.tracecompass.internal.tmf.ui.Messages;
51import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry;
8f91a789 52import org.eclipse.ui.PlatformUI;
8f91a789 53import org.eclipse.ui.dialogs.ISelectionStatusValidator;
40b7b614 54import org.eclipse.ui.dialogs.PatternFilter;
8f91a789
AM
55import org.eclipse.ui.dialogs.SelectionStatusDialog;
56
57/**
40b7b614
GP
58 * Filter dialog for the time graphs This class is derived from the
59 * CheckedTreeSelectionDialog It was necessary to develop this similar dialog to
60 * allow multiple columns
8f91a789 61 *
8f91a789
AM
62 * @author François Rajotte
63 */
64public class TimeGraphFilterDialog extends SelectionStatusDialog {
f1fae91f
PT
65 private static final int BUTTON_CHECK_SELECTED_ID = IDialogConstants.CLIENT_ID;
66 private static final int BUTTON_UNCHECK_SELECTED_ID = IDialogConstants.CLIENT_ID + 1;
67 private static final int BUTTON_CHECK_SUBTREE_ID = IDialogConstants.CLIENT_ID + 2;
68 private static final int BUTTON_UNCHECK_SUBTREE_ID = IDialogConstants.CLIENT_ID + 3;
03beb743 69
f1fae91f
PT
70 private static final int DEFAULT_WIDTH = 60;
71 private static final int DEFAULT_HEIGHT = 18;
8f91a789 72
40b7b614 73 private FilteredCheckboxTree fTree;
8f91a789
AM
74
75 private IBaseLabelProvider fLabelProvider;
76
77 private ITreeContentProvider fContentProvider;
78
79 private String[] fColumnNames;
80
81 private ISelectionStatusValidator fValidator = null;
82
83 private ViewerComparator fComparator;
84
85 private String fEmptyListMessage = ""; //$NON-NLS-1$
86
87 private IStatus fCurrStatus = new Status(IStatus.OK, PlatformUI.PLUGIN_ID,
88 0, "", null); //$NON-NLS-1$
89
90 private List<ViewerFilter> fFilters;
91
92 private Object fInput;
93
94 private boolean fIsEmpty;
95
f1fae91f 96 private int fWidth = DEFAULT_WIDTH;
8f91a789 97
f1fae91f 98 private int fHeight = DEFAULT_HEIGHT;
8f91a789 99
8f91a789
AM
100 private Object[] fExpandedElements;
101
102 /**
103 * Constructs an instance of <code>ElementTreeSelectionDialog</code>.
104 *
105 * @param parent
106 * The shell to parent from.
107 */
108 public TimeGraphFilterDialog(Shell parent) {
109 super(parent);
507b1336 110 setResult(new ArrayList<>(0));
8f91a789
AM
111 setStatusLineAboveButtons(true);
112 setHelpAvailable(false);
8f91a789
AM
113 fExpandedElements = null;
114 }
115
8f91a789
AM
116 /**
117 * Sets the initial selection. Convenience method.
118 *
119 * @param selection
120 * the initial selection.
121 */
122 public void setInitialSelection(Object selection) {
123 setInitialSelections(new Object[] { selection });
124 }
125
126 /**
127 * Sets the message to be displayed if the list is empty.
128 *
129 * @param message
130 * the message to be displayed.
131 */
132 public void setEmptyListMessage(String message) {
133 fEmptyListMessage = message;
134 }
135
136 /**
137 * Sets the comparator used by the tree viewer.
138 *
139 * @param comparator
140 * The comparator
141 */
142 public void setComparator(ViewerComparator comparator) {
143 fComparator = comparator;
144 }
145
146 /**
147 * Adds a filter to the tree viewer.
148 *
149 * @param filter
150 * a filter.
151 */
152 public void addFilter(ViewerFilter filter) {
153 if (fFilters == null) {
507b1336 154 fFilters = new ArrayList<>();
8f91a789
AM
155 }
156 fFilters.add(filter);
157 }
158
159 /**
160 * Sets an optional validator to check if the selection is valid. The
161 * validator is invoked whenever the selection changes.
162 *
163 * @param validator
164 * the validator to validate the selection.
165 */
166 public void setValidator(ISelectionStatusValidator validator) {
167 fValidator = validator;
168 }
169
170 /**
171 * Sets the tree input.
172 *
173 * @param input
174 * the tree input.
175 */
176 public void setInput(Object input) {
177 fInput = input;
178 }
179
180 /**
181 * Expands elements in the tree.
182 *
183 * @param elements
184 * The elements that will be expanded.
185 */
186 public void setExpandedElements(Object[] elements) {
f1fae91f
PT
187 if (elements != null) {
188 fExpandedElements = Arrays.copyOf(elements, elements.length);
189 } else {
190 fExpandedElements = null;
191 }
8f91a789
AM
192 }
193
194 /**
195 * Sets the size of the tree in unit of characters.
196 *
197 * @param width
198 * the width of the tree.
199 * @param height
200 * the height of the tree.
201 */
202 public void setSize(int width, int height) {
203 fWidth = width;
204 fHeight = height;
205 }
206
207 /**
40b7b614
GP
208 * @param contentProvider
209 * The content provider for the table
8f91a789
AM
210 */
211 public void setContentProvider(ITreeContentProvider contentProvider) {
212 fContentProvider = contentProvider;
213 }
214
215 /**
40b7b614
GP
216 * @param labelProvider
217 * The label provider for the table
8f91a789
AM
218 */
219 public void setLabelProvider(IBaseLabelProvider labelProvider) {
220 fLabelProvider = labelProvider;
221 }
222
223 /**
40b7b614
GP
224 * @param columnNames
225 * An array of column names to display
8f91a789
AM
226 */
227 public void setColumnNames(String[] columnNames) {
f1fae91f
PT
228 if (columnNames != null) {
229 fColumnNames = Arrays.copyOf(columnNames, columnNames.length);
230 } else {
231 fColumnNames = null;
232 }
8f91a789
AM
233 }
234
235 /**
236 * Validate the receiver and update the status with the result.
237 *
238 */
239 protected void updateOKStatus() {
240 if (!fIsEmpty) {
241 if (fValidator != null) {
40b7b614 242 fCurrStatus = fValidator.validate(fTree.getCheckedElements());
8f91a789
AM
243 updateStatus(fCurrStatus);
244 } else if (!fCurrStatus.isOK()) {
245 fCurrStatus = new Status(IStatus.OK, PlatformUI.PLUGIN_ID,
246 IStatus.OK, "", //$NON-NLS-1$
247 null);
248 }
249 } else {
250 fCurrStatus = new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID,
251 IStatus.OK, fEmptyListMessage, null);
252 }
253 updateStatus(fCurrStatus);
254 }
255
256 @Override
257 public int open() {
258 fIsEmpty = evaluateIfTreeEmpty(fInput);
259 super.open();
260 return getReturnCode();
261 }
262
8f91a789
AM
263 @Override
264 protected void cancelPressed() {
265 setResult(null);
266 super.cancelPressed();
267 }
268
269 @Override
270 protected void computeResult() {
40b7b614 271 setResult(Arrays.asList(fTree.getCheckedElements()));
8f91a789
AM
272 }
273
274 @Override
275 public void create() {
276 BusyIndicator.showWhile(null, new Runnable() {
277 @Override
278 public void run() {
f1fae91f 279 TimeGraphFilterDialog.super.create();
40b7b614 280 fTree.setCheckedElements(getInitialElementSelections()
8f91a789
AM
281 .toArray());
282 if (fExpandedElements != null) {
40b7b614 283 fTree.getViewer().setExpandedElements(fExpandedElements);
8f91a789
AM
284 }
285 updateOKStatus();
286 }
287 });
288 }
289
290 @Override
291 protected Control createDialogArea(Composite parent) {
292 Composite composite = (Composite) super.createDialogArea(parent);
293 Label messageLabel = createMessageArea(composite);
294 CheckboxTreeViewer treeViewer = createTreeViewer(composite);
295 Control buttonComposite = createSelectionButtons(composite);
296 GridData data = new GridData(GridData.FILL_BOTH);
297 data.widthHint = convertWidthInCharsToPixels(fWidth);
298 data.heightHint = convertHeightInCharsToPixels(fHeight);
299 Tree treeWidget = treeViewer.getTree();
300 treeWidget.setLayoutData(data);
301 treeWidget.setFont(parent.getFont());
302 if (fIsEmpty) {
303 messageLabel.setEnabled(false);
304 treeWidget.setEnabled(false);
305 buttonComposite.setEnabled(false);
306 }
307 return composite;
308 }
309
310 /**
311 * Creates the tree viewer.
312 *
313 * @param parent
314 * the parent composite
315 * @return the tree viewer
316 */
317 protected CheckboxTreeViewer createTreeViewer(Composite parent) {
40b7b614
GP
318 PatternFilter filter = new TreePatternFilter();
319 filter.setIncludeLeadingWildcard(true);
320 fTree = new FilteredCheckboxTree(parent, SWT.BORDER | SWT.MULTI, filter, true);
8f91a789 321
40b7b614 322 Tree tree = fTree.getViewer().getTree();
8f91a789
AM
323 tree.setHeaderVisible(true);
324 for (String columnName : fColumnNames) {
325 TreeColumn column = new TreeColumn(tree, SWT.LEFT);
326 column.setText(columnName);
327 column.pack();
328 }
329
40b7b614
GP
330 fTree.getViewer().setContentProvider(fContentProvider);
331 fTree.getViewer().setLabelProvider(fLabelProvider);
332 fTree.addCheckStateListener(new CheckStateListener());
333 fTree.getViewer().setComparator(fComparator);
8f91a789
AM
334 if (fFilters != null) {
335 for (int i = 0; i != fFilters.size(); i++) {
40b7b614 336 fTree.getViewer().addFilter(fFilters.get(i));
8f91a789
AM
337 }
338 }
40b7b614 339 fTree.getViewer().setInput(fInput);
8f91a789 340
40b7b614 341 // pack the columns again for a nice view...
8f91a789
AM
342 for (TreeColumn column : tree.getColumns()) {
343 column.pack();
344 }
40b7b614 345 return (CheckboxTreeViewer) fTree.getViewer();
8f91a789
AM
346 }
347
348 /**
349 * Returns the tree viewer.
350 *
351 * @return the tree viewer
352 */
353 protected CheckboxTreeViewer getTreeViewer() {
40b7b614 354 return (CheckboxTreeViewer) fTree.getViewer();
8f91a789
AM
355 }
356
357 /**
358 * Adds the selection and deselection buttons to the dialog.
359 *
360 * @param composite
361 * the parent composite
362 * @return Composite the composite the buttons were created in.
363 */
364 protected Composite createSelectionButtons(Composite composite) {
365 Composite buttonComposite = new Composite(composite, SWT.RIGHT);
366 GridLayout layout = new GridLayout();
8f91a789
AM
367 layout.marginWidth = 0;
368 layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
369 buttonComposite.setLayout(layout);
370 buttonComposite.setFont(composite.getFont());
371 GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END
372 | GridData.GRAB_HORIZONTAL);
373 data.grabExcessHorizontalSpace = true;
374 buttonComposite.setLayoutData(data);
8906e53c
SM
375
376 /* Create the buttons in the good order to place them as we want */
03beb743
SM
377 Button checkSelectedButton = createButton(buttonComposite,
378 BUTTON_CHECK_SELECTED_ID, Messages.TmfTimeFilterDialog_CHECK_SELECTED,
379 false);
380 Button checkSubtreeButton = createButton(buttonComposite,
381 BUTTON_CHECK_SUBTREE_ID, Messages.TmfTimeFilterDialog_CHECK_SUBTREE,
382 false);
8906e53c
SM
383 Button checkAllButton = createButton(buttonComposite,
384 IDialogConstants.SELECT_ALL_ID, Messages.TmfTimeFilterDialog_CHECK_ALL,
385 false);
03beb743
SM
386
387 Button uncheckSelectedButton = createButton(buttonComposite,
388 BUTTON_UNCHECK_SELECTED_ID, Messages.TmfTimeFilterDialog_UNCHECK_SELECTED,
389 false);
390 Button uncheckSubtreeButton = createButton(buttonComposite,
391 BUTTON_UNCHECK_SUBTREE_ID, Messages.TmfTimeFilterDialog_UNCHECK_SUBTREE,
8906e53c
SM
392 false);
393 Button uncheckAllButton = createButton(buttonComposite,
394 IDialogConstants.DESELECT_ALL_ID, Messages.TmfTimeFilterDialog_UNCHECK_ALL,
395 false);
03beb743 396
8906e53c
SM
397 /*
398 * Apply the layout again after creating the buttons to override
399 * createButton messing with the columns
400 */
03beb743 401 layout.numColumns = 3;
8906e53c
SM
402 buttonComposite.setLayout(layout);
403
404 /* Add a listener to each button */
03beb743 405 checkSelectedButton.addSelectionListener(new SelectionAdapter() {
8f91a789
AM
406 @Override
407 public void widgetSelected(SelectionEvent e) {
40b7b614 408 TreeSelection selection = (TreeSelection) fTree.getViewer().getSelection();
8906e53c 409
03beb743
SM
410 for (Object element : selection.toArray()) {
411 checkElement(element);
8f91a789 412 }
8906e53c 413
8f91a789
AM
414 updateOKStatus();
415 }
8906e53c
SM
416 });
417
03beb743 418 checkSubtreeButton.addSelectionListener(new SelectionAdapter() {
8f91a789
AM
419 @Override
420 public void widgetSelected(SelectionEvent e) {
40b7b614 421 TreeSelection selection = (TreeSelection) fTree.getViewer().getSelection();
03beb743
SM
422
423 for (Object element : selection.toArray()) {
424 checkElementAndSubtree(element);
425 }
426 }
427 });
428
429 checkAllButton.addSelectionListener(new SelectionAdapter() {
430 @Override
431 public void widgetSelected(SelectionEvent e) {
432 Object[] viewerElements = fContentProvider.getElements(fInput);
433
434 for (int i = 0; i < viewerElements.length; i++) {
40b7b614 435 fTree.setSubtreeChecked(viewerElements[i], true);
03beb743
SM
436 }
437
8f91a789
AM
438 updateOKStatus();
439 }
8906e53c
SM
440 });
441
03beb743 442 uncheckSelectedButton.addSelectionListener(new SelectionAdapter() {
8906e53c
SM
443 @Override
444 public void widgetSelected(SelectionEvent e) {
40b7b614 445 TreeSelection selection = (TreeSelection) fTree.getViewer().getSelection();
8906e53c
SM
446
447 for (Object element : selection.toArray()) {
03beb743 448 uncheckElement(element);
8906e53c
SM
449 }
450
451 updateOKStatus();
452 }
453 });
454
03beb743 455 uncheckSubtreeButton.addSelectionListener(new SelectionAdapter() {
8906e53c
SM
456 @Override
457 public void widgetSelected(SelectionEvent e) {
40b7b614 458 TreeSelection selection = (TreeSelection) fTree.getViewer().getSelection();
8906e53c
SM
459
460 for (Object element : selection.toArray()) {
461 uncheckElement(element);
462 }
463
464 updateOKStatus();
465 }
466 });
467
03beb743
SM
468 uncheckAllButton.addSelectionListener(new SelectionAdapter() {
469 @Override
470 public void widgetSelected(SelectionEvent e) {
40b7b614
GP
471 Object[] viewerElements = fContentProvider.getElements(fInput);
472 for (Object element : viewerElements) {
473 if (fTree.getViewer().testFindItem(element) != null) {
474 // uncheck only visible roots and their children
475 uncheckElement(element);
476 }
477 }
03beb743
SM
478 updateOKStatus();
479 }
480 });
481
8f91a789
AM
482 return buttonComposite;
483 }
484
03beb743
SM
485 /**
486 * Check an element and all its parents.
487 *
488 * @param element
489 * The element to check.
490 */
8906e53c 491 private void checkElement(Object element) {
40b7b614 492 fTree.setChecked(element, true);
03beb743
SM
493
494 Object parent = fContentProvider.getParent(element);
495
40b7b614 496 if (parent != null && !fTree.getChecked(parent)) {
03beb743 497 checkElement(parent);
8906e53c
SM
498 }
499 }
500
03beb743
SM
501 /**
502 * Check an element, all its parents and all its children.
503 *
504 * @param element
505 * The element to check.
506 */
507 private void checkElementAndSubtree(Object element) {
508 checkElement(element);
509
510 for (Object child : fContentProvider.getChildren(element)) {
511 checkElementAndSubtree(child);
512 }
513 }
8906e53c 514
03beb743
SM
515 /**
516 * Uncheck an element and all its children.
517 *
518 * @param element
519 * The element to uncheck.
520 */
521 private void uncheckElement(Object element) {
40b7b614 522 fTree.setChecked(element, false);
8906e53c 523
03beb743 524 for (Object child : fContentProvider.getChildren(element)) {
8906e53c
SM
525 uncheckElement(child);
526 }
527 }
528
8f91a789
AM
529 private boolean evaluateIfTreeEmpty(Object input) {
530 Object[] elements = fContentProvider.getElements(input);
f1fae91f
PT
531 if (elements.length > 0 && fFilters != null) {
532 for (int i = 0; i < fFilters.size(); i++) {
533 ViewerFilter curr = fFilters.get(i);
40b7b614 534 elements = curr.filter(fTree.getViewer(), input, elements);
8f91a789
AM
535 }
536 }
537 return elements.length == 0;
538 }
539
540 /**
541 * Private classes
542 */
543
544 private class CheckStateListener implements ICheckStateListener {
545
546 CheckStateListener() {
547 }
8906e53c 548
8f91a789
AM
549 @Override
550 public void checkStateChanged(CheckStateChangedEvent event) {
551 try {
552 ITimeGraphEntry entry = (ITimeGraphEntry) event.getElement();
553 boolean checked = event.getChecked();
8906e53c
SM
554 if (checked) {
555 checkElement(entry);
556 } else {
557 uncheckElement(entry);
8f91a789
AM
558 }
559 } catch (ClassCastException e) {
560 return;
40b7b614
GP
561 } finally {
562 updateOKStatus();
8f91a789
AM
563 }
564 }
40b7b614 565
8f91a789 566 }
40b7b614 567}
This page took 0.083094 seconds and 5 git commands to generate.