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 abstract public class AbstractContentAssistModifier<T> implements CustomModifier {
32 protected final Enumeration<T> enumeration;
33 protected final T value;
35 protected ContentAssistTextField text;
37 public AbstractContentAssistModifier(Enumeration<T> enumeration, T value) {
38 if (enumeration == null)
39 throw new NullPointerException("null enumeration");
40 if (enumeration.size() == 0)
41 throw new IllegalArgumentException("");
43 this.enumeration = enumeration;
48 public String getValue() {
50 return value.toString();
51 return enumeration.values().get(0).getName();
55 public String isValid(String label) {
56 if (enumeration.findByName(label) == null)
57 return "Value '" + label + "' is not among the enumerated values " + enumeration.values();
62 public void modify(String label) {
63 String error = isValid(label);
65 throw new IllegalArgumentException(error);
66 modifyWithValue(this.value, label);
69 abstract void modifyWithValue(T oldEnumValue, String enumValue);
72 * Override to customize the content assist proposal objects created from
73 * the enumerated values.
78 protected NamedObject<T> createNamedObject(EnumeratedValue<T> value) {
79 return new NamedObject<T>(value.getObject(), value.getName());
82 protected List<NamedObject<T>> toNamedObjects(Enumeration<T> enumeration) {
83 List<NamedObject<T>> namedObjects = new ArrayList<NamedObject<T>>();
84 for (EnumeratedValue<T> v : enumeration.values())
85 namedObjects.add(createNamedObject(v));
90 public Object createControl(Object parentControl, Object controlItem, final int columnIndex, NodeContext context) {
91 Composite parent = (Composite) parentControl;
92 final TreeItem item = (TreeItem) controlItem;
94 List<NamedObject<T>> possibleValues = toNamedObjects(enumeration);
96 EnumeratedValue<T> enuValue = enumeration.find(value);
98 NamedObject<T> selectedValue = enuValue != null ? createNamedObject(enuValue) : null;
100 text = new ContentAssistTextField(parent, selectedValue, possibleValues, SWT.NONE);
102 Listener textListener = new Listener() {
106 public void handleEvent(final Event e) {
109 String newText = text.getControl().getText();
110 // System.out.println("VALIDATE NEW TEXT: " + newText);
111 error = isValid(newText);
113 text.getControl().setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED));
114 // System.out.println("validation error: " + error);
116 text.getControl().setBackground(null);
118 // text.getDisplay().asyncExec(new Runnable() {
120 // public void run() {
121 //if (!text.getControl().isDisposed())
122 //text.getControl().traverse(SWT.TRAVERSE_ARROW_NEXT);
123 //text.getControl().setSelection(text.getControl().getCaretPosition());
129 // Safety check since it seems that this may happen with
131 // if (item.isDisposed())
134 // newText = text.getControl().getText();
135 // String leftText = newText.substring(0, e.start);
136 // String rightText = newText.substring(e.end, newText.length());
137 // GC gc = new GC(text.getControl());
138 // Point size = gc.textExtent(leftText + e.text + rightText);
140 // size = text.getControl().computeSize(size.x, SWT.DEFAULT);
141 // Rectangle itemRect = item.getBounds(columnIndex),
142 // rect = tree.getClientArea();
143 // editor.minimumWidth = Math.max(size.x, itemRect.width) + insetX * 2;
144 // int left = itemRect.x,
145 // right = rect.x + rect.width;
146 // editor.minimumWidth = Math.min(editor.minimumWidth, right - left);
147 // editor.minimumHeight = size.y + insetY * 2;
150 // case SWT.FocusOut: {
151 // System.out.println("focus out");
152 // String t = text.getControl().getText();
155 // // Item may be disposed if the tree gets reset after a previous editing.
156 // if (!item.isDisposed()) {
157 // item.setText(columnIndex, t);
158 // //queueSelectionRefresh(context);
164 //System.out.println(AbstractContentAssistEnumerationModifier.class.getSimpleName() + " TRAVERSE: " + e.detail);
166 case SWT.TRAVERSE_RETURN:
167 //System.out.println("TRAVERSE: RETURN");
168 INamedObject obj = text.getResult();
169 String txt = obj != null ? obj.getName() : text.getControl().getText();
170 if (txt == null || error != null) {
175 if (!item.isDisposed()) {
176 item.setText(columnIndex, txt);
177 //queueSelectionRefresh(context);
180 case SWT.TRAVERSE_ESCAPE:
181 //System.out.println("TRAVERSE: ESCAPE");
186 //System.out.println("unhandled traversal: " + e.detail);
194 text.getControl().addListener(SWT.Modify, textListener);
195 // text.getControl().addListener(SWT.Verify, textListener);
196 // text.getControl().addListener(SWT.FocusOut, textListener);
197 text.getControl().addListener(SWT.Traverse, textListener);
200 text.text.selectAll();
201 text.getDisplay().asyncExec(new Runnable() {
204 if (!text.isDisposed())