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
.TreeSelection
;
33 import org
.eclipse
.jface
.viewers
.ViewerComparator
;
34 import org
.eclipse
.jface
.viewers
.ViewerFilter
;
35 import org
.eclipse
.linuxtools
.internal
.tmf
.ui
.Messages
;
36 import org
.eclipse
.linuxtools
.tmf
.ui
.widgets
.timegraph
.model
.ITimeGraphEntry
;
37 import org
.eclipse
.swt
.SWT
;
38 import org
.eclipse
.swt
.custom
.BusyIndicator
;
39 import org
.eclipse
.swt
.events
.SelectionAdapter
;
40 import org
.eclipse
.swt
.events
.SelectionEvent
;
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
.ISelectionStatusValidator
;
52 import org
.eclipse
.ui
.dialogs
.SelectionStatusDialog
;
55 * Filter dialog for the time graphs
56 * This class is derived from the CheckedTreeSelectionDialog
57 * It was necessary to develop this similar dialog to allow multiple columns
61 * @author François Rajotte
63 public class TimeGraphFilterDialog
extends SelectionStatusDialog
{
65 private CheckboxTreeViewer fViewer
;
67 private IBaseLabelProvider fLabelProvider
;
69 private ITreeContentProvider fContentProvider
;
71 private String
[] fColumnNames
;
73 private ISelectionStatusValidator fValidator
= null;
75 private ViewerComparator fComparator
;
77 private String fEmptyListMessage
= ""; //$NON-NLS-1$
79 private IStatus fCurrStatus
= new Status(IStatus
.OK
, PlatformUI
.PLUGIN_ID
,
80 0, "", null); //$NON-NLS-1$
82 private List
<ViewerFilter
> fFilters
;
84 private Object fInput
;
86 private boolean fIsEmpty
;
88 private int fWidth
= 60;
90 private int fHeight
= 18;
92 private Object
[] fExpandedElements
;
95 * Constructs an instance of <code>ElementTreeSelectionDialog</code>.
98 * The shell to parent from.
100 public TimeGraphFilterDialog(Shell parent
) {
102 setResult(new ArrayList
<Object
>(0));
103 setStatusLineAboveButtons(true);
104 setHelpAvailable(false);
105 fExpandedElements
= null;
109 * Sets the initial selection. Convenience method.
112 * the initial selection.
114 public void setInitialSelection(Object selection
) {
115 setInitialSelections(new Object
[] { selection
});
119 * Sets the message to be displayed if the list is empty.
122 * the message to be displayed.
124 public void setEmptyListMessage(String message
) {
125 fEmptyListMessage
= message
;
129 * Sets the comparator used by the tree viewer.
134 public void setComparator(ViewerComparator comparator
) {
135 fComparator
= comparator
;
139 * Adds a filter to the tree viewer.
144 public void addFilter(ViewerFilter filter
) {
145 if (fFilters
== null) {
146 fFilters
= new ArrayList
<ViewerFilter
>(4);
148 fFilters
.add(filter
);
152 * Sets an optional validator to check if the selection is valid. The
153 * validator is invoked whenever the selection changes.
156 * the validator to validate the selection.
158 public void setValidator(ISelectionStatusValidator validator
) {
159 fValidator
= validator
;
163 * Sets the tree input.
168 public void setInput(Object input
) {
173 * Expands elements in the tree.
176 * The elements that will be expanded.
178 public void setExpandedElements(Object
[] elements
) {
179 fExpandedElements
= elements
;
183 * Sets the size of the tree in unit of characters.
186 * the width of the tree.
188 * the height of the tree.
190 public void setSize(int width
, int height
) {
196 * @param contentProvider The content provider for the table
198 public void setContentProvider(ITreeContentProvider contentProvider
) {
199 fContentProvider
= contentProvider
;
203 * @param labelProvider The label provider for the table
205 public void setLabelProvider(IBaseLabelProvider labelProvider
) {
206 fLabelProvider
= labelProvider
;
210 * @param columnNames An array of column names to display
212 public void setColumnNames(String
[] columnNames
) {
213 fColumnNames
= columnNames
;
217 * Validate the receiver and update the status with the result.
220 protected void updateOKStatus() {
222 if (fValidator
!= null) {
223 fCurrStatus
= fValidator
.validate(fViewer
.getCheckedElements());
224 updateStatus(fCurrStatus
);
225 } else if (!fCurrStatus
.isOK()) {
226 fCurrStatus
= new Status(IStatus
.OK
, PlatformUI
.PLUGIN_ID
,
227 IStatus
.OK
, "", //$NON-NLS-1$
231 fCurrStatus
= new Status(IStatus
.ERROR
, PlatformUI
.PLUGIN_ID
,
232 IStatus
.OK
, fEmptyListMessage
, null);
234 updateStatus(fCurrStatus
);
239 fIsEmpty
= evaluateIfTreeEmpty(fInput
);
241 return getReturnCode();
244 private void access$
superCreate() {
249 protected void cancelPressed() {
251 super.cancelPressed();
255 protected void computeResult() {
256 setResult(Arrays
.asList(fViewer
.getCheckedElements()));
260 public void create() {
261 BusyIndicator
.showWhile(null, new Runnable() {
264 access$
superCreate();
265 fViewer
.setCheckedElements(getInitialElementSelections()
267 if (fExpandedElements
!= null) {
268 fViewer
.setExpandedElements(fExpandedElements
);
276 protected Control
createDialogArea(Composite parent
) {
277 Composite composite
= (Composite
) super.createDialogArea(parent
);
278 Label messageLabel
= createMessageArea(composite
);
279 CheckboxTreeViewer treeViewer
= createTreeViewer(composite
);
280 Control buttonComposite
= createSelectionButtons(composite
);
281 GridData data
= new GridData(GridData
.FILL_BOTH
);
282 data
.widthHint
= convertWidthInCharsToPixels(fWidth
);
283 data
.heightHint
= convertHeightInCharsToPixels(fHeight
);
284 Tree treeWidget
= treeViewer
.getTree();
285 treeWidget
.setLayoutData(data
);
286 treeWidget
.setFont(parent
.getFont());
288 messageLabel
.setEnabled(false);
289 treeWidget
.setEnabled(false);
290 buttonComposite
.setEnabled(false);
296 * Creates the tree viewer.
299 * the parent composite
300 * @return the tree viewer
302 protected CheckboxTreeViewer
createTreeViewer(Composite parent
) {
303 fViewer
= new CheckboxTreeViewer(parent
, SWT
.BORDER
| SWT
.MULTI
);
305 Tree tree
= fViewer
.getTree();
306 tree
.setHeaderVisible(true);
307 for (String columnName
: fColumnNames
) {
308 TreeColumn column
= new TreeColumn(tree
, SWT
.LEFT
);
309 column
.setText(columnName
);
313 fViewer
.setContentProvider(fContentProvider
);
314 fViewer
.setLabelProvider(fLabelProvider
);
315 fViewer
.addCheckStateListener(new CheckStateListener());
316 fViewer
.addCheckStateListener(new ICheckStateListener() {
318 public void checkStateChanged(CheckStateChangedEvent event
) {
322 fViewer
.setComparator(fComparator
);
323 if (fFilters
!= null) {
324 for (int i
= 0; i
!= fFilters
.size(); i
++) {
325 fViewer
.addFilter(fFilters
.get(i
));
328 fViewer
.setInput(fInput
);
330 //pack the columns again for a nice view...
331 for (TreeColumn column
: tree
.getColumns()) {
338 * Returns the tree viewer.
340 * @return the tree viewer
342 protected CheckboxTreeViewer
getTreeViewer() {
347 * Adds the selection and deselection buttons to the dialog.
350 * the parent composite
351 * @return Composite the composite the buttons were created in.
353 protected Composite
createSelectionButtons(Composite composite
) {
354 Composite buttonComposite
= new Composite(composite
, SWT
.RIGHT
);
355 GridLayout layout
= new GridLayout();
356 layout
.numColumns
= 2;
357 layout
.marginWidth
= 0;
358 layout
.horizontalSpacing
= convertHorizontalDLUsToPixels(IDialogConstants
.HORIZONTAL_SPACING
);
359 buttonComposite
.setLayout(layout
);
360 buttonComposite
.setFont(composite
.getFont());
361 GridData data
= new GridData(GridData
.HORIZONTAL_ALIGN_END
362 | GridData
.GRAB_HORIZONTAL
);
363 data
.grabExcessHorizontalSpace
= true;
364 buttonComposite
.setLayoutData(data
);
366 /* Create the buttons in the good order to place them as we want */
367 Button checkAllButton
= createButton(buttonComposite
,
368 IDialogConstants
.SELECT_ALL_ID
, Messages
.TmfTimeFilterDialog_CHECK_ALL
,
370 Button checkSelectedButton
= createButton(buttonComposite
,
371 IDialogConstants
.CLIENT_ID
, Messages
.TmfTimeFilterDialog_CHECK_SELECTED
,
373 Button uncheckAllButton
= createButton(buttonComposite
,
374 IDialogConstants
.DESELECT_ALL_ID
, Messages
.TmfTimeFilterDialog_UNCHECK_ALL
,
376 Button uncheckSelectedButton
= createButton(buttonComposite
,
377 IDialogConstants
.CLIENT_ID
+ 1, Messages
.TmfTimeFilterDialog_UNCHECK_SELECTED
,
381 * Apply the layout again after creating the buttons to override
382 * createButton messing with the columns
384 layout
.numColumns
= 2;
385 buttonComposite
.setLayout(layout
);
387 /* Add a listener to each button */
388 checkAllButton
.addSelectionListener(new SelectionAdapter() {
390 public void widgetSelected(SelectionEvent e
) {
391 Object
[] viewerElements
= fContentProvider
.getElements(fInput
);
393 for (int i
= 0; i
< viewerElements
.length
; i
++) {
394 fViewer
.setSubtreeChecked(viewerElements
[i
], true);
401 uncheckAllButton
.addSelectionListener(new SelectionAdapter() {
403 public void widgetSelected(SelectionEvent e
) {
404 fViewer
.setCheckedElements(new Object
[0]);
409 checkSelectedButton
.addSelectionListener(new SelectionAdapter() {
411 public void widgetSelected(SelectionEvent e
) {
412 TreeSelection selection
= (TreeSelection
) fViewer
.getSelection();
414 for (Object element
: selection
.toArray()) {
415 checkElement(element
);
422 uncheckSelectedButton
.addSelectionListener(new SelectionAdapter() {
424 public void widgetSelected(SelectionEvent e
) {
425 TreeSelection selection
= (TreeSelection
) fViewer
.getSelection();
427 for (Object element
: selection
.toArray()) {
428 uncheckElement(element
);
435 return buttonComposite
;
438 private void checkElement(Object element
) {
441 fViewer
.setChecked(e
, true);
442 e
= fContentProvider
.getParent(e
);
446 private void uncheckElement(Object element
) {
449 fViewer
.setChecked(e
, false);
451 for (Object child
: fContentProvider
.getChildren(e
)) {
452 uncheckElement(child
);
456 private boolean evaluateIfTreeEmpty(Object input
) {
457 Object
[] elements
= fContentProvider
.getElements(input
);
458 if (elements
.length
> 0) {
459 if (fFilters
!= null) {
460 for (int i
= 0; i
< fFilters
.size(); i
++) {
461 ViewerFilter curr
= fFilters
.get(i
);
462 elements
= curr
.filter(fViewer
, input
, elements
);
466 return elements
.length
== 0;
473 private class CheckStateListener
implements ICheckStateListener
{
475 CheckStateListener() {
479 public void checkStateChanged(CheckStateChangedEvent event
) {
481 ITimeGraphEntry entry
= (ITimeGraphEntry
) event
.getElement();
482 boolean checked
= event
.getChecked();
486 uncheckElement(entry
);
488 } catch (ClassCastException e
) {