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