1 /*******************************************************************************
2 * Copyright (c) 2000, 2013 IBM Corporation and others.
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
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
16 *******************************************************************************/
18 package org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.dialogs
;
20 import java
.util
.ArrayList
;
21 import java
.util
.Arrays
;
22 import java
.util
.List
;
24 import org
.eclipse
.core
.runtime
.IStatus
;
25 import org
.eclipse
.core
.runtime
.Status
;
26 import org
.eclipse
.jface
.dialogs
.IDialogConstants
;
27 import org
.eclipse
.jface
.viewers
.CheckStateChangedEvent
;
28 import org
.eclipse
.jface
.viewers
.CheckboxTreeViewer
;
29 import org
.eclipse
.jface
.viewers
.IBaseLabelProvider
;
30 import org
.eclipse
.jface
.viewers
.ICheckStateListener
;
31 import org
.eclipse
.jface
.viewers
.ITreeContentProvider
;
32 import org
.eclipse
.jface
.viewers
.ViewerComparator
;
33 import org
.eclipse
.jface
.viewers
.ViewerFilter
;
34 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.Messages
;
35 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
36 import org
.eclipse
.swt
.SWT
;
37 import org
.eclipse
.swt
.custom
.BusyIndicator
;
38 import org
.eclipse
.swt
.events
.SelectionAdapter
;
39 import org
.eclipse
.swt
.events
.SelectionEvent
;
40 import org
.eclipse
.swt
.events
.SelectionListener
;
41 import org
.eclipse
.swt
.layout
.GridData
;
42 import org
.eclipse
.swt
.layout
.GridLayout
;
43 import org
.eclipse
.swt
.widgets
.Button
;
44 import org
.eclipse
.swt
.widgets
.Composite
;
45 import org
.eclipse
.swt
.widgets
.Control
;
46 import org
.eclipse
.swt
.widgets
.Label
;
47 import org
.eclipse
.swt
.widgets
.Shell
;
48 import org
.eclipse
.swt
.widgets
.Tree
;
49 import org
.eclipse
.swt
.widgets
.TreeColumn
;
50 import org
.eclipse
.ui
.PlatformUI
;
51 import org
.eclipse
.ui
.dialogs
.ContainerCheckedTreeViewer
;
52 import org
.eclipse
.ui
.dialogs
.ISelectionStatusValidator
;
53 import org
.eclipse
.ui
.dialogs
.SelectionStatusDialog
;
56 * Filter dialog for the time graphs
57 * This class is derived from the CheckedTreeSelectionDialog
58 * It was necessary to develop this similar dialog to allow multiple columns
62 * @author François Rajotte
64 public class TimeGraphFilterDialog
extends SelectionStatusDialog
{
66 private CheckboxTreeViewer fViewer
;
68 private IBaseLabelProvider fLabelProvider
;
70 private ITreeContentProvider fContentProvider
;
72 private String
[] fColumnNames
;
74 private ISelectionStatusValidator fValidator
= null;
76 private ViewerComparator fComparator
;
78 private String fEmptyListMessage
= ""; //$NON-NLS-1$
80 private IStatus fCurrStatus
= new Status(IStatus
.OK
, PlatformUI
.PLUGIN_ID
,
81 0, "", null); //$NON-NLS-1$
83 private List
<ViewerFilter
> fFilters
;
85 private Object fInput
;
87 private boolean fIsEmpty
;
89 private int fWidth
= 60;
91 private int fHeight
= 18;
93 private boolean fContainerMode
;
95 private Object
[] fExpandedElements
;
98 * Constructs an instance of <code>ElementTreeSelectionDialog</code>.
101 * The shell to parent from.
103 public TimeGraphFilterDialog(Shell parent
) {
105 setResult(new ArrayList
<Object
>(0));
106 setStatusLineAboveButtons(true);
107 setHelpAvailable(false);
108 fContainerMode
= false;
109 fExpandedElements
= null;
113 * If set, the checked /gray state of containers (inner nodes) is derived
114 * from the checked state of its leaf nodes.
116 * @param containerMode
117 * The containerMode to set
119 public void setContainerMode(boolean containerMode
) {
120 fContainerMode
= containerMode
;
124 * Sets the initial selection. Convenience method.
127 * the initial selection.
129 public void setInitialSelection(Object selection
) {
130 setInitialSelections(new Object
[] { selection
});
134 * Sets the message to be displayed if the list is empty.
137 * the message to be displayed.
139 public void setEmptyListMessage(String message
) {
140 fEmptyListMessage
= message
;
144 * Sets the comparator used by the tree viewer.
149 public void setComparator(ViewerComparator comparator
) {
150 fComparator
= comparator
;
154 * Adds a filter to the tree viewer.
159 public void addFilter(ViewerFilter filter
) {
160 if (fFilters
== null) {
161 fFilters
= new ArrayList
<ViewerFilter
>(4);
163 fFilters
.add(filter
);
167 * Sets an optional validator to check if the selection is valid. The
168 * validator is invoked whenever the selection changes.
171 * the validator to validate the selection.
173 public void setValidator(ISelectionStatusValidator validator
) {
174 fValidator
= validator
;
178 * Sets the tree input.
183 public void setInput(Object input
) {
188 * Expands elements in the tree.
191 * The elements that will be expanded.
193 public void setExpandedElements(Object
[] elements
) {
194 fExpandedElements
= elements
;
198 * Sets the size of the tree in unit of characters.
201 * the width of the tree.
203 * the height of the tree.
205 public void setSize(int width
, int height
) {
211 * @param contentProvider The content provider for the table
213 public void setContentProvider(ITreeContentProvider contentProvider
) {
214 fContentProvider
= contentProvider
;
218 * @param labelProvider The label provider for the table
220 public void setLabelProvider(IBaseLabelProvider labelProvider
) {
221 fLabelProvider
= labelProvider
;
225 * @param columnNames An array of column names to display
227 public void setColumnNames(String
[] columnNames
) {
228 fColumnNames
= columnNames
;
232 * Validate the receiver and update the status with the result.
235 protected void updateOKStatus() {
237 if (fValidator
!= null) {
238 fCurrStatus
= fValidator
.validate(fViewer
.getCheckedElements());
239 updateStatus(fCurrStatus
);
240 } else if (!fCurrStatus
.isOK()) {
241 fCurrStatus
= new Status(IStatus
.OK
, PlatformUI
.PLUGIN_ID
,
242 IStatus
.OK
, "", //$NON-NLS-1$
246 fCurrStatus
= new Status(IStatus
.ERROR
, PlatformUI
.PLUGIN_ID
,
247 IStatus
.OK
, fEmptyListMessage
, null);
249 updateStatus(fCurrStatus
);
254 fIsEmpty
= evaluateIfTreeEmpty(fInput
);
256 return getReturnCode();
259 private void access$
superCreate() {
264 protected void cancelPressed() {
266 super.cancelPressed();
270 protected void computeResult() {
271 setResult(Arrays
.asList(fViewer
.getCheckedElements()));
275 public void create() {
276 BusyIndicator
.showWhile(null, new Runnable() {
279 access$
superCreate();
280 fViewer
.setCheckedElements(getInitialElementSelections()
282 if (fExpandedElements
!= null) {
283 fViewer
.setExpandedElements(fExpandedElements
);
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());
303 messageLabel
.setEnabled(false);
304 treeWidget
.setEnabled(false);
305 buttonComposite
.setEnabled(false);
311 * Creates the tree viewer.
314 * the parent composite
315 * @return the tree viewer
317 protected CheckboxTreeViewer
createTreeViewer(Composite parent
) {
318 if (fContainerMode
) {
319 fViewer
= new ContainerCheckedTreeViewer(parent
, SWT
.BORDER
);
321 fViewer
= new CheckboxTreeViewer(parent
, SWT
.BORDER
);
324 Tree tree
= fViewer
.getTree();
325 tree
.setHeaderVisible(true);
326 for (String columnName
: fColumnNames
) {
327 TreeColumn column
= new TreeColumn(tree
, SWT
.LEFT
);
328 column
.setText(columnName
);
332 fViewer
.setContentProvider(fContentProvider
);
333 fViewer
.setLabelProvider(fLabelProvider
);
334 fViewer
.addCheckStateListener(new CheckStateListener());
335 fViewer
.addCheckStateListener(new ICheckStateListener() {
337 public void checkStateChanged(CheckStateChangedEvent event
) {
341 fViewer
.setComparator(fComparator
);
342 if (fFilters
!= null) {
343 for (int i
= 0; i
!= fFilters
.size(); i
++) {
344 fViewer
.addFilter(fFilters
.get(i
));
347 fViewer
.setInput(fInput
);
349 //pack the columns again for a nice view...
350 for (TreeColumn column
: tree
.getColumns()) {
357 * Returns the tree viewer.
359 * @return the tree viewer
361 protected CheckboxTreeViewer
getTreeViewer() {
366 * Adds the selection and deselection buttons to the dialog.
369 * the parent composite
370 * @return Composite the composite the buttons were created in.
372 protected Composite
createSelectionButtons(Composite composite
) {
373 Composite buttonComposite
= new Composite(composite
, SWT
.RIGHT
);
374 GridLayout layout
= new GridLayout();
375 layout
.numColumns
= 0;
376 layout
.marginWidth
= 0;
377 layout
.horizontalSpacing
= convertHorizontalDLUsToPixels(IDialogConstants
.HORIZONTAL_SPACING
);
378 buttonComposite
.setLayout(layout
);
379 buttonComposite
.setFont(composite
.getFont());
380 GridData data
= new GridData(GridData
.HORIZONTAL_ALIGN_END
381 | GridData
.GRAB_HORIZONTAL
);
382 data
.grabExcessHorizontalSpace
= true;
383 buttonComposite
.setLayoutData(data
);
384 Button selectButton
= createButton(buttonComposite
,
385 IDialogConstants
.SELECT_ALL_ID
, Messages
.TmfTimeFilterDialog_SELECT_ALL
,
387 SelectionListener listener
= new SelectionAdapter() {
389 public void widgetSelected(SelectionEvent e
) {
390 Object
[] viewerElements
= fContentProvider
.getElements(fInput
);
391 if (fContainerMode
) {
392 fViewer
.setCheckedElements(viewerElements
);
394 for (int i
= 0; i
< viewerElements
.length
; i
++) {
395 fViewer
.setSubtreeChecked(viewerElements
[i
], true);
401 selectButton
.addSelectionListener(listener
);
402 Button deselectButton
= createButton(buttonComposite
,
403 IDialogConstants
.DESELECT_ALL_ID
, Messages
.TmfTimeFilterDialog_DESELECT_ALL
,
405 listener
= new SelectionAdapter() {
407 public void widgetSelected(SelectionEvent e
) {
408 fViewer
.setCheckedElements(new Object
[0]);
412 deselectButton
.addSelectionListener(listener
);
413 return buttonComposite
;
416 private boolean evaluateIfTreeEmpty(Object input
) {
417 Object
[] elements
= fContentProvider
.getElements(input
);
418 if (elements
.length
> 0) {
419 if (fFilters
!= null) {
420 for (int i
= 0; i
< fFilters
.size(); i
++) {
421 ViewerFilter curr
= fFilters
.get(i
);
422 elements
= curr
.filter(fViewer
, input
, elements
);
426 return elements
.length
== 0;
433 private class CheckStateListener
implements ICheckStateListener
{
435 CheckStateListener() {
438 public void checkStateChanged(CheckStateChangedEvent event
) {
440 ITimeGraphEntry entry
= (ITimeGraphEntry
) event
.getElement();
441 boolean checked
= event
.getChecked();
443 uncheckChildren(entry
);
449 } catch (ClassCastException e
) {
454 private void uncheckChildren(ITimeGraphEntry entry
) {
456 for (ITimeGraphEntry child
: entry
.getChildren()) {
457 getTreeViewer().setChecked(child
, false);
458 uncheckChildren(child
);
462 private void checkParent(ITimeGraphEntry entry
) {
464 if (entry
.getParent() != null) {
465 getTreeViewer().setChecked(entry
.getParent(), true);
466 checkParent(entry
.getParent());