1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
15 package org.simantics.ui.workbench.dialogs;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Collection;
20 import java.util.Comparator;
21 import java.util.HashMap;
22 import java.util.List;
25 import org.eclipse.jface.viewers.ILabelProvider;
26 import org.eclipse.swt.widgets.Composite;
27 import org.eclipse.swt.widgets.Control;
28 import org.eclipse.swt.widgets.Display;
29 import org.eclipse.swt.widgets.Label;
30 import org.eclipse.swt.widgets.Shell;
31 import org.eclipse.swt.widgets.Text;
32 import org.eclipse.ui.dialogs.AbstractElementListSelectionDialog;
33 import org.eclipse.ui.dialogs.FilteredList;
36 * ElementListSelectionDialog. This dialog component automatically sorts
37 * previously selected objects to the top of the list.
39 * The component uses title as key for distinguishing different dialog types.
41 * @author Toni Kalajainen
42 * @author Tuukka Lehtonen
44 public class ElementListSelectionDialog extends AbstractElementListSelectionDialog {
46 /** The number of previously selected objects to be remembered */
47 protected static final int REMEMBER_NUM = 128;
49 /** The number of previously selected objects to be prioritized in the list */
50 protected static final int PRIORITIZE_NUM = 5;
52 protected String title = "";
54 protected List<Object> elementList = new ArrayList<Object>();
56 protected ILabelProvider labelProvider;
58 protected boolean usePreviousSelectionSort = true;
60 protected Label messageLabel;
62 protected Text filterText;
66 * Creates a list selection dialog.
68 * @param parent the parent widget.
69 * @param labelProvider the label provider.
71 public ElementListSelectionDialog(Shell parent, ILabelProvider labelProvider) {
72 super(parent, labelProvider);
73 this.labelProvider = labelProvider;
74 this.setIgnoreCase(true);
78 * Sets the elements of the list.
79 * @param elements the elements of the list.
81 public void setElements(Object... elements) {
83 addElements(elements);
86 public void addElements(Object... elements) {
87 if (elementList==null)
88 elementList = new ArrayList<Object>();
89 for (Object e : elements)
94 * Sets the elements of the list.
95 * @param elements the elements of the list.
97 @SuppressWarnings("rawtypes")
98 public void setElements(Collection c) {
103 @SuppressWarnings("rawtypes")
104 public void addElements(Collection c) {
105 if (elementList==null)
106 elementList = new ArrayList<Object>();
111 public void updateList() {
112 // Make sure that the filtered list exists before trying to update it.
113 if (fFilteredList != null && elementList != null) {
114 Object[] objs = elementList.toArray(new Object[elementList.size()]);
115 final boolean isEmpty = objs.length == 0;
116 setListElements(objs);
117 Runnable r = new Runnable() {
119 handleListChange(isEmpty);
122 Display d = getShell().getDisplay();
123 if (Thread.currentThread() == d.getThread())
130 protected void handleListChange(boolean isEmpty) {
131 boolean wasEnabled = filterText.isEnabled();
132 boolean enable = !isEmpty;
133 messageLabel.setEnabled(enable);
134 filterText.setEnabled(enable);
135 fFilteredList.setEnabled(enable);
137 filterText.setFocus();
142 * Do alphabetical sort for list elements
144 public void sortElements() {
145 if (elementList==null) return;
147 Object[] objects = elementList.toArray(new Object[0]);
148 Arrays.sort(objects, new Comparator<Object>() {
149 public int compare(Object o1, Object o2) {
150 String n1 = labelProvider.getText(o1).toLowerCase();
151 String n2 = labelProvider.getText(o2).toLowerCase();
152 return n1.compareTo(n2);
155 elementList = new ArrayList<Object>(objects.length);
156 for (Object o : objects)
161 * @see SelectionStatusDialog#computeResult()
163 protected void computeResult() {
164 setResult(Arrays.asList(getSelectedElements()));
168 public void setTitle(String title) {
169 super.setTitle(title);
173 public void setInitialSelection(Object selectedElement) {
174 this.setInitialSelections(new Object[] {selectedElement});
178 * Overridden just to get a hold of the message area label.
180 * @see org.eclipse.ui.dialogs.AbstractElementListSelectionDialog#createMessageArea(org.eclipse.swt.widgets.Composite)
183 protected Label createMessageArea(Composite composite) {
184 messageLabel = super.createMessageArea(composite);
189 * Overridden just to get a hold of the filter text.
191 * @see org.eclipse.ui.dialogs.AbstractElementListSelectionDialog#createFilterText(org.eclipse.swt.widgets.Composite)
194 protected Text createFilterText(Composite parent) {
195 filterText = super.createFilterText(parent);
200 protected FilteredList createFilteredList(Composite parent) {
201 FilteredList flist = super.createFilteredList(parent);
203 if (usePreviousSelectionSort)
205 List<Object> prioritizeList = new ArrayList<Object>();
206 int[] previousSelections = getPreviousSelections( title );
207 for (int i=0; i<previousSelections.length; i++)
208 for (int j=0; j<elementList.size(); j++)
209 if (elementList.get(j).hashCode()==previousSelections[i])
211 String name = labelProvider.getText(elementList.get(j));
212 if (name==null) continue;
213 prioritizeList.add(name);
214 if (prioritizeList.size()>PRIORITIZE_NUM)
218 flist.setComparator(new PrioritizeComparator(prioritizeList, isCaseIgnored()));
224 protected void createControls(Composite contents) {
225 createMessageArea(contents);
226 createFilterText(contents);
227 createFilteredList(contents);
231 * @see Dialog#createDialogArea(Composite)
233 protected Control createDialogArea(Composite parent) {
234 Composite contents = (Composite) super.createDialogArea(parent);
236 createControls(contents);
238 setListElements(elementList.toArray(new Object[elementList.size()]));
241 setSelection(getInitialElementSelections().toArray());
243 // If nothing is selected, select the first element
244 //if (getSelectionIndices()==null || getSelectionIndices().length==0)
245 // this.fFilteredList.setSelection(new int[] {0});
251 protected void okPressed() {
253 for (Object o : getResult())
254 addSelection(title, o);
257 protected static Map<String, List<Integer>> previousSelections =
258 new HashMap<String, List<Integer>>();
260 protected static synchronized int[] getPreviousSelections(String key)
262 List<Integer> list = previousSelections.get(key);
263 if (list==null) return new int[0];
264 int result[] = new int[list.size()];
265 for (int i=0; i<list.size(); i++)
266 result[i] = list.get(i);
270 protected static synchronized void addSelection(String key, Object o)
272 List<Integer> list = previousSelections.get(key);
274 list = new ArrayList<Integer>();
275 previousSelections.put(key, list);
277 int hash = o.hashCode();
279 for (int i=0; i<list.size(); i++)
280 if (list.get(i)==hash)
285 list.add(0, o.hashCode());
288 if (list.size()>REMEMBER_NUM)
289 list.remove(list.size()-1);
292 public int[] getSelectionIndices() {
293 return super.getSelectionIndices();
296 public boolean isUsePreviousSelectionSort() {
297 return usePreviousSelectionSort;
301 * Set usage for sorting of previous selections.
302 * When this sorting is enabled, the items that have been selected
303 * the items that have been selected previously in this same dialog
304 * are prioritized to appear first in the list
306 * (Dialogs are distinguished by their title :X)
308 * @param usePreviousSelectionSort
310 public void setUsePreviousSelectionSort(boolean usePreviousSelectionSort) {
311 this.usePreviousSelectionSort = usePreviousSelectionSort;
316 class PrioritizeComparator implements Comparator<Object>
318 private final List<Object> prioritizeList;
319 private final boolean ignoreCase;
320 public PrioritizeComparator(List<Object> prioritizeList, boolean ignoreCase)
322 this.prioritizeList = prioritizeList;
323 this.ignoreCase = ignoreCase;
326 public int getIndex(Object o)
328 for (int i=0; i<prioritizeList.size(); i++)
329 if (o==prioritizeList.get(i))
331 return Integer.MAX_VALUE/4;
334 public int compare(Object o1, Object o2) {
335 int p1 = getIndex(o1);
336 int p2 = getIndex(o2);
338 return (ignoreCase?o1.toString().compareToIgnoreCase(o2.toString()):o1.toString().compareTo(o2.toString()));