1 /*******************************************************************************
2 * Copyright (c) 2007, 2012 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 *******************************************************************************/
12 package org.simantics.browsing.ui.swt.widgets;
14 import java.util.List;
16 import java.util.concurrent.CopyOnWriteArrayList;
17 import java.util.concurrent.atomic.AtomicBoolean;
19 import org.eclipse.swt.events.ModifyListener;
20 import org.eclipse.swt.widgets.Composite;
21 import org.eclipse.swt.widgets.Control;
22 import org.eclipse.swt.widgets.Display;
23 import org.simantics.browsing.ui.swt.widgets.impl.ReadFactory;
24 import org.simantics.browsing.ui.swt.widgets.impl.Widget;
25 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;
26 import org.simantics.db.management.ISessionContext;
27 import org.simantics.db.procedure.Listener;
28 import org.simantics.utils.datastructures.Pair;
30 public class Combo extends WidgetImpl {
32 private ReadFactory<?, Map<String, Object>> itemFactory;
33 private ReadFactory<?, List<Pair<String, Object>>> itemFactory2;
34 private ReadFactory<?, String> selectionFactory;
35 private final CopyOnWriteArrayList<ModifyListener> modifyListeners = new CopyOnWriteArrayList<ModifyListener>();
36 private List<Pair<String, Object>> itemList;
38 final private Display display;
39 final private org.eclipse.swt.widgets.Combo combo;
41 public Combo(Composite parent, WidgetSupport support, int style) {
43 this.display = parent.getDisplay();
44 combo = new org.eclipse.swt.widgets.Combo(parent, style);
45 combo.setData("org.simantics.browsing.ui.widgets.Combo", this);
46 support.register(this);
49 public void setItemFactory(ReadFactory<?, Map<String, Object>> itemFactory) {
50 if (this.itemFactory2 != null)
51 throw new IllegalStateException("Cannot use both itemFactory and itemFactory2");
52 this.itemFactory = itemFactory;
55 public void setItemFactory2(ReadFactory<?, List<Pair<String, Object>>> itemFactory) {
56 if (this.itemFactory != null)
57 throw new IllegalStateException("Cannot use both itemFactory and itemFactory2");
58 this.itemFactory2 = itemFactory;
61 public void setSelectionFactory(ReadFactory<?, String> selectionFactory) {
62 this.selectionFactory = selectionFactory;
65 public org.eclipse.swt.widgets.Combo getWidget() {
70 public Control getControl() {
74 private AtomicBoolean inputDisposed;
77 public void setInput(ISessionContext context, Object input) {
79 if (this.inputDisposed != null)
80 this.inputDisposed.set(true);
81 final AtomicBoolean inputDisposed = this.inputDisposed = new AtomicBoolean(false);
83 if (modifyListeners != null) {
84 for (ModifyListener listener : modifyListeners) {
85 if(listener instanceof Widget) {
86 ((Widget) listener).setInput(context, input);
91 if(itemFactory != null) {
92 itemFactory.listen(context, input, new Listener<Map<String, Object>>() {
95 public void exception(Throwable t) {
100 public void execute(final Map<String, Object> items) {
101 if(isDisposed()) return;
102 display.asyncExec(new Runnable() {
106 if(isDisposed()) return;
107 // System.out.println("Combo received new items: " + items.size());
108 for(ModifyListener listener : modifyListeners) combo.removeModifyListener(listener);
109 combo.setData(items);
110 combo.clearSelection();
113 } catch (Throwable t) {
117 for(String key : items.keySet()) {
118 // System.out.println("-" + key);
120 combo.setData(key, index++);
122 String selectionKey = (String)combo.getData("_SelectionKey");
123 if(selectionKey != null) {
124 Integer selectionIndex = (Integer)combo.getData(selectionKey);
125 if(selectionIndex != null) combo.select(selectionIndex);
127 for(ModifyListener listener : modifyListeners) combo.addModifyListener(listener);
128 //label.setSize(200, 20);
129 // label.getParent().layout();
130 // label.getParent().getParent().layout();
137 public boolean isDisposed() {
138 return combo.isDisposed() || inputDisposed.get();
144 if(itemFactory2 != null) {
145 itemFactory2.listen(context, input, new Listener<List<Pair<String, Object>>>() {
148 public void exception(Throwable t) {
153 public void execute(final List<Pair<String, Object>> items) {
154 if(isDisposed()) return;
155 display.asyncExec(new Runnable() {
159 if(isDisposed()) return;
160 // System.out.println("Combo received new items: " + items.size());
162 for(ModifyListener listener : modifyListeners) combo.removeModifyListener(listener);
163 combo.setData(items);
164 combo.clearSelection();
167 } catch (Throwable t) {
172 for(Pair<String, Object> key : items) {
173 // System.out.println("-" + key);
174 combo.add(key.first);
175 combo.setData(key.first, index++);
177 String selectionKey = (String)combo.getData("_SelectionKey");
178 if(selectionKey != null) {
179 Integer selectionIndex = (Integer)combo.getData(selectionKey);
180 if(selectionIndex != null) combo.select(selectionIndex);
183 for(ModifyListener listener : modifyListeners) combo.addModifyListener(listener);
184 //label.setSize(200, 20);
185 // label.getParent().layout();
186 // label.getParent().getParent().layout();
193 public boolean isDisposed() {
194 return combo.isDisposed() || inputDisposed.get();
200 if(selectionFactory != null) {
201 selectionFactory.listen(context, input, new Listener<String>() {
204 public void exception(Throwable t) {
209 public void execute(final String selectionKey) {
210 if(isDisposed()) return;
211 display.asyncExec(new Runnable() {
215 if(isDisposed()) return;
216 if(selectionKey == null) return;
217 // System.out.println("Combo received new selection key: " + selectionKey);
218 for(ModifyListener listener : modifyListeners) combo.removeModifyListener(listener);
219 combo.setData("_SelectionKey", selectionKey);
220 Integer selectionIndex = (Integer)combo.getData(selectionKey);
221 if(selectionIndex != null) combo.select(selectionIndex);
222 for(ModifyListener listener : modifyListeners) combo.addModifyListener(listener);
229 public boolean isDisposed() {
230 return combo.isDisposed() || inputDisposed.get();
238 public synchronized void addModifyListener(ModifyListener listener) {
239 modifyListeners.add(listener);
240 combo.addModifyListener(listener);
246 * @throws IndexOutOfBoundsException if index is outside widget bounds
248 @SuppressWarnings("unchecked")
249 public <T> Pair<String, T> getData(int index) {
250 if (itemFactory != null)
251 new IllegalStateException("this method is only useful when used with Combo.setItemFactory2").printStackTrace();
254 return (Pair<String, T>) itemList.get(index);
258 * @return selected combo list item or <code>null</code> if no item is
261 public <T> Pair<String, T> getSelectedData() {
262 return getData(combo.getSelectionIndex());