Fixed: could not access linked resources
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / dialogs / CheckedTreeSelectionDialog.java
1 package net.sourceforge.phpdt.internal.ui.dialogs;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.List;
6
7 import net.sourceforge.phpdt.internal.ui.viewsupport.ContainerCheckedTreeViewer;
8
9 import org.eclipse.core.runtime.IStatus;
10 import org.eclipse.jface.dialogs.IDialogConstants;
11 import org.eclipse.jface.viewers.CheckStateChangedEvent;
12 import org.eclipse.jface.viewers.CheckboxTreeViewer;
13 import org.eclipse.jface.viewers.ICheckStateListener;
14 import org.eclipse.jface.viewers.ILabelProvider;
15 import org.eclipse.jface.viewers.ITreeContentProvider;
16 import org.eclipse.jface.viewers.ViewerFilter;
17 import org.eclipse.jface.viewers.ViewerSorter;
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.custom.BusyIndicator;
20 import org.eclipse.swt.events.SelectionAdapter;
21 import org.eclipse.swt.events.SelectionEvent;
22 import org.eclipse.swt.events.SelectionListener;
23 import org.eclipse.swt.layout.GridData;
24 import org.eclipse.swt.layout.GridLayout;
25 import org.eclipse.swt.widgets.Button;
26 import org.eclipse.swt.widgets.Composite;
27 import org.eclipse.swt.widgets.Control;
28 import org.eclipse.swt.widgets.Label;
29 import org.eclipse.swt.widgets.Shell;
30 import org.eclipse.swt.widgets.Tree;
31
32 /**
33  * A class to select elements out of a tree structure.
34  */
35 public class CheckedTreeSelectionDialog extends SelectionStatusDialog {
36
37         private CheckboxTreeViewer fViewer;
38
39         private ILabelProvider fLabelProvider;
40
41         private ITreeContentProvider fContentProvider;
42
43         private ISelectionValidator fValidator = null;
44
45         private ViewerSorter fSorter;
46
47         private String fEmptyListMessage = "No entries available";
48
49         private IStatus fCurrStatus = new StatusInfo();
50
51         private List fFilters;
52
53         private Object fInput;
54
55         private boolean fIsEmpty;
56
57         private int fWidth = 60;
58
59         private int fHeight = 18;
60
61         private boolean fContainerMode;
62
63         private Object[] fExpandedElements;
64
65         /**
66          * Constructs an instance of <code>ElementTreeSelectionDialog</code>.
67          * 
68          * @param labelProvider
69          *            the label provider to render the entries
70          * @param contentProvider
71          *            the content provider to evaluate the tree structure
72          */
73         public CheckedTreeSelectionDialog(Shell parent,
74                         ILabelProvider labelProvider, ITreeContentProvider contentProvider) {
75                 super(parent);
76
77                 fLabelProvider = labelProvider;
78                 fContentProvider = contentProvider;
79
80                 setResult(new ArrayList(0));
81                 setStatusLineAboveButtons(true);
82
83                 fContainerMode = false;
84                 fExpandedElements = null;
85
86                 int shellStyle = getShellStyle();
87                 setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE);
88         }
89
90         /**
91          * If set, the checked /gray state of containers (inner nodes) is derived
92          * from the checked state of its leaf nodes.
93          * 
94          * @param containerMode
95          *            The containerMode to set
96          */
97         public void setContainerMode(boolean containerMode) {
98                 fContainerMode = containerMode;
99         }
100
101         /**
102          * Sets the initial selection. Convenience method.
103          * 
104          * @param selection
105          *            the initial selection.
106          */
107         public void setInitialSelection(Object selection) {
108                 setInitialSelections(new Object[] { selection });
109         }
110
111         /**
112          * Sets the message to be displayed if the list is empty.
113          * 
114          * @param message
115          *            the message to be displayed.
116          */
117         public void setEmptyListMessage(String message) {
118                 fEmptyListMessage = message;
119         }
120
121         /**
122          * Sets the sorter used by the tree viewer.
123          */
124         public void setSorter(ViewerSorter sorter) {
125                 fSorter = sorter;
126         }
127
128         /**
129          * Adds a filter to the tree viewer.
130          * 
131          * @param filter
132          *            a filter.
133          */
134         public void addFilter(ViewerFilter filter) {
135                 if (fFilters == null)
136                         fFilters = new ArrayList(4);
137
138                 fFilters.add(filter);
139         }
140
141         /**
142          * Sets an optional validator to check if the selection is valid. The
143          * validator is invoked whenever the selection changes.
144          * 
145          * @param validator
146          *            the validator to validate the selection.
147          */
148         public void setValidator(ISelectionValidator validator) {
149                 fValidator = validator;
150         }
151
152         /**
153          * Sets the tree input.
154          * 
155          * @param input
156          *            the tree input.
157          */
158         public void setInput(Object input) {
159                 fInput = input;
160         }
161
162         /**
163          * Expands the tree
164          */
165         public void setExpandedElements(Object[] elements) {
166                 fExpandedElements = elements;
167         }
168
169         /**
170          * Sets the size of the tree in unit of characters.
171          * 
172          * @param width
173          *            the width of the tree.
174          * @param height
175          *            the height of the tree.
176          */
177         public void setSize(int width, int height) {
178                 fWidth = width;
179                 fHeight = height;
180         }
181
182         protected void updateOKStatus() {
183                 if (!fIsEmpty) {
184                         if (fValidator != null) {
185                                 fCurrStatus = fValidator.validate(fViewer.getCheckedElements());
186                                 updateStatus(fCurrStatus);
187                         } else if (!fCurrStatus.isOK()) {
188                                 fCurrStatus = new StatusInfo();
189                         }
190                 } else {
191                         fCurrStatus = new StatusInfo(IStatus.ERROR, fEmptyListMessage);
192                 }
193                 updateStatus(fCurrStatus);
194         }
195
196         /*
197          * @see Window#open()
198          */
199         public int open() {
200                 fIsEmpty = evaluateIfTreeEmpty(fInput);
201                 BusyIndicator.showWhile(null, new Runnable() {
202                         public void run() {
203                                 access$superOpen();
204                         }
205                 });
206
207                 return getReturnCode();
208         }
209
210         private void access$superOpen() {
211                 super.open();
212         }
213
214         /**
215          * Handles cancel button pressed event.
216          */
217         protected void cancelPressed() {
218                 setResult(null);
219                 super.cancelPressed();
220         }
221
222         /*
223          * @see SelectionStatusDialog#computeResult()
224          */
225         protected void computeResult() {
226                 setResult(Arrays.asList(fViewer.getCheckedElements()));
227         }
228
229         /*
230          * @see Window#create()
231          */
232         public void create() {
233                 super.create();
234
235                 List initialSelections = getInitialElementSelections();
236                 if (initialSelections != null) {
237                         fViewer.setCheckedElements(initialSelections.toArray());
238                 }
239
240                 if (fExpandedElements != null) {
241                         fViewer.setExpandedElements(fExpandedElements);
242                 }
243
244                 updateOKStatus();
245         }
246
247         /*
248          * @see Dialog#createDialogArea(Composite)
249          */
250         protected Control createDialogArea(Composite parent) {
251                 Composite composite = (Composite) super.createDialogArea(parent);
252
253                 Label messageLabel = createMessageArea(composite);
254                 Control treeWidget = createTreeViewer(composite);
255                 Control buttonComposite = createSelectionButtons(composite);
256
257                 GridData data = new GridData(GridData.FILL_BOTH);
258                 data.widthHint = convertWidthInCharsToPixels(fWidth);
259                 data.heightHint = convertHeightInCharsToPixels(fHeight);
260                 treeWidget.setLayoutData(data);
261
262                 if (fIsEmpty) {
263                         messageLabel.setEnabled(false);
264                         treeWidget.setEnabled(false);
265                         buttonComposite.setEnabled(false);
266                 }
267
268                 return composite;
269         }
270
271         private Tree createTreeViewer(Composite parent) {
272                 if (fContainerMode) {
273                         fViewer = new ContainerCheckedTreeViewer(parent, SWT.BORDER);
274                 } else {
275                         fViewer = new CheckboxTreeViewer(parent, SWT.BORDER);
276                 }
277
278                 fViewer.setContentProvider(fContentProvider);
279                 fViewer.setLabelProvider(fLabelProvider);
280                 fViewer.addCheckStateListener(new ICheckStateListener() {
281                         public void checkStateChanged(CheckStateChangedEvent event) {
282                                 updateOKStatus();
283                         }
284                 });
285
286                 fViewer.setSorter(fSorter);
287                 if (fFilters != null) {
288                         for (int i = 0; i != fFilters.size(); i++)
289                                 fViewer.addFilter((ViewerFilter) fFilters.get(i));
290                 }
291
292                 fViewer.setInput(fInput);
293
294                 return fViewer.getTree();
295         }
296
297         /**
298          * Add the selection and deselection buttons to the dialog.
299          * 
300          * @param composite
301          *            org.eclipse.swt.widgets.Composite
302          */
303         private Composite createSelectionButtons(Composite composite) {
304
305                 Composite buttonComposite = new Composite(composite, SWT.RIGHT);
306                 GridLayout layout = new GridLayout();
307                 layout.numColumns = 2;
308                 buttonComposite.setLayout(layout);
309                 GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END
310                                 | GridData.GRAB_HORIZONTAL);
311                 data.grabExcessHorizontalSpace = true;
312                 composite.setData(data);
313
314                 Button selectButton = createButton(buttonComposite,
315                                 IDialogConstants.SELECT_ALL_ID, "Select &All", false);
316
317                 SelectionListener listener = new SelectionAdapter() {
318                         public void widgetSelected(SelectionEvent e) {
319                                 fViewer
320                                                 .setCheckedElements(fContentProvider
321                                                                 .getElements(fInput));
322                                 updateOKStatus();
323                         }
324                 };
325                 selectButton.addSelectionListener(listener);
326
327                 Button deselectButton = createButton(buttonComposite,
328                                 IDialogConstants.DESELECT_ALL_ID, "&Deselect All", false);
329
330                 listener = new SelectionAdapter() {
331                         public void widgetSelected(SelectionEvent e) {
332                                 fViewer.setCheckedElements(new Object[0]);
333                                 updateOKStatus();
334                         }
335                 };
336                 deselectButton.addSelectionListener(listener);
337                 return buttonComposite;
338         }
339
340         private boolean evaluateIfTreeEmpty(Object input) {
341                 Object[] elements = fContentProvider.getElements(input);
342                 if (elements.length > 0) {
343                         if (fFilters != null) {
344                                 for (int i = 0; i < fFilters.size(); i++) {
345                                         ViewerFilter curr = (ViewerFilter) fFilters.get(i);
346                                         elements = curr.filter(fViewer, input, elements);
347                                 }
348                         }
349                 }
350                 return elements.length == 0;
351         }
352
353 }