1 package net.sourceforge.phpdt.internal.ui.dialogs;
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
27 SelectionStatusDialog {
29 private ILabelProvider fRenderer;
31 private boolean fIgnoreCase = true;
33 private boolean fIsMultipleSelection = false;
35 private boolean fMatchEmptyString = true;
37 private boolean fAllowDuplicates = true;
39 private Label fMessage;
41 protected FilteredList fFilteredList;
43 private Text fFilterText;
45 private ISelectionValidator fValidator;
47 private String fFilter = null;
49 private String fEmptyListMessage = ""; //$NON-NLS-1$
51 private String fEmptySelectionMessage = ""; //$NON-NLS-1$
53 private int fWidth = 60;
55 private int fHeight = 18;
57 private Object[] fSelection = new Object[0];
60 * Constructs a list selection dialog.
63 * The label renderer used
65 * Decides if the match string ignores lower/upppr case
66 * @param multipleSelection
67 * Allow multiple selection
69 protected AbstractElementListSelectionDialog(Shell parent,
70 ILabelProvider renderer) {
74 int shellStyle = getShellStyle();
75 setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE);
79 * Handles default selection (double click). By default, the OK button is
82 protected void handleDefaultSelected() {
83 if (validateCurrentSelection())
84 buttonPressed(IDialogConstants.OK_ID);
88 * Specifies if sorting, filtering and folding is case sensitive.
90 public void setIgnoreCase(boolean ignoreCase) {
91 fIgnoreCase = ignoreCase;
95 * Returns if sorting, filtering and folding is case sensitive.
97 public boolean isCaseIgnored() {
102 * Specifies whether everything or nothing should be filtered on empty
105 public void setMatchEmptyString(boolean matchEmptyString) {
106 fMatchEmptyString = matchEmptyString;
110 * Specifies if multiple selection is allowed.
112 public void setMultipleSelection(boolean multipleSelection) {
113 fIsMultipleSelection = multipleSelection;
117 * Specifies whether duplicate entries are displayed or not.
119 public void setAllowDuplicates(boolean allowDuplicates) {
120 fAllowDuplicates = allowDuplicates;
124 * Sets the list size in unit of characters.
127 * the width of the list.
129 * the height of the list.
131 public void setSize(int width, int height) {
137 * Sets the message to be displayed if the list is empty.
140 * the message to be displayed.
142 public void setEmptyListMessage(String message) {
143 fEmptyListMessage = message;
147 * Sets the message to be displayed if the selection is empty.
150 * the message to be displayed.
152 public void setEmptySelectionMessage(String message) {
153 fEmptySelectionMessage = message;
157 * Sets an optional validator to check if the selection is valid. The
158 * validator is invoked whenever the selection changes.
161 * the validator to validate the selection.
163 public void setValidator(ISelectionValidator validator) {
164 fValidator = validator;
168 * Sets the elements of the list (widget). To be called within open().
171 * the elements of the list.
173 protected void setListElements(Object[] elements) {
174 Assert.isNotNull(fFilteredList);
175 fFilteredList.setElements(elements);
179 * Sets the filter pattern.
182 * the filter pattern.
184 public void setFilter(String filter) {
185 if (fFilterText == null)
188 fFilterText.setText(filter);
192 * Returns the current filter pattern.
194 * @return returns the current filter pattern or
195 * <code>null<code> if filter was not set.
197 public String getFilter() {
198 if (fFilteredList == null)
201 return fFilteredList.getFilter();
205 * Returns the indices referring the current selection. To be called within
208 * @return returns the indices of the current selection.
210 protected int[] getSelectionIndices() {
211 Assert.isNotNull(fFilteredList);
212 return fFilteredList.getSelectionIndices();
216 * Returns an index referring the first current selection. To be called
219 * @return returns the indices of the current selection.
221 protected int getSelectionIndex() {
222 Assert.isNotNull(fFilteredList);
223 return fFilteredList.getSelectionIndex();
227 * Sets the selection referenced by an array of elements. To be called
231 * the indices of the selection.
233 protected void setSelection(Object[] selection) {
234 Assert.isNotNull(fFilteredList);
235 fFilteredList.setSelection(selection);
239 * Returns an array of the currently selected elements. To be called within
242 * @return returns an array of the currently selected elements.
244 protected Object[] getSelectedElements() {
245 Assert.isNotNull(fFilteredList);
246 return fFilteredList.getSelection();
250 * Returns all elements which are folded together to one entry in the list.
253 * the index selecting the entry in the list.
254 * @return returns an array of elements folded together.
256 public Object[] getFoldedElements(int index) {
257 Assert.isNotNull(fFilteredList);
258 return fFilteredList.getFoldedElements(index);
262 * Creates the message text widget and sets layout data.
265 * the parent composite of the message area.
267 protected Label createMessageArea(Composite composite) {
268 Label label = super.createMessageArea(composite);
270 GridData data = new GridData();
271 data.grabExcessVerticalSpace = false;
272 data.grabExcessHorizontalSpace = true;
273 data.horizontalAlignment = GridData.FILL;
274 data.verticalAlignment = GridData.BEGINNING;
275 label.setLayoutData(data);
283 * Handles a selection changed event. By default, the current selection is
286 protected void handleSelectionChanged() {
287 validateCurrentSelection();
291 * Validates the current selection and updates the status line accordingly.
293 protected boolean validateCurrentSelection() {
294 Assert.isNotNull(fFilteredList);
297 Object[] elements = getSelectedElements();
299 if (elements.length > 0) {
300 if (fValidator != null) {
301 status = fValidator.validate(elements);
303 status = new StatusInfo();
306 if (fFilteredList.isEmpty()) {
307 status = new StatusInfo(IStatus.ERROR, fEmptyListMessage);
309 status = new StatusInfo(IStatus.ERROR, fEmptySelectionMessage);
313 updateStatus(status);
315 return status.isOK();
319 * @see Dialog#cancelPressed
321 protected void cancelPressed() {
323 super.cancelPressed();
327 * Creates a filtered list.
330 * the parent composite.
331 * @return returns the filtered list widget.
333 protected FilteredList createFilteredList(Composite parent) {
334 int flags = SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL
335 | (fIsMultipleSelection ? SWT.MULTI : SWT.SINGLE);
337 FilteredList list = new FilteredList(parent, flags, fRenderer,
338 fIgnoreCase, fAllowDuplicates, fMatchEmptyString);
340 GridData data = new GridData();
341 data.widthHint = convertWidthInCharsToPixels(fWidth);
342 data.heightHint = convertHeightInCharsToPixels(fHeight);
343 data.grabExcessVerticalSpace = true;
344 data.grabExcessHorizontalSpace = true;
345 data.horizontalAlignment = GridData.FILL;
346 data.verticalAlignment = GridData.FILL;
347 list.setLayoutData(data);
349 list.setFilter((fFilter == null ? "" : fFilter)); //$NON-NLS-1$
351 list.addSelectionListener(new SelectionListener() {
352 public void widgetDefaultSelected(SelectionEvent e) {
353 handleDefaultSelected();
356 public void widgetSelected(SelectionEvent e) {
357 handleWidgetSelected();
361 fFilteredList = list;
367 private void handleWidgetSelected() {
368 Object[] newSelection = fFilteredList.getSelection();
370 if (newSelection.length != fSelection.length) {
371 fSelection = newSelection;
372 handleSelectionChanged();
374 for (int i = 0; i != newSelection.length; i++) {
375 if (!newSelection[i].equals(fSelection[i])) {
376 fSelection = newSelection;
377 handleSelectionChanged();
384 protected Text createFilterText(Composite parent) {
385 Text text = new Text(parent, SWT.BORDER);
387 GridData data = new GridData();
388 data.grabExcessVerticalSpace = false;
389 data.grabExcessHorizontalSpace = true;
390 data.horizontalAlignment = GridData.FILL;
391 data.verticalAlignment = GridData.BEGINNING;
392 text.setLayoutData(data);
394 text.setText((fFilter == null ? "" : fFilter)); //$NON-NLS-1$
396 Listener listener = new Listener() {
397 public void handleEvent(Event e) {
398 fFilteredList.setFilter(fFilterText.getText());
401 text.addListener(SWT.Modify, listener);
403 text.addKeyListener(new KeyListener() {
404 public void keyPressed(KeyEvent e) {
405 if (e.keyCode == SWT.ARROW_DOWN)
406 fFilteredList.setFocus();
409 public void keyReleased(KeyEvent e) {
422 BusyIndicator.showWhile(null, new Runnable() {
427 return getReturnCode();
430 private void access$superOpen() {
435 * @see Window#create(Shell)
437 public void create() {
440 Assert.isNotNull(fFilteredList);
442 if (fFilteredList.isEmpty()) {
445 validateCurrentSelection();
446 fFilterText.selectAll();
447 fFilterText.setFocus();
452 * Handles empty list by disabling widgets.
454 protected void handleEmptyList() {
455 fMessage.setEnabled(false);
456 fFilterText.setEnabled(false);
457 fFilteredList.setEnabled(false);