1 package net.sourceforge.phpdt.internal.ui.dialog;
3 import net.sourceforge.phpdt.internal.ui.util.FilteredList;
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;
24 * An abstract class to select elements out of a list of elements.
26 public abstract class AbstractElementListSelectionDialog extends SelectionStatusDialog {
28 private ILabelProvider fRenderer;
29 private boolean fIgnoreCase= true;
30 private boolean fIsMultipleSelection= false;
31 private boolean fMatchEmptyString= true;
32 private boolean fAllowDuplicates= true;
34 private Label fMessage;
36 protected FilteredList fFilteredList;
37 private Text fFilterText;
39 private ISelectionValidator fValidator;
40 private String fFilter= null;
42 private String fEmptyListMessage= ""; //$NON-NLS-1$
43 private String fEmptySelectionMessage= ""; //$NON-NLS-1$
45 private int fWidth= 60;
46 private int fHeight= 18;
48 private Object[] fSelection= new Object[0];
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
56 protected AbstractElementListSelectionDialog(Shell parent, ILabelProvider renderer)
61 int shellStyle= getShellStyle();
62 setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE);
66 * Handles default selection (double click).
67 * By default, the OK button is pressed.
69 protected void handleDefaultSelected() {
70 if (validateCurrentSelection())
71 buttonPressed(IDialogConstants.OK_ID);
75 * Specifies if sorting, filtering and folding is case sensitive.
77 public void setIgnoreCase(boolean ignoreCase) {
78 fIgnoreCase= ignoreCase;
82 * Returns if sorting, filtering and folding is case sensitive.
84 public boolean isCaseIgnored() {
89 * Specifies whether everything or nothing should be filtered on
90 * empty filter string.
92 public void setMatchEmptyString(boolean matchEmptyString) {
93 fMatchEmptyString= matchEmptyString;
97 * Specifies if multiple selection is allowed.
99 public void setMultipleSelection(boolean multipleSelection) {
100 fIsMultipleSelection= multipleSelection;
104 * Specifies whether duplicate entries are displayed or not.
106 public void setAllowDuplicates(boolean allowDuplicates) {
107 fAllowDuplicates= allowDuplicates;
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.
115 public void setSize(int width, int height) {
121 * Sets the message to be displayed if the list is empty.
122 * @param message the message to be displayed.
124 public void setEmptyListMessage(String message) {
125 fEmptyListMessage= message;
129 * Sets the message to be displayed if the selection is empty.
130 * @param message the message to be displayed.
132 public void setEmptySelectionMessage(String message) {
133 fEmptySelectionMessage= message;
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.
141 public void setValidator(ISelectionValidator validator) {
142 fValidator= validator;
146 * Sets the elements of the list (widget).
147 * To be called within open().
148 * @param elements the elements of the list.
150 protected void setListElements(Object[] elements) {
151 Assert.isNotNull(fFilteredList);
152 fFilteredList.setElements(elements);
156 * Sets the filter pattern.
157 * @param filter the filter pattern.
159 public void setFilter(String filter) {
160 if (fFilterText == null)
163 fFilterText.setText(filter);
167 * Returns the current filter pattern.
168 * @return returns the current filter pattern or <code>null<code> if filter was not set.
170 public String getFilter() {
171 if (fFilteredList == null)
174 return fFilteredList.getFilter();
178 * Returns the indices referring the current selection.
179 * To be called within open().
180 * @return returns the indices of the current selection.
182 protected int[] getSelectionIndices() {
183 Assert.isNotNull(fFilteredList);
184 return fFilteredList.getSelectionIndices();
188 * Returns an index referring the first current selection.
189 * To be called within open().
190 * @return returns the indices of the current selection.
192 protected int getSelectionIndex() {
193 Assert.isNotNull(fFilteredList);
194 return fFilteredList.getSelectionIndex();
198 * Sets the selection referenced by an array of elements.
199 * To be called within open().
200 * @param selection the indices of the selection.
202 protected void setSelection(Object[] selection) {
203 Assert.isNotNull(fFilteredList);
204 fFilteredList.setSelection(selection);
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.
212 protected Object[] getSelectedElements() {
213 Assert.isNotNull(fFilteredList);
214 return fFilteredList.getSelection();
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.
222 public Object[] getFoldedElements(int index) {
223 Assert.isNotNull(fFilteredList);
224 return fFilteredList.getFoldedElements(index);
228 * Creates the message text widget and sets layout data.
229 * @param composite the parent composite of the message area.
231 protected Label createMessageArea(Composite composite) {
232 Label label= super.createMessageArea(composite);
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);
247 * Handles a selection changed event.
248 * By default, the current selection is validated.
250 protected void handleSelectionChanged() {
251 validateCurrentSelection();
255 * Validates the current selection and updates the status line
258 protected boolean validateCurrentSelection() {
259 Assert.isNotNull(fFilteredList);
262 Object[] elements= getSelectedElements();
264 if (elements.length > 0) {
265 if (fValidator != null) {
266 status= fValidator.validate(elements);
268 status= new StatusInfo();
271 if (fFilteredList.isEmpty()) {
272 status= new StatusInfo(IStatus.ERROR, fEmptyListMessage);
274 status= new StatusInfo(IStatus.ERROR, fEmptySelectionMessage);
278 updateStatus(status);
280 return status.isOK();
284 * @see Dialog#cancelPressed
286 protected void cancelPressed() {
288 super.cancelPressed();
292 * Creates a filtered list.
293 * @param parent the parent composite.
294 * @return returns the filtered list widget.
296 protected FilteredList createFilteredList(Composite parent) {
297 int flags= SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL |
298 (fIsMultipleSelection ? SWT.MULTI : SWT.SINGLE);
300 FilteredList list= new FilteredList(parent, flags, fRenderer,
301 fIgnoreCase, fAllowDuplicates, fMatchEmptyString);
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);
312 list.setFilter((fFilter == null ? "" : fFilter)); //$NON-NLS-1$
314 list.addSelectionListener(new SelectionListener() {
315 public void widgetDefaultSelected(SelectionEvent e) {
316 handleDefaultSelected();
318 public void widgetSelected(SelectionEvent e) {
319 handleWidgetSelected();
329 private void handleWidgetSelected() {
330 Object[] newSelection= fFilteredList.getSelection();
332 if (newSelection.length != fSelection.length) {
333 fSelection= newSelection;
334 handleSelectionChanged();
336 for (int i= 0; i != newSelection.length; i++) {
337 if (!newSelection[i].equals(fSelection[i])) {
338 fSelection= newSelection;
339 handleSelectionChanged();
346 protected Text createFilterText(Composite parent) {
347 Text text= new Text(parent, SWT.BORDER);
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);
356 text.setText((fFilter == null ? "" : fFilter)); //$NON-NLS-1$
358 Listener listener= new Listener() {
359 public void handleEvent(Event e) {
360 fFilteredList.setFilter(fFilterText.getText());
363 text.addListener(SWT.Modify, listener);
365 text.addKeyListener(new KeyListener() {
366 public void keyPressed(KeyEvent e) {
367 if (e.keyCode == SWT.ARROW_DOWN)
368 fFilteredList.setFocus();
371 public void keyReleased(KeyEvent e) {}
383 BusyIndicator.showWhile(null, new Runnable() {
388 return getReturnCode();
391 private void access$superOpen() {
396 * @see Window#create(Shell)
398 public void create() {
401 Assert.isNotNull(fFilteredList);
403 if (fFilteredList.isEmpty()) {
406 validateCurrentSelection();
407 fFilterText.selectAll();
408 fFilterText.setFocus();
413 * Handles empty list by disabling widgets.
415 protected void handleEmptyList() {
416 fMessage.setEnabled(false);
417 fFilterText.setEnabled(false);
418 fFilteredList.setEnabled(false);