1 package net.sourceforge.phpdt.internal.ui.dialog;
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;
23 * An abstract class to select elements out of a list of elements.
25 public abstract class AbstractElementListSelectionDialog extends SelectionStatusDialog {
27 private ILabelProvider fRenderer;
28 private boolean fIgnoreCase= true;
29 private boolean fIsMultipleSelection= false;
30 private boolean fMatchEmptyString= true;
31 private boolean fAllowDuplicates= true;
33 private Label fMessage;
35 protected FilteredList fFilteredList;
36 private Text fFilterText;
38 private ISelectionValidator fValidator;
39 private String fFilter= null;
41 private String fEmptyListMessage= ""; //$NON-NLS-1$
42 private String fEmptySelectionMessage= ""; //$NON-NLS-1$
44 private int fWidth= 60;
45 private int fHeight= 18;
47 private Object[] fSelection= new Object[0];
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
55 protected AbstractElementListSelectionDialog(Shell parent, ILabelProvider renderer)
60 int shellStyle= getShellStyle();
61 setShellStyle(shellStyle | SWT.MAX | SWT.RESIZE);
65 * Handles default selection (double click).
66 * By default, the OK button is pressed.
68 protected void handleDefaultSelected() {
69 if (validateCurrentSelection())
70 buttonPressed(IDialogConstants.OK_ID);
74 * Specifies if sorting, filtering and folding is case sensitive.
76 public void setIgnoreCase(boolean ignoreCase) {
77 fIgnoreCase= ignoreCase;
81 * Returns if sorting, filtering and folding is case sensitive.
83 public boolean isCaseIgnored() {
88 * Specifies whether everything or nothing should be filtered on
89 * empty filter string.
91 public void setMatchEmptyString(boolean matchEmptyString) {
92 fMatchEmptyString= matchEmptyString;
96 * Specifies if multiple selection is allowed.
98 public void setMultipleSelection(boolean multipleSelection) {
99 fIsMultipleSelection= multipleSelection;
103 * Specifies whether duplicate entries are displayed or not.
105 public void setAllowDuplicates(boolean allowDuplicates) {
106 fAllowDuplicates= allowDuplicates;
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.
114 public void setSize(int width, int height) {
120 * Sets the message to be displayed if the list is empty.
121 * @param message the message to be displayed.
123 public void setEmptyListMessage(String message) {
124 fEmptyListMessage= message;
128 * Sets the message to be displayed if the selection is empty.
129 * @param message the message to be displayed.
131 public void setEmptySelectionMessage(String message) {
132 fEmptySelectionMessage= message;
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.
140 public void setValidator(ISelectionValidator validator) {
141 fValidator= validator;
145 * Sets the elements of the list (widget).
146 * To be called within open().
147 * @param elements the elements of the list.
149 protected void setListElements(Object[] elements) {
150 Assert.isNotNull(fFilteredList);
151 fFilteredList.setElements(elements);
155 * Sets the filter pattern.
156 * @param filter the filter pattern.
158 public void setFilter(String filter) {
159 if (fFilterText == null)
162 fFilterText.setText(filter);
166 * Returns the current filter pattern.
167 * @return returns the current filter pattern or <code>null<code> if filter was not set.
169 public String getFilter() {
170 if (fFilteredList == null)
173 return fFilteredList.getFilter();
177 * Returns the indices referring the current selection.
178 * To be called within open().
179 * @return returns the indices of the current selection.
181 protected int[] getSelectionIndices() {
182 Assert.isNotNull(fFilteredList);
183 return fFilteredList.getSelectionIndices();
187 * Returns an index referring the first current selection.
188 * To be called within open().
189 * @return returns the indices of the current selection.
191 protected int getSelectionIndex() {
192 Assert.isNotNull(fFilteredList);
193 return fFilteredList.getSelectionIndex();
197 * Sets the selection referenced by an array of elements.
198 * To be called within open().
199 * @param selection the indices of the selection.
201 protected void setSelection(Object[] selection) {
202 Assert.isNotNull(fFilteredList);
203 fFilteredList.setSelection(selection);
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.
211 protected Object[] getSelectedElements() {
212 Assert.isNotNull(fFilteredList);
213 return fFilteredList.getSelection();
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.
221 public Object[] getFoldedElements(int index) {
222 Assert.isNotNull(fFilteredList);
223 return fFilteredList.getFoldedElements(index);
227 * Creates the message text widget and sets layout data.
228 * @param composite the parent composite of the message area.
230 protected Label createMessageArea(Composite composite) {
231 Label label= super.createMessageArea(composite);
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);
246 * Handles a selection changed event.
247 * By default, the current selection is validated.
249 protected void handleSelectionChanged() {
250 validateCurrentSelection();
254 * Validates the current selection and updates the status line
257 protected boolean validateCurrentSelection() {
258 Assert.isNotNull(fFilteredList);
261 Object[] elements= getSelectedElements();
263 if (elements.length > 0) {
264 if (fValidator != null) {
265 status= fValidator.validate(elements);
267 status= new StatusInfo();
270 if (fFilteredList.isEmpty()) {
271 status= new StatusInfo(IStatus.ERROR, fEmptyListMessage);
273 status= new StatusInfo(IStatus.ERROR, fEmptySelectionMessage);
277 updateStatus(status);
279 return status.isOK();
283 * @see Dialog#cancelPressed
285 protected void cancelPressed() {
287 super.cancelPressed();
291 * Creates a filtered list.
292 * @param parent the parent composite.
293 * @return returns the filtered list widget.
295 protected FilteredList createFilteredList(Composite parent) {
296 int flags= SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL |
297 (fIsMultipleSelection ? SWT.MULTI : SWT.SINGLE);
299 FilteredList list= new FilteredList(parent, flags, fRenderer,
300 fIgnoreCase, fAllowDuplicates, fMatchEmptyString);
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);
311 list.setFilter((fFilter == null ? "" : fFilter)); //$NON-NLS-1$
313 list.addSelectionListener(new SelectionListener() {
314 public void widgetDefaultSelected(SelectionEvent e) {
315 handleDefaultSelected();
317 public void widgetSelected(SelectionEvent e) {
318 handleWidgetSelected();
328 private void handleWidgetSelected() {
329 Object[] newSelection= fFilteredList.getSelection();
331 if (newSelection.length != fSelection.length) {
332 fSelection= newSelection;
333 handleSelectionChanged();
335 for (int i= 0; i != newSelection.length; i++) {
336 if (!newSelection[i].equals(fSelection[i])) {
337 fSelection= newSelection;
338 handleSelectionChanged();
345 protected Text createFilterText(Composite parent) {
346 Text text= new Text(parent, SWT.BORDER);
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);
355 text.setText((fFilter == null ? "" : fFilter)); //$NON-NLS-1$
357 Listener listener= new Listener() {
358 public void handleEvent(Event e) {
359 fFilteredList.setFilter(fFilterText.getText());
362 text.addListener(SWT.Modify, listener);
364 text.addKeyListener(new KeyListener() {
365 public void keyPressed(KeyEvent e) {
366 if (e.keyCode == SWT.ARROW_DOWN)
367 fFilteredList.setFocus();
370 public void keyReleased(KeyEvent e) {}
382 BusyIndicator.showWhile(null, new Runnable() {
387 return getReturnCode();
390 private void access$superOpen() {
395 * @see Window#create(Shell)
397 public void create() {
400 Assert.isNotNull(fFilteredList);
402 if (fFilteredList.isEmpty()) {
405 validateCurrentSelection();
406 fFilterText.selectAll();
407 fFilterText.setFocus();
412 * Handles empty list by disabling widgets.
414 protected void handleEmptyList() {
415 fMessage.setEnabled(false);
416 fFilterText.setEnabled(false);
417 fFilteredList.setEnabled(false);