]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.ui/src/org/simantics/ui/workbench/dialogs/ElementListSelectionDialog.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.ui / src / org / simantics / ui / workbench / dialogs / ElementListSelectionDialog.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 /*\r
13  * 7.6.2006\r
14  */\r
15 package org.simantics.ui.workbench.dialogs;\r
16 \r
17 import java.util.ArrayList;\r
18 import java.util.Arrays;\r
19 import java.util.Collection;\r
20 import java.util.Comparator;\r
21 import java.util.HashMap;\r
22 import java.util.List;\r
23 import java.util.Map;\r
24 \r
25 import org.eclipse.jface.viewers.ILabelProvider;\r
26 import org.eclipse.swt.widgets.Composite;\r
27 import org.eclipse.swt.widgets.Control;\r
28 import org.eclipse.swt.widgets.Display;\r
29 import org.eclipse.swt.widgets.Label;\r
30 import org.eclipse.swt.widgets.Shell;\r
31 import org.eclipse.swt.widgets.Text;\r
32 import org.eclipse.ui.dialogs.AbstractElementListSelectionDialog;\r
33 import org.eclipse.ui.dialogs.FilteredList;\r
34 \r
35 /**\r
36  * ElementListSelectionDialog. This dialog component automatically sorts\r
37  * previously selected objects to the top of the list. \r
38  * <p>\r
39  * The component uses title as key for distinguishing different dialog types.\r
40  * \r
41  * @author Toni Kalajainen\r
42  * @author Tuukka Lehtonen\r
43  */\r
44 public class ElementListSelectionDialog extends AbstractElementListSelectionDialog {\r
45 \r
46     /** The number of previously selected objects to be remembered */\r
47     protected static final int REMEMBER_NUM             = 128;\r
48 \r
49     /** The number of previously selected objects to be prioritized in the list */\r
50     protected static final int PRIORITIZE_NUM           = 5;\r
51     \r
52     protected String           title                    = "";\r
53 \r
54     protected List<Object>     elementList              = new ArrayList<Object>();\r
55 \r
56     protected ILabelProvider   labelProvider;\r
57 \r
58     protected boolean          usePreviousSelectionSort = true;\r
59 \r
60     protected Label            messageLabel;\r
61 \r
62     protected Text             filterText;\r
63 \r
64 \r
65     /**\r
66      * Creates a list selection dialog.\r
67      * \r
68      * @param parent the parent widget.\r
69      * @param labelProvider the label provider.\r
70      */\r
71     public ElementListSelectionDialog(Shell parent, ILabelProvider labelProvider) {\r
72         super(parent, labelProvider);\r
73         this.labelProvider = labelProvider;\r
74         this.setIgnoreCase(true);\r
75     }\r
76 \r
77     /**\r
78      * Sets the elements of the list.\r
79      * @param elements the elements of the list.\r
80      */\r
81     public void setElements(Object... elements) {\r
82         elementList = null;\r
83         addElements(elements);\r
84     }\r
85 \r
86     public void addElements(Object... elements) {\r
87         if (elementList==null)\r
88             elementList = new ArrayList<Object>();\r
89         for (Object e : elements)\r
90             elementList.add(e);\r
91     }\r
92 \r
93     /**\r
94      * Sets the elements of the list.\r
95      * @param elements the elements of the list.\r
96      */\r
97     @SuppressWarnings("rawtypes")\r
98     public void setElements(Collection c) {\r
99         elementList = null;\r
100         addElements(c);\r
101     }\r
102 \r
103     @SuppressWarnings("rawtypes")\r
104     public void addElements(Collection c) {\r
105         if (elementList==null)\r
106             elementList = new ArrayList<Object>();\r
107         for (Object e : c)\r
108             elementList.add(e);\r
109     }\r
110 \r
111     public void updateList() {\r
112         // Make sure that the filtered list exists before trying to update it.\r
113         if (fFilteredList != null && elementList != null) {\r
114             Object[] objs = elementList.toArray(new Object[elementList.size()]);\r
115             final boolean isEmpty = objs.length == 0;\r
116             setListElements(objs);\r
117             Runnable r = new Runnable() {\r
118                 public void run() {\r
119                     handleListChange(isEmpty);\r
120                 }\r
121             };\r
122             Display d = getShell().getDisplay();\r
123             if (Thread.currentThread() == d.getThread())\r
124                 r.run();\r
125             else\r
126                 d.asyncExec(r);\r
127         }\r
128     }\r
129 \r
130     protected void handleListChange(boolean isEmpty) {\r
131         boolean wasEnabled = filterText.isEnabled();\r
132         boolean enable = !isEmpty;\r
133         messageLabel.setEnabled(enable);\r
134         filterText.setEnabled(enable);\r
135         fFilteredList.setEnabled(enable);\r
136         if (!wasEnabled)\r
137             filterText.setFocus();\r
138         updateOkState();\r
139     }\r
140 \r
141     /**\r
142      * Do alphabetical sort for list elements\r
143      */\r
144     public void sortElements() {\r
145         if (elementList==null) return;\r
146         \r
147         Object[] objects = elementList.toArray(new Object[0]);\r
148         Arrays.sort(objects, new Comparator<Object>() {\r
149             public int compare(Object o1, Object o2) {\r
150                 String n1 = labelProvider.getText(o1).toLowerCase();\r
151                 String n2 = labelProvider.getText(o2).toLowerCase();\r
152                 return n1.compareTo(n2);\r
153             }});\r
154         \r
155         elementList = new ArrayList<Object>(objects.length);\r
156         for (Object o : objects)\r
157             elementList.add(o);\r
158     }\r
159 \r
160     /*\r
161      * @see SelectionStatusDialog#computeResult()\r
162      */\r
163     protected void computeResult() {\r
164         setResult(Arrays.asList(getSelectedElements()));\r
165     }\r
166 \r
167     @Override\r
168     public void setTitle(String title) {\r
169         super.setTitle(title);\r
170         this.title = title;\r
171     }\r
172 \r
173     public void setInitialSelection(Object selectedElement) {\r
174         this.setInitialSelections(new Object[] {selectedElement});\r
175     }\r
176 \r
177     /**\r
178      * Overridden just to get a hold of the message area label.\r
179      * \r
180      * @see org.eclipse.ui.dialogs.AbstractElementListSelectionDialog#createMessageArea(org.eclipse.swt.widgets.Composite)\r
181      */\r
182     @Override\r
183     protected Label createMessageArea(Composite composite) {\r
184         messageLabel = super.createMessageArea(composite);\r
185         return messageLabel;\r
186     }\r
187 \r
188     /**\r
189      * Overridden just to get a hold of the filter text.\r
190      *\r
191      * @see org.eclipse.ui.dialogs.AbstractElementListSelectionDialog#createFilterText(org.eclipse.swt.widgets.Composite)\r
192      */\r
193     @Override\r
194     protected Text createFilterText(Composite parent) {\r
195         filterText = super.createFilterText(parent);\r
196         return filterText;\r
197     }\r
198 \r
199     @Override\r
200     protected FilteredList createFilteredList(Composite parent) {\r
201         FilteredList flist = super.createFilteredList(parent);\r
202 \r
203         if (usePreviousSelectionSort) \r
204         {\r
205             List<Object> prioritizeList = new ArrayList<Object>();\r
206             int[] previousSelections = getPreviousSelections( title );\r
207             for (int i=0; i<previousSelections.length; i++)\r
208                 for (int j=0; j<elementList.size(); j++)\r
209                     if (elementList.get(j).hashCode()==previousSelections[i])\r
210                     {\r
211                         String name = labelProvider.getText(elementList.get(j));\r
212                         if (name==null) continue;\r
213                         prioritizeList.add(name);\r
214                         if (prioritizeList.size()>PRIORITIZE_NUM)\r
215                             break;\r
216                     }\r
217         \r
218             flist.setComparator(new PrioritizeComparator(prioritizeList, isCaseIgnored()));\r
219         } else {\r
220         }\r
221         return flist;\r
222     }\r
223 \r
224     protected void createControls(Composite contents) {\r
225         createMessageArea(contents);\r
226         createFilterText(contents);\r
227         createFilteredList(contents);\r
228     }\r
229     \r
230     /*\r
231      * @see Dialog#createDialogArea(Composite)\r
232      */\r
233     protected Control createDialogArea(Composite parent) {\r
234         Composite contents = (Composite) super.createDialogArea(parent);\r
235 \r
236         createControls(contents);\r
237 \r
238         setListElements(elementList.toArray(new Object[elementList.size()]));\r
239 \r
240         // Select items\r
241         setSelection(getInitialElementSelections().toArray());\r
242 \r
243         // If nothing is selected, select the first element\r
244         //if (getSelectionIndices()==null || getSelectionIndices().length==0)\r
245         //    this.fFilteredList.setSelection(new int[] {0});        \r
246 \r
247         return contents;\r
248     }\r
249     \r
250     @Override\r
251     protected void okPressed() {\r
252         super.okPressed();\r
253         for (Object o : getResult())\r
254             addSelection(title, o);\r
255     }\r
256     \r
257     protected static Map<String, List<Integer>> previousSelections =\r
258          new HashMap<String, List<Integer>>();\r
259     \r
260     protected static synchronized int[] getPreviousSelections(String key)\r
261     {\r
262         List<Integer> list = previousSelections.get(key);\r
263         if (list==null) return new int[0];\r
264         int result[] = new int[list.size()];\r
265         for (int i=0; i<list.size(); i++)\r
266             result[i] = list.get(i);\r
267         return result;\r
268     }\r
269     \r
270     protected static synchronized void addSelection(String key, Object o)\r
271     {\r
272         List<Integer> list = previousSelections.get(key);\r
273         if (list==null) {\r
274             list = new ArrayList<Integer>();\r
275             previousSelections.put(key, list);\r
276         }\r
277         int hash = o.hashCode();\r
278         // remove previous\r
279         for (int i=0; i<list.size(); i++)\r
280             if (list.get(i)==hash)\r
281             {\r
282                 list.remove(i);\r
283             }\r
284         // Add as first\r
285         list.add(0, o.hashCode());\r
286         \r
287         // remove last\r
288         if (list.size()>REMEMBER_NUM)\r
289             list.remove(list.size()-1);\r
290     }    \r
291     \r
292     public int[] getSelectionIndices() {\r
293         return super.getSelectionIndices();\r
294     }\r
295 \r
296     public boolean isUsePreviousSelectionSort() {\r
297         return usePreviousSelectionSort;\r
298     }\r
299 \r
300     /**\r
301      * Set usage for sorting of previous selections.\r
302      * When this sorting is enabled, the items that have been selected\r
303      * the items that have been selected previously in this same dialog\r
304      * are prioritized to appear first in the list\r
305      * \r
306      * (Dialogs are distinguished by their title :X)\r
307      * \r
308      * @param usePreviousSelectionSort\r
309      */\r
310     public void setUsePreviousSelectionSort(boolean usePreviousSelectionSort) {\r
311         this.usePreviousSelectionSort = usePreviousSelectionSort;\r
312     }\r
313     \r
314 }\r
315 \r
316 class PrioritizeComparator implements Comparator<Object>\r
317 {    \r
318     private final List<Object> prioritizeList;\r
319     private final boolean ignoreCase;\r
320     public PrioritizeComparator(List<Object> prioritizeList, boolean ignoreCase)\r
321     {\r
322         this.prioritizeList = prioritizeList;\r
323         this.ignoreCase = ignoreCase;\r
324     }\r
325     \r
326     public int getIndex(Object o)\r
327     {\r
328         for (int i=0; i<prioritizeList.size(); i++)\r
329             if (o==prioritizeList.get(i))\r
330                 return i;\r
331         return Integer.MAX_VALUE/4;\r
332     }\r
333     \r
334     public int compare(Object o1, Object o2) {\r
335         int p1 = getIndex(o1);\r
336         int p2 = getIndex(o2);\r
337         if (p1==p2)            \r
338             return (ignoreCase?o1.toString().compareToIgnoreCase(o2.toString()):o1.toString().compareTo(o2.toString()));     \r
339         \r
340         return p1-p2;\r
341     }\r
342     \r
343 }\r