f104da5c2b13d3e2025be168def1684dfcbd9d87
[phpeclipse.git] / net.sourceforge.phpeclipse.ui / src / net / sourceforge / phpdt / internal / ui / dialogs / AbstractElementListSelectionDialog.java
1 package net.sourceforge.phpdt.internal.ui.dialogs;
2
3 import net.sourceforge.phpdt.internal.ui.util.FilteredList;
4
5 import org.eclipse.core.runtime.IStatus;
6 import org.eclipse.jface.dialogs.IDialogConstants;
7 //incastrix
8 //import org.eclipse.jface.text.Assert;
9 import org.eclipse.core.runtime.Assert;
10 import org.eclipse.jface.viewers.ILabelProvider;
11 import org.eclipse.swt.SWT;
12 import org.eclipse.swt.custom.BusyIndicator;
13 import org.eclipse.swt.events.KeyEvent;
14 import org.eclipse.swt.events.KeyListener;
15 import org.eclipse.swt.events.SelectionEvent;
16 import org.eclipse.swt.events.SelectionListener;
17 import org.eclipse.swt.layout.GridData;
18 import org.eclipse.swt.widgets.Composite;
19 import org.eclipse.swt.widgets.Event;
20 import org.eclipse.swt.widgets.Label;
21 import org.eclipse.swt.widgets.Listener;
22 import org.eclipse.swt.widgets.Shell;
23 import org.eclipse.swt.widgets.Text;
24
25 /**
26  * An abstract class to select elements out of a list of elements.
27  */
28 public abstract class AbstractElementListSelectionDialog extends
29                 SelectionStatusDialog {
30
31         private ILabelProvider fRenderer;
32
33         private boolean fIgnoreCase = true;
34
35         private boolean fIsMultipleSelection = false;
36
37         private boolean fMatchEmptyString = true;
38
39         private boolean fAllowDuplicates = true;
40
41         private Label fMessage;
42
43         protected FilteredList fFilteredList;
44
45         private Text fFilterText;
46
47         private ISelectionValidator fValidator;
48
49         private String fFilter = null;
50
51         private String fEmptyListMessage = ""; //$NON-NLS-1$
52
53         private String fEmptySelectionMessage = ""; //$NON-NLS-1$
54
55         private int fWidth = 60;
56
57         private int fHeight = 18;
58
59         private Object[] fSelection = new Object[0];
60
61         /**
62          * Constructs a list selection dialog.
63          * 
64          * @param renderer
65          *            The label renderer used
66          * @param ignoreCase
67          *            Decides if the match string ignores lower/upppr case
68          * @param multipleSelection
69          *            Allow multiple selection
70          */
71         protected AbstractElementListSelectionDialog(Shell parent,
72                         ILabelProvider renderer) {
73                 super(parent);
74                 fRenderer = renderer;
75
76                 int shellStyle = getShellStyle();
77                 setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE);
78         }
79
80         /**
81          * Handles default selection (double click). By default, the OK button is
82          * pressed.
83          */
84         protected void handleDefaultSelected() {
85                 if (validateCurrentSelection())
86                         buttonPressed(IDialogConstants.OK_ID);
87         }
88
89         /**
90          * Specifies if sorting, filtering and folding is case sensitive.
91          */
92         public void setIgnoreCase(boolean ignoreCase) {
93                 fIgnoreCase = ignoreCase;
94         }
95
96         /**
97          * Returns if sorting, filtering and folding is case sensitive.
98          */
99         public boolean isCaseIgnored() {
100                 return fIgnoreCase;
101         }
102
103         /**
104          * Specifies whether everything or nothing should be filtered on empty
105          * filter string.
106          */
107         public void setMatchEmptyString(boolean matchEmptyString) {
108                 fMatchEmptyString = matchEmptyString;
109         }
110
111         /**
112          * Specifies if multiple selection is allowed.
113          */
114         public void setMultipleSelection(boolean multipleSelection) {
115                 fIsMultipleSelection = multipleSelection;
116         }
117
118         /**
119          * Specifies whether duplicate entries are displayed or not.
120          */
121         public void setAllowDuplicates(boolean allowDuplicates) {
122                 fAllowDuplicates = allowDuplicates;
123         }
124
125         /**
126          * Sets the list size in unit of characters.
127          * 
128          * @param width
129          *            the width of the list.
130          * @param height
131          *            the height of the list.
132          */
133         public void setSize(int width, int height) {
134                 fWidth = width;
135                 fHeight = height;
136         }
137
138         /**
139          * Sets the message to be displayed if the list is empty.
140          * 
141          * @param message
142          *            the message to be displayed.
143          */
144         public void setEmptyListMessage(String message) {
145                 fEmptyListMessage = message;
146         }
147
148         /**
149          * Sets the message to be displayed if the selection is empty.
150          * 
151          * @param message
152          *            the message to be displayed.
153          */
154         public void setEmptySelectionMessage(String message) {
155                 fEmptySelectionMessage = message;
156         }
157
158         /**
159          * Sets an optional validator to check if the selection is valid. The
160          * validator is invoked whenever the selection changes.
161          * 
162          * @param validator
163          *            the validator to validate the selection.
164          */
165         public void setValidator(ISelectionValidator validator) {
166                 fValidator = validator;
167         }
168
169         /**
170          * Sets the elements of the list (widget). To be called within open().
171          * 
172          * @param elements
173          *            the elements of the list.
174          */
175         protected void setListElements(Object[] elements) {
176                 Assert.isNotNull(fFilteredList);
177                 fFilteredList.setElements(elements);
178         }
179
180         /**
181          * Sets the filter pattern.
182          * 
183          * @param filter
184          *            the filter pattern.
185          */
186         public void setFilter(String filter) {
187                 if (fFilterText == null)
188                         fFilter = filter;
189                 else
190                         fFilterText.setText(filter);
191         }
192
193         /**
194          * Returns the current filter pattern.
195          * 
196          * @return returns the current filter pattern or
197          *         <code>null<code> if filter was not set.
198          */
199         public String getFilter() {
200                 if (fFilteredList == null)
201                         return fFilter;
202                 else
203                         return fFilteredList.getFilter();
204         }
205
206         /**
207          * Returns the indices referring the current selection. To be called within
208          * open().
209          * 
210          * @return returns the indices of the current selection.
211          */
212         protected int[] getSelectionIndices() {
213                 Assert.isNotNull(fFilteredList);
214                 return fFilteredList.getSelectionIndices();
215         }
216
217         /**
218          * Returns an index referring the first current selection. To be called
219          * within open().
220          * 
221          * @return returns the indices of the current selection.
222          */
223         protected int getSelectionIndex() {
224                 Assert.isNotNull(fFilteredList);
225                 return fFilteredList.getSelectionIndex();
226         }
227
228         /**
229          * Sets the selection referenced by an array of elements. To be called
230          * within open().
231          * 
232          * @param selection
233          *            the indices of the selection.
234          */
235         protected void setSelection(Object[] selection) {
236                 Assert.isNotNull(fFilteredList);
237                 fFilteredList.setSelection(selection);
238         }
239
240         /**
241          * Returns an array of the currently selected elements. To be called within
242          * or after open().
243          * 
244          * @return returns an array of the currently selected elements.
245          */
246         protected Object[] getSelectedElements() {
247                 Assert.isNotNull(fFilteredList);
248                 return fFilteredList.getSelection();
249         }
250
251         /**
252          * Returns all elements which are folded together to one entry in the list.
253          * 
254          * @param index
255          *            the index selecting the entry in the list.
256          * @return returns an array of elements folded together.
257          */
258         public Object[] getFoldedElements(int index) {
259                 Assert.isNotNull(fFilteredList);
260                 return fFilteredList.getFoldedElements(index);
261         }
262
263         /**
264          * Creates the message text widget and sets layout data.
265          * 
266          * @param composite
267          *            the parent composite of the message area.
268          */
269         protected Label createMessageArea(Composite composite) {
270                 Label label = super.createMessageArea(composite);
271
272                 GridData data = new GridData();
273                 data.grabExcessVerticalSpace = false;
274                 data.grabExcessHorizontalSpace = true;
275                 data.horizontalAlignment = GridData.FILL;
276                 data.verticalAlignment = GridData.BEGINNING;
277                 label.setLayoutData(data);
278
279                 fMessage = label;
280
281                 return label;
282         }
283
284         /**
285          * Handles a selection changed event. By default, the current selection is
286          * validated.
287          */
288         protected void handleSelectionChanged() {
289                 validateCurrentSelection();
290         }
291
292         /**
293          * Validates the current selection and updates the status line accordingly.
294          */
295         protected boolean validateCurrentSelection() {
296                 Assert.isNotNull(fFilteredList);
297
298                 IStatus status;
299                 Object[] elements = getSelectedElements();
300
301                 if (elements.length > 0) {
302                         if (fValidator != null) {
303                                 status = fValidator.validate(elements);
304                         } else {
305                                 status = new StatusInfo();
306                         }
307                 } else {
308                         if (fFilteredList.isEmpty()) {
309                                 status = new StatusInfo(IStatus.ERROR, fEmptyListMessage);
310                         } else {
311                                 status = new StatusInfo(IStatus.ERROR, fEmptySelectionMessage);
312                         }
313                 }
314
315                 updateStatus(status);
316
317                 return status.isOK();
318         }
319
320         /*
321          * @see Dialog#cancelPressed
322          */
323         protected void cancelPressed() {
324                 setResult(null);
325                 super.cancelPressed();
326         }
327
328         /**
329          * Creates a filtered list.
330          * 
331          * @param parent
332          *            the parent composite.
333          * @return returns the filtered list widget.
334          */
335         protected FilteredList createFilteredList(Composite parent) {
336                 int flags = SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL
337                                 | (fIsMultipleSelection ? SWT.MULTI : SWT.SINGLE);
338
339                 FilteredList list = new FilteredList(parent, flags, fRenderer,
340                                 fIgnoreCase, fAllowDuplicates, fMatchEmptyString);
341
342                 GridData data = new GridData();
343                 data.widthHint = convertWidthInCharsToPixels(fWidth);
344                 data.heightHint = convertHeightInCharsToPixels(fHeight);
345                 data.grabExcessVerticalSpace = true;
346                 data.grabExcessHorizontalSpace = true;
347                 data.horizontalAlignment = GridData.FILL;
348                 data.verticalAlignment = GridData.FILL;
349                 list.setLayoutData(data);
350
351                 list.setFilter((fFilter == null ? "" : fFilter)); //$NON-NLS-1$         
352
353                 list.addSelectionListener(new SelectionListener() {
354                         public void widgetDefaultSelected(SelectionEvent e) {
355                                 handleDefaultSelected();
356                         }
357
358                         public void widgetSelected(SelectionEvent e) {
359                                 handleWidgetSelected();
360                         }
361                 });
362
363                 fFilteredList = list;
364
365                 return list;
366         }
367
368         // 3515
369         private void handleWidgetSelected() {
370                 Object[] newSelection = fFilteredList.getSelection();
371
372                 if (newSelection.length != fSelection.length) {
373                         fSelection = newSelection;
374                         handleSelectionChanged();
375                 } else {
376                         for (int i = 0; i != newSelection.length; i++) {
377                                 if (!newSelection[i].equals(fSelection[i])) {
378                                         fSelection = newSelection;
379                                         handleSelectionChanged();
380                                         break;
381                                 }
382                         }
383                 }
384         }
385
386         protected Text createFilterText(Composite parent) {
387                 Text text = new Text(parent, SWT.BORDER);
388
389                 GridData data = new GridData();
390                 data.grabExcessVerticalSpace = false;
391                 data.grabExcessHorizontalSpace = true;
392                 data.horizontalAlignment = GridData.FILL;
393                 data.verticalAlignment = GridData.BEGINNING;
394                 text.setLayoutData(data);
395
396                 text.setText((fFilter == null ? "" : fFilter)); //$NON-NLS-1$
397
398                 Listener listener = new Listener() {
399                         public void handleEvent(Event e) {
400                                 fFilteredList.setFilter(fFilterText.getText());
401                         }
402                 };
403                 text.addListener(SWT.Modify, listener);
404
405                 text.addKeyListener(new KeyListener() {
406                         public void keyPressed(KeyEvent e) {
407                                 if (e.keyCode == SWT.ARROW_DOWN)
408                                         fFilteredList.setFocus();
409                         }
410
411                         public void keyReleased(KeyEvent e) {
412                         }
413                 });
414
415                 fFilterText = text;
416
417                 return text;
418         }
419
420         /*
421          * @see Window#open()
422          */
423         public int open() {
424                 BusyIndicator.showWhile(null, new Runnable() {
425                         public void run() {
426                                 access$superOpen();
427                         }
428                 });
429                 return getReturnCode();
430         }
431
432         private void access$superOpen() {
433                 super.open();
434         }
435
436         /*
437          * @see Window#create(Shell)
438          */
439         public void create() {
440                 super.create();
441
442                 Assert.isNotNull(fFilteredList);
443
444                 if (fFilteredList.isEmpty()) {
445                         handleEmptyList();
446                 } else {
447                         validateCurrentSelection();
448                         fFilterText.selectAll();
449                         fFilterText.setFocus();
450                 }
451         }
452
453         /**
454          * Handles empty list by disabling widgets.
455          */
456         protected void handleEmptyList() {
457                 fMessage.setEnabled(false);
458                 fFilterText.setEnabled(false);
459                 fFilteredList.setEnabled(false);
460         }
461
462 }