]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/contentassist/AbstractContentAssistEnumerationModifier.java
TreeGridWidget performance
[simantics/platform.git] / bundles / org.simantics.browsing.ui.swt / src / org / simantics / browsing / ui / swt / contentassist / AbstractContentAssistEnumerationModifier.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2012 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.browsing.ui.swt.contentassist;
13
14 import java.util.ArrayList;
15 import java.util.List;
16
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;
26
27 /**
28  * @author Tuukka Lehtonen
29  */
30 public class AbstractContentAssistEnumerationModifier<T> implements CustomModifier {
31
32     protected final Enumeration<T>     enumeration;
33     protected final EnumeratedValue<T> value;
34
35     protected ContentAssistTextField   text;
36
37     public AbstractContentAssistEnumerationModifier(Enumeration<T> enumeration, T value) {
38         this(enumeration, enumeration.find(value));
39     }
40
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("");
46
47         this.enumeration = enumeration;
48         this.value = value;
49     }
50
51     @Override
52     public String getValue() {
53         if (value != null)
54             return value.getName();
55         return enumeration.values().get(0).getName();
56     }
57
58     @Override
59     public String isValid(String label) {
60         if (enumeration.findByName(label) == null)
61             return "Value '" + label + "' is not among the enumerated values " + enumeration.values();
62         return null;
63     }
64
65     @Override
66     public void modify(String label) {
67         EnumeratedValue<T> value = enumeration.findByName(label);
68         if (value == null)
69             throw new IllegalArgumentException("Cannot modify enumeration with value '" + label + "', not among the enumerated values " + enumeration.values());
70         modifyWithValue(this.value, value);
71     }
72
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));
77     }
78
79     /**
80      * At least implement this if you don't override
81      * {@link #modifyWithValue(EnumeratedValue, EnumeratedValue)}.
82      * 
83      * @param oldEnumObject
84      * @param enumObject
85      */
86     protected void modifyWithObject(T oldEnumObject, T enumObject, boolean force) {
87     }
88
89     /**
90      * Override to customize the content assist proposal objects created from
91      * the enumerated values.
92      * 
93      * @param value
94      * @return
95      */
96     protected NamedObject<T> createNamedObject(EnumeratedValue<T> value) {
97         return new NamedObject<T>(value.getObject(), value.getName());
98     }
99
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));
104         return namedObjects;
105     }
106
107     @Override
108     public Object createControl(Object parentControl, Object controlItem, final int columnIndex, NodeContext context) {
109         Composite parent = (Composite) parentControl;
110         final TreeItem item = (TreeItem) controlItem;
111
112         List<NamedObject<T>> possibleValues = toNamedObjects(enumeration);
113         NamedObject<T> selectedValue = value != null ? createNamedObject(value) : null;
114
115         text = new ContentAssistTextField(parent, selectedValue, possibleValues, SWT.NONE);
116
117         Listener textListener = new Listener() {
118             String error;
119
120             @Override
121             public void handleEvent(final Event e) {
122                 switch (e.type) {
123                     case SWT.Modify: {
124                         String newText = text.getControl().getText();
125 //                        System.out.println("VALIDATE NEW TEXT: " + newText);
126                         error = isValid(newText);
127                         if (error != null) {
128                             text.getControl().setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED));
129 //                                System.out.println("validation error: " + error);
130                         } else {
131                             text.getControl().setBackground(null);
132                         }
133 //                        text.getDisplay().asyncExec(new Runnable() {
134 //                            @Override
135 //                            public void run() {
136                         //if (!text.getControl().isDisposed())
137                         //text.getControl().traverse(SWT.TRAVERSE_ARROW_NEXT);
138                         //text.getControl().setSelection(text.getControl().getCaretPosition());
139 //                            }
140 //                        });
141                         break;
142                     }
143                     case SWT.Verify:
144                         // Safety check since it seems that this may happen with
145                         // virtual trees.
146 //                        if (item.isDisposed())
147 //                            return;
148
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);
154 //                        gc.dispose();
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;
163 //                        editor.layout();
164                         break;
165 //                    case SWT.FocusOut: {
166 //                        System.out.println("focus out");
167 //                        String t = text.getControl().getText();
168 //                        modify(t);
169 //
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);
174 //                        }
175 //                        text.dispose();
176 //                        break;
177 //                    }
178                     case SWT.Traverse: {
179                         //System.out.println(AbstractContentAssistEnumerationModifier.class.getSimpleName() + " TRAVERSE: " + e.detail);
180                         switch (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) {
186                                     e.doit = false;
187                                     return;
188                                 }
189                                 modify(txt);
190                                 if (!item.isDisposed()) {
191                                     item.setText(columnIndex, txt);
192                                     //queueSelectionRefresh(context);
193                                 }
194                                 // FALL THROUGH
195                             case SWT.TRAVERSE_ESCAPE:
196                                 //System.out.println("TRAVERSE: ESCAPE");
197                                 text.dispose();
198                                 e.doit = false;
199                                 break;
200                             default:
201                                 //System.out.println("unhandled traversal: " + e.detail);
202                                 break;
203                         }
204                         break;
205                     }
206                 }
207             }
208         };
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);
213
214         text.setFocus();
215         text.text.selectAll();
216         text.getDisplay().asyncExec(new Runnable() {
217             @Override
218             public void run() {
219                 if (!text.isDisposed())
220                     text.openAssist();
221             }
222         });
223
224         return text;
225     }
226
227 }