]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/contentassist/AbstractContentAssistEnumerationModifier.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.browsing.ui.swt / src / org / simantics / browsing / ui / swt / contentassist / AbstractContentAssistEnumerationModifier.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.contentassist;\r
13 \r
14 import java.util.ArrayList;\r
15 import java.util.List;\r
16 \r
17 import org.eclipse.swt.SWT;\r
18 import org.eclipse.swt.widgets.Composite;\r
19 import org.eclipse.swt.widgets.Event;\r
20 import org.eclipse.swt.widgets.Listener;\r
21 import org.eclipse.swt.widgets.TreeItem;\r
22 import org.simantics.browsing.ui.NodeContext;\r
23 import org.simantics.browsing.ui.common.modifiers.EnumeratedValue;\r
24 import org.simantics.browsing.ui.common.modifiers.Enumeration;\r
25 import org.simantics.browsing.ui.content.Labeler.CustomModifier;\r
26 \r
27 /**\r
28  * @author Tuukka Lehtonen\r
29  */\r
30 public class AbstractContentAssistEnumerationModifier<T> implements CustomModifier {\r
31 \r
32     protected final Enumeration<T>     enumeration;\r
33     protected final EnumeratedValue<T> value;\r
34 \r
35     protected ContentAssistTextField   text;\r
36 \r
37     public AbstractContentAssistEnumerationModifier(Enumeration<T> enumeration, T value) {\r
38         this(enumeration, enumeration.find(value));\r
39     }\r
40 \r
41     public AbstractContentAssistEnumerationModifier(Enumeration<T> enumeration, EnumeratedValue<T> value) {\r
42         if (enumeration == null)\r
43             throw new NullPointerException("null enumeration");\r
44         if (enumeration.size() == 0)\r
45             throw new IllegalArgumentException("");\r
46 \r
47         this.enumeration = enumeration;\r
48         this.value = value;\r
49     }\r
50 \r
51     @Override\r
52     public String getValue() {\r
53         if (value != null)\r
54             return value.getName();\r
55         return enumeration.values().get(0).getName();\r
56     }\r
57 \r
58     @Override\r
59     public String isValid(String label) {\r
60         if (enumeration.findByName(label) == null)\r
61             return "Value '" + label + "' is not among the enumerated values " + enumeration.values();\r
62         return null;\r
63     }\r
64 \r
65     @Override\r
66     public void modify(String label) {\r
67         EnumeratedValue<T> value = enumeration.findByName(label);\r
68         if (value == null)\r
69             throw new IllegalArgumentException("Cannot modify enumeration with value '" + label + "', not among the enumerated values " + enumeration.values());\r
70         modifyWithValue(this.value, value);\r
71     }\r
72 \r
73     protected void modifyWithValue(EnumeratedValue<T> oldEnumValue, EnumeratedValue<T> enumValue) {\r
74         T oldObject = oldEnumValue != null ? oldEnumValue.getObject() : null;\r
75         T newObject = enumValue != null ? enumValue.getObject() : null;\r
76         modifyWithObject(oldObject, newObject, EnumeratedValue.isInvalid(oldEnumValue));\r
77     }\r
78 \r
79     /**\r
80      * At least implement this if you don't override\r
81      * {@link #modifyWithValue(EnumeratedValue, EnumeratedValue)}.\r
82      * \r
83      * @param oldEnumObject\r
84      * @param enumObject\r
85      */\r
86     protected void modifyWithObject(T oldEnumObject, T enumObject, boolean force) {\r
87     }\r
88 \r
89     /**\r
90      * Override to customize the content assist proposal objects created from\r
91      * the enumerated values.\r
92      * \r
93      * @param value\r
94      * @return\r
95      */\r
96     protected NamedObject<T> createNamedObject(EnumeratedValue<T> value) {\r
97         return new NamedObject<T>(value.getObject(), value.getName());\r
98     }\r
99 \r
100     protected List<NamedObject<T>> toNamedObjects(Enumeration<T> enumeration) {\r
101         List<NamedObject<T>> namedObjects = new ArrayList<NamedObject<T>>();\r
102         for (EnumeratedValue<T> v : enumeration.values())\r
103             namedObjects.add(createNamedObject(v));\r
104         return namedObjects;\r
105     }\r
106 \r
107     @Override\r
108     public Object createControl(Object parentControl, Object controlItem, final int columnIndex, NodeContext context) {\r
109         Composite parent = (Composite) parentControl;\r
110         final TreeItem item = (TreeItem) controlItem;\r
111 \r
112         List<NamedObject<T>> possibleValues = toNamedObjects(enumeration);\r
113         NamedObject<T> selectedValue = value != null ? createNamedObject(value) : null;\r
114 \r
115         text = new ContentAssistTextField(parent, selectedValue, possibleValues, SWT.NONE);\r
116 \r
117         Listener textListener = new Listener() {\r
118             String error;\r
119 \r
120             @Override\r
121             public void handleEvent(final Event e) {\r
122                 switch (e.type) {\r
123                     case SWT.Modify: {\r
124                         String newText = text.getControl().getText();\r
125 //                        System.out.println("VALIDATE NEW TEXT: " + newText);\r
126                         error = isValid(newText);\r
127                         if (error != null) {\r
128                             text.getControl().setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED));\r
129 //                                System.out.println("validation error: " + error);\r
130                         } else {\r
131                             text.getControl().setBackground(null);\r
132                         }\r
133 //                        text.getDisplay().asyncExec(new Runnable() {\r
134 //                            @Override\r
135 //                            public void run() {\r
136                         //if (!text.getControl().isDisposed())\r
137                         //text.getControl().traverse(SWT.TRAVERSE_ARROW_NEXT);\r
138                         //text.getControl().setSelection(text.getControl().getCaretPosition());\r
139 //                            }\r
140 //                        });\r
141                         break;\r
142                     }\r
143                     case SWT.Verify:\r
144                         // Safety check since it seems that this may happen with\r
145                         // virtual trees.\r
146 //                        if (item.isDisposed())\r
147 //                            return;\r
148 \r
149 //                        newText = text.getControl().getText();\r
150 //                        String leftText = newText.substring(0, e.start);\r
151 //                        String rightText = newText.substring(e.end, newText.length());\r
152 //                        GC gc = new GC(text.getControl());\r
153 //                        Point size = gc.textExtent(leftText + e.text + rightText);\r
154 //                        gc.dispose();\r
155 //                        size = text.getControl().computeSize(size.x, SWT.DEFAULT);\r
156 //                        Rectangle itemRect = item.getBounds(columnIndex),\r
157 //                        rect = tree.getClientArea();\r
158 //                        editor.minimumWidth = Math.max(size.x, itemRect.width) + insetX * 2;\r
159 //                        int left = itemRect.x,\r
160 //                        right = rect.x + rect.width;\r
161 //                        editor.minimumWidth = Math.min(editor.minimumWidth, right - left);\r
162 //                        editor.minimumHeight = size.y + insetY * 2;\r
163 //                        editor.layout();\r
164                         break;\r
165 //                    case SWT.FocusOut: {\r
166 //                        System.out.println("focus out");\r
167 //                        String t = text.getControl().getText();\r
168 //                        modify(t);\r
169 //\r
170 //                        // Item may be disposed if the tree gets reset after a previous editing.\r
171 //                        if (!item.isDisposed()) {\r
172 //                            item.setText(columnIndex, t);\r
173 //                            //queueSelectionRefresh(context);\r
174 //                        }\r
175 //                        text.dispose();\r
176 //                        break;\r
177 //                    }\r
178                     case SWT.Traverse: {\r
179                         //System.out.println(AbstractContentAssistEnumerationModifier.class.getSimpleName() + " TRAVERSE: " + e.detail);\r
180                         switch (e.detail) {\r
181                             case SWT.TRAVERSE_RETURN:\r
182                                 //System.out.println("TRAVERSE: RETURN");\r
183                                 INamedObject obj = text.getResult();\r
184                                 String txt = obj != null ? obj.getName() : text.getControl().getText();\r
185                                 if (txt ==  null || error != null) {\r
186                                     e.doit = false;\r
187                                     return;\r
188                                 }\r
189                                 modify(txt);\r
190                                 if (!item.isDisposed()) {\r
191                                     item.setText(columnIndex, txt);\r
192                                     //queueSelectionRefresh(context);\r
193                                 }\r
194                                 // FALL THROUGH\r
195                             case SWT.TRAVERSE_ESCAPE:\r
196                                 //System.out.println("TRAVERSE: ESCAPE");\r
197                                 text.dispose();\r
198                                 e.doit = false;\r
199                                 break;\r
200                             default:\r
201                                 //System.out.println("unhandled traversal: " + e.detail);\r
202                                 break;\r
203                         }\r
204                         break;\r
205                     }\r
206                 }\r
207             }\r
208         };\r
209         text.getControl().addListener(SWT.Modify, textListener);\r
210 //        text.getControl().addListener(SWT.Verify, textListener);\r
211 //        text.getControl().addListener(SWT.FocusOut, textListener);\r
212         text.getControl().addListener(SWT.Traverse, textListener);\r
213 \r
214         text.setFocus();\r
215         text.text.selectAll();\r
216         text.getDisplay().asyncExec(new Runnable() {\r
217             @Override\r
218             public void run() {\r
219                 if (!text.isDisposed())\r
220                     text.openAssist();\r
221             }\r
222         });\r
223 \r
224         return text;\r
225     }\r
226 \r
227 }\r