]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/widgets/Combo.java
9e7f90207bd889b60c6a6d9d3b2a7d660f9b9940
[simantics/platform.git] / bundles / org.simantics.browsing.ui.swt / src / org / simantics / browsing / ui / swt / widgets / Combo.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2012 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 package org.simantics.browsing.ui.swt.widgets;\r
13 \r
14 import java.util.List;\r
15 import java.util.Map;\r
16 import java.util.concurrent.CopyOnWriteArrayList;\r
17 import java.util.concurrent.atomic.AtomicBoolean;\r
18 \r
19 import org.eclipse.swt.events.ModifyListener;\r
20 import org.eclipse.swt.widgets.Composite;\r
21 import org.eclipse.swt.widgets.Control;\r
22 import org.eclipse.swt.widgets.Display;\r
23 import org.simantics.browsing.ui.swt.widgets.impl.ReadFactory;\r
24 import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
25 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
26 import org.simantics.db.management.ISessionContext;\r
27 import org.simantics.db.procedure.Listener;\r
28 import org.simantics.utils.datastructures.Pair;\r
29 \r
30 public class Combo extends WidgetImpl {\r
31 \r
32     private ReadFactory<?, Map<String, Object>> itemFactory;\r
33     private ReadFactory<?, List<Pair<String, Object>>> itemFactory2;\r
34     private ReadFactory<?, String> selectionFactory;\r
35     private final CopyOnWriteArrayList<ModifyListener> modifyListeners = new CopyOnWriteArrayList<ModifyListener>();\r
36     private List<Pair<String, Object>> itemList;\r
37 \r
38     final private Display display;\r
39     final private org.eclipse.swt.widgets.Combo combo;\r
40 \r
41     public Combo(Composite parent, WidgetSupport support, int style) {\r
42         super(support);\r
43         this.display = parent.getDisplay();\r
44         combo = new org.eclipse.swt.widgets.Combo(parent, style);\r
45         combo.setData("org.simantics.browsing.ui.widgets.Combo", this);\r
46         support.register(this);\r
47     }\r
48 \r
49     public void setItemFactory(ReadFactory<?, Map<String, Object>> itemFactory) {\r
50         if (this.itemFactory2 != null)\r
51             throw new IllegalStateException("Cannot use both itemFactory and itemFactory2");\r
52         this.itemFactory = itemFactory;\r
53     }\r
54 \r
55     public void setItemFactory2(ReadFactory<?, List<Pair<String, Object>>> itemFactory) {\r
56         if (this.itemFactory != null)\r
57             throw new IllegalStateException("Cannot use both itemFactory and itemFactory2");\r
58         this.itemFactory2 = itemFactory;\r
59     }\r
60 \r
61     public void setSelectionFactory(ReadFactory<?, String> selectionFactory) {\r
62         this.selectionFactory = selectionFactory;\r
63     }\r
64 \r
65     public org.eclipse.swt.widgets.Combo getWidget() {\r
66         return combo;\r
67     }\r
68 \r
69     @Override\r
70     public Control getControl() {\r
71         return combo;\r
72     }\r
73 \r
74     private AtomicBoolean inputDisposed;\r
75 \r
76     @Override\r
77     public void setInput(ISessionContext context, Object input) {\r
78 \r
79         if (this.inputDisposed != null)\r
80             this.inputDisposed.set(true);\r
81         final AtomicBoolean inputDisposed = this.inputDisposed = new AtomicBoolean(false);\r
82 \r
83         if (modifyListeners != null) {\r
84             for (ModifyListener listener : modifyListeners) {\r
85                 if(listener instanceof Widget) {\r
86                     ((Widget) listener).setInput(context, input);\r
87                 }\r
88             }\r
89         }\r
90 \r
91         if(itemFactory != null) {\r
92             itemFactory.listen(context, input, new Listener<Map<String, Object>>() {\r
93 \r
94                 @Override\r
95                 public void exception(Throwable t) {\r
96                     t.printStackTrace();\r
97                 }\r
98 \r
99                 @Override\r
100                 public void execute(final Map<String, Object> items) {\r
101                     if(isDisposed()) return;\r
102                     display.asyncExec(new Runnable() {\r
103 \r
104                         @Override\r
105                         public void run() {\r
106                             if(isDisposed()) return;\r
107 //                            System.out.println("Combo received new items: " + items.size());\r
108                             for(ModifyListener listener : modifyListeners) combo.removeModifyListener(listener);\r
109                             combo.setData(items);\r
110                             combo.clearSelection();\r
111                             try {\r
112                                 combo.removeAll();\r
113                             } catch (Throwable t) {\r
114                                 t.printStackTrace();\r
115                             }\r
116                             int index = 0;\r
117                             for(String key : items.keySet()) {\r
118 //                                System.out.println("-" + key);\r
119                                 combo.add(key);\r
120                                 combo.setData(key, index++);\r
121                             }\r
122                             String selectionKey = (String)combo.getData("_SelectionKey");\r
123                             if(selectionKey != null) {\r
124                                 Integer selectionIndex = (Integer)combo.getData(selectionKey);\r
125                                 if(selectionIndex != null) combo.select(selectionIndex);\r
126                             }\r
127                             for(ModifyListener listener : modifyListeners) combo.addModifyListener(listener);\r
128                             //label.setSize(200, 20);\r
129 //                            label.getParent().layout();\r
130 //                            label.getParent().getParent().layout();\r
131                         }\r
132 \r
133                     });\r
134                 }\r
135 \r
136                 @Override\r
137                 public boolean isDisposed() {\r
138                     return combo.isDisposed() || inputDisposed.get();\r
139                 }\r
140 \r
141             });\r
142         }\r
143 \r
144         if(itemFactory2 != null) {\r
145             itemFactory2.listen(context, input, new Listener<List<Pair<String, Object>>>() {\r
146 \r
147                 @Override\r
148                 public void exception(Throwable t) {\r
149                     t.printStackTrace();\r
150                 }\r
151 \r
152                 @Override\r
153                 public void execute(final List<Pair<String, Object>> items) {\r
154                     if(isDisposed()) return;\r
155                     display.asyncExec(new Runnable() {\r
156 \r
157                         @Override\r
158                         public void run() {\r
159                             if(isDisposed()) return;\r
160 //                            System.out.println("Combo received new items: " + items.size());\r
161                             itemList = items;\r
162                             for(ModifyListener listener : modifyListeners) combo.removeModifyListener(listener);\r
163                             combo.setData(items);\r
164                             combo.clearSelection();\r
165                             try {\r
166                                 combo.removeAll();\r
167                             } catch (Throwable t) {\r
168                                 t.printStackTrace();\r
169                             }\r
170                             if (items != null) {\r
171                                 int index = 0;\r
172                                 for(Pair<String, Object> key : items) {\r
173 //                                    System.out.println("-" + key);\r
174                                     combo.add(key.first);\r
175                                     combo.setData(key.first, index++);\r
176                                 }\r
177                                 String selectionKey = (String)combo.getData("_SelectionKey");\r
178                                 if(selectionKey != null) {\r
179                                     Integer selectionIndex = (Integer)combo.getData(selectionKey);\r
180                                     if(selectionIndex != null) combo.select(selectionIndex);\r
181                                 }\r
182                             }\r
183                             for(ModifyListener listener : modifyListeners) combo.addModifyListener(listener);\r
184                             //label.setSize(200, 20);\r
185 //                                                      label.getParent().layout();\r
186 //                                                      label.getParent().getParent().layout();\r
187                         }\r
188 \r
189                     });\r
190                 }\r
191 \r
192                 @Override\r
193                 public boolean isDisposed() {\r
194                     return combo.isDisposed() || inputDisposed.get();\r
195                 }\r
196 \r
197             });\r
198         }\r
199 \r
200         if(selectionFactory != null) {\r
201             selectionFactory.listen(context, input, new Listener<String>() {\r
202 \r
203                 @Override\r
204                 public void exception(Throwable t) {\r
205                     t.printStackTrace();\r
206                 }\r
207 \r
208                 @Override\r
209                 public void execute(final String selectionKey) {\r
210                     if(isDisposed()) return;\r
211                     display.asyncExec(new Runnable() {\r
212 \r
213                         @Override\r
214                         public void run() {\r
215                             if(isDisposed()) return;\r
216                             if(selectionKey == null) return;\r
217 //                            System.out.println("Combo received new selection key: " + selectionKey);\r
218                             for(ModifyListener listener : modifyListeners) combo.removeModifyListener(listener);\r
219                             combo.setData("_SelectionKey", selectionKey);\r
220                             Integer selectionIndex = (Integer)combo.getData(selectionKey);\r
221                             if(selectionIndex != null) combo.select(selectionIndex);\r
222                             for(ModifyListener listener : modifyListeners) combo.addModifyListener(listener);\r
223                         }\r
224 \r
225                     });\r
226                 }\r
227 \r
228                 @Override\r
229                 public boolean isDisposed() {\r
230                     return combo.isDisposed() || inputDisposed.get();\r
231                 }\r
232 \r
233             });\r
234         }\r
235 \r
236     }\r
237 \r
238     public synchronized void addModifyListener(ModifyListener listener) {\r
239         modifyListeners.add(listener);\r
240         combo.addModifyListener(listener);\r
241     }\r
242 \r
243     /**\r
244      * @param index\r
245      * @return\r
246      * @throws IndexOutOfBoundsException if index is outside widget bounds\r
247      */\r
248     @SuppressWarnings("unchecked")\r
249     public <T> Pair<String, T> getData(int index) {\r
250         if (itemFactory != null)\r
251             new IllegalStateException("this method is only useful when used with Combo.setItemFactory2").printStackTrace();\r
252         if (index == -1)\r
253             return null;\r
254         return (Pair<String, T>) itemList.get(index);\r
255     }\r
256 \r
257     /**\r
258      * @return selected combo list item or <code>null</code> if no item is\r
259      *         selected\r
260      */\r
261     public <T> Pair<String, T> getSelectedData() {\r
262         return getData(combo.getSelectionIndex());\r
263     }\r
264 \r
265 }\r