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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.browsing.ui.swt.widgets;
\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
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
30 public class Combo extends WidgetImpl {
\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
38 final private Display display;
\r
39 final private org.eclipse.swt.widgets.Combo combo;
\r
41 public Combo(Composite parent, WidgetSupport support, int style) {
\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
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
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
61 public void setSelectionFactory(ReadFactory<?, String> selectionFactory) {
\r
62 this.selectionFactory = selectionFactory;
\r
65 public org.eclipse.swt.widgets.Combo getWidget() {
\r
70 public Control getControl() {
\r
74 private AtomicBoolean inputDisposed;
\r
77 public void setInput(ISessionContext context, Object input) {
\r
79 if (this.inputDisposed != null)
\r
80 this.inputDisposed.set(true);
\r
81 final AtomicBoolean inputDisposed = this.inputDisposed = new AtomicBoolean(false);
\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
91 if(itemFactory != null) {
\r
92 itemFactory.listen(context, input, new Listener<Map<String, Object>>() {
\r
95 public void exception(Throwable t) {
\r
96 t.printStackTrace();
\r
100 public void execute(final Map<String, Object> items) {
\r
101 if(isDisposed()) return;
\r
102 display.asyncExec(new Runnable() {
\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
113 } catch (Throwable t) {
\r
114 t.printStackTrace();
\r
117 for(String key : items.keySet()) {
\r
118 // System.out.println("-" + key);
\r
120 combo.setData(key, index++);
\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
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
137 public boolean isDisposed() {
\r
138 return combo.isDisposed() || inputDisposed.get();
\r
144 if(itemFactory2 != null) {
\r
145 itemFactory2.listen(context, input, new Listener<List<Pair<String, Object>>>() {
\r
148 public void exception(Throwable t) {
\r
149 t.printStackTrace();
\r
153 public void execute(final List<Pair<String, Object>> items) {
\r
154 if(isDisposed()) return;
\r
155 display.asyncExec(new Runnable() {
\r
158 public void run() {
\r
159 if(isDisposed()) return;
\r
160 // System.out.println("Combo received new items: " + items.size());
\r
162 for(ModifyListener listener : modifyListeners) combo.removeModifyListener(listener);
\r
163 combo.setData(items);
\r
164 combo.clearSelection();
\r
167 } catch (Throwable t) {
\r
168 t.printStackTrace();
\r
170 if (items != null) {
\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
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
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
193 public boolean isDisposed() {
\r
194 return combo.isDisposed() || inputDisposed.get();
\r
200 if(selectionFactory != null) {
\r
201 selectionFactory.listen(context, input, new Listener<String>() {
\r
204 public void exception(Throwable t) {
\r
205 t.printStackTrace();
\r
209 public void execute(final String selectionKey) {
\r
210 if(isDisposed()) return;
\r
211 display.asyncExec(new Runnable() {
\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
229 public boolean isDisposed() {
\r
230 return combo.isDisposed() || inputDisposed.get();
\r
238 public synchronized void addModifyListener(ModifyListener listener) {
\r
239 modifyListeners.add(listener);
\r
240 combo.addModifyListener(listener);
\r
246 * @throws IndexOutOfBoundsException if index is outside widget bounds
\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
254 return (Pair<String, T>) itemList.get(index);
\r
258 * @return selected combo list item or <code>null</code> if no item is
\r
261 public <T> Pair<String, T> getSelectedData() {
\r
262 return getData(combo.getSelectionIndex());
\r