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