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.contentassist;
14 import java.util.ArrayList;
15 import java.util.List;
17 import org.eclipse.swt.SWT;
18 import org.eclipse.swt.widgets.Composite;
19 import org.eclipse.swt.widgets.Event;
20 import org.eclipse.swt.widgets.Listener;
21 import org.eclipse.swt.widgets.TreeItem;
22 import org.simantics.browsing.ui.NodeContext;
23 import org.simantics.browsing.ui.common.modifiers.EnumeratedValue;
24 import org.simantics.browsing.ui.common.modifiers.Enumeration;
25 import org.simantics.browsing.ui.content.Labeler.CustomModifier;
28 * @author Tuukka Lehtonen
30 public class AbstractContentAssistEnumerationModifier<T> implements CustomModifier {
32 protected final Enumeration<T> enumeration;
33 protected final EnumeratedValue<T> value;
35 protected ContentAssistTextField text;
37 public AbstractContentAssistEnumerationModifier(Enumeration<T> enumeration, T value) {
38 this(enumeration, enumeration.find(value));
41 public AbstractContentAssistEnumerationModifier(Enumeration<T> enumeration, EnumeratedValue<T> value) {
42 if (enumeration == null)
43 throw new NullPointerException("null enumeration");
44 if (enumeration.size() == 0)
45 throw new IllegalArgumentException("");
47 this.enumeration = enumeration;
52 public String getValue() {
54 return value.getName();
55 return enumeration.values().get(0).getName();
59 public String isValid(String label) {
60 if (enumeration.findByName(label) == null)
61 return "Value '" + label + "' is not among the enumerated values " + enumeration.values();
66 public void modify(String label) {
67 EnumeratedValue<T> value = enumeration.findByName(label);
69 throw new IllegalArgumentException("Cannot modify enumeration with value '" + label + "', not among the enumerated values " + enumeration.values());
70 modifyWithValue(this.value, value);
73 protected void modifyWithValue(EnumeratedValue<T> oldEnumValue, EnumeratedValue<T> enumValue) {
74 T oldObject = oldEnumValue != null ? oldEnumValue.getObject() : null;
75 T newObject = enumValue != null ? enumValue.getObject() : null;
76 modifyWithObject(oldObject, newObject, EnumeratedValue.isInvalid(oldEnumValue));
80 * At least implement this if you don't override
81 * {@link #modifyWithValue(EnumeratedValue, EnumeratedValue)}.
83 * @param oldEnumObject
86 protected void modifyWithObject(T oldEnumObject, T enumObject, boolean force) {
90 * Override to customize the content assist proposal objects created from
91 * the enumerated values.
96 protected NamedObject<T> createNamedObject(EnumeratedValue<T> value) {
97 return new NamedObject<T>(value.getObject(), value.getName());
100 protected List<NamedObject<T>> toNamedObjects(Enumeration<T> enumeration) {
101 List<NamedObject<T>> namedObjects = new ArrayList<NamedObject<T>>();
102 for (EnumeratedValue<T> v : enumeration.values())
103 namedObjects.add(createNamedObject(v));
108 public Object createControl(Object parentControl, Object controlItem, final int columnIndex, NodeContext context) {
109 Composite parent = (Composite) parentControl;
110 final TreeItem item = (TreeItem) controlItem;
112 List<NamedObject<T>> possibleValues = toNamedObjects(enumeration);
113 NamedObject<T> selectedValue = value != null ? createNamedObject(value) : null;
115 text = new ContentAssistTextField(parent, selectedValue, possibleValues, SWT.NONE);
117 Listener textListener = new Listener() {
121 public void handleEvent(final Event e) {
124 String newText = text.getControl().getText();
125 // System.out.println("VALIDATE NEW TEXT: " + newText);
126 error = isValid(newText);
128 text.getControl().setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED));
129 // System.out.println("validation error: " + error);
131 text.getControl().setBackground(null);
133 // text.getDisplay().asyncExec(new Runnable() {
135 // public void run() {
136 //if (!text.getControl().isDisposed())
137 //text.getControl().traverse(SWT.TRAVERSE_ARROW_NEXT);
138 //text.getControl().setSelection(text.getControl().getCaretPosition());
144 // Safety check since it seems that this may happen with
146 // if (item.isDisposed())
149 // newText = text.getControl().getText();
150 // String leftText = newText.substring(0, e.start);
151 // String rightText = newText.substring(e.end, newText.length());
152 // GC gc = new GC(text.getControl());
153 // Point size = gc.textExtent(leftText + e.text + rightText);
155 // size = text.getControl().computeSize(size.x, SWT.DEFAULT);
156 // Rectangle itemRect = item.getBounds(columnIndex),
157 // rect = tree.getClientArea();
158 // editor.minimumWidth = Math.max(size.x, itemRect.width) + insetX * 2;
159 // int left = itemRect.x,
160 // right = rect.x + rect.width;
161 // editor.minimumWidth = Math.min(editor.minimumWidth, right - left);
162 // editor.minimumHeight = size.y + insetY * 2;
165 // case SWT.FocusOut: {
166 // System.out.println("focus out");
167 // String t = text.getControl().getText();
170 // // Item may be disposed if the tree gets reset after a previous editing.
171 // if (!item.isDisposed()) {
172 // item.setText(columnIndex, t);
173 // //queueSelectionRefresh(context);
179 //System.out.println(AbstractContentAssistEnumerationModifier.class.getSimpleName() + " TRAVERSE: " + e.detail);
181 case SWT.TRAVERSE_RETURN:
182 //System.out.println("TRAVERSE: RETURN");
183 INamedObject obj = text.getResult();
184 String txt = obj != null ? obj.getName() : text.getControl().getText();
185 if (txt == null || error != null) {
190 if (!item.isDisposed()) {
191 item.setText(columnIndex, txt);
192 //queueSelectionRefresh(context);
195 case SWT.TRAVERSE_ESCAPE:
196 //System.out.println("TRAVERSE: ESCAPE");
201 //System.out.println("unhandled traversal: " + e.detail);
209 text.getControl().addListener(SWT.Modify, textListener);
210 // text.getControl().addListener(SWT.Verify, textListener);
211 // text.getControl().addListener(SWT.FocusOut, textListener);
212 text.getControl().addListener(SWT.Traverse, textListener);
215 text.text.selectAll();
216 text.getDisplay().asyncExec(new Runnable() {
219 if (!text.isDisposed())