]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/contentassist/AbstractContentAssistModifier.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.browsing.ui.swt / src / org / simantics / browsing / ui / swt / contentassist / AbstractContentAssistModifier.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 abstract public class AbstractContentAssistModifier<T> implements CustomModifier {
31
32     protected final Enumeration<T>     enumeration;
33     protected final T value;
34
35     protected ContentAssistTextField   text;
36
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("");
42
43         this.enumeration = enumeration;
44         this.value = value;
45     }
46
47     @Override
48     public String getValue() {
49         if (value != null)
50             return value.toString();
51         return enumeration.values().get(0).getName();
52     }
53
54     @Override
55     public String isValid(String label) {
56         if (enumeration.findByName(label) == null)
57             return "Value '" + label + "' is not among the enumerated values " + enumeration.values();
58         return null;
59     }
60
61     @Override
62     public void modify(String label) {
63         String error = isValid(label); 
64         if(error != null)
65             throw new IllegalArgumentException(error);
66         modifyWithValue(this.value, label);
67     }
68
69     abstract void modifyWithValue(T oldEnumValue, String enumValue);
70
71     /**
72      * Override to customize the content assist proposal objects created from
73      * the enumerated values.
74      * 
75      * @param value
76      * @return
77      */
78     protected NamedObject<T> createNamedObject(EnumeratedValue<T> value) {
79         return new NamedObject<T>(value.getObject(), value.getName());
80     }
81
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));
86         return namedObjects;
87     }
88
89     @Override
90     public Object createControl(Object parentControl, Object controlItem, final int columnIndex, NodeContext context) {
91         Composite parent = (Composite) parentControl;
92         final TreeItem item = (TreeItem) controlItem;
93
94         List<NamedObject<T>> possibleValues = toNamedObjects(enumeration);
95         
96         EnumeratedValue<T> enuValue = enumeration.find(value);
97         
98         NamedObject<T> selectedValue = enuValue != null ? createNamedObject(enuValue) : null;
99
100         text = new ContentAssistTextField(parent, selectedValue, possibleValues, SWT.NONE);
101
102         Listener textListener = new Listener() {
103             String error;
104
105             @Override
106             public void handleEvent(final Event e) {
107                 switch (e.type) {
108                     case SWT.Modify: {
109                         String newText = text.getControl().getText();
110 //                        System.out.println("VALIDATE NEW TEXT: " + newText);
111                         error = isValid(newText);
112                         if (error != null) {
113                             text.getControl().setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED));
114 //                                System.out.println("validation error: " + error);
115                         } else {
116                             text.getControl().setBackground(null);
117                         }
118 //                        text.getDisplay().asyncExec(new Runnable() {
119 //                            @Override
120 //                            public void run() {
121                         //if (!text.getControl().isDisposed())
122                         //text.getControl().traverse(SWT.TRAVERSE_ARROW_NEXT);
123                         //text.getControl().setSelection(text.getControl().getCaretPosition());
124 //                            }
125 //                        });
126                         break;
127                     }
128                     case SWT.Verify:
129                         // Safety check since it seems that this may happen with
130                         // virtual trees.
131 //                        if (item.isDisposed())
132 //                            return;
133
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);
139 //                        gc.dispose();
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;
148 //                        editor.layout();
149                         break;
150 //                    case SWT.FocusOut: {
151 //                        System.out.println("focus out");
152 //                        String t = text.getControl().getText();
153 //                        modify(t);
154 //
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);
159 //                        }
160 //                        text.dispose();
161 //                        break;
162 //                    }
163                     case SWT.Traverse: {
164                         //System.out.println(AbstractContentAssistEnumerationModifier.class.getSimpleName() + " TRAVERSE: " + e.detail);
165                         switch (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) {
171                                     e.doit = false;
172                                     return;
173                                 }
174                                 modify(txt);
175                                 if (!item.isDisposed()) {
176                                     item.setText(columnIndex, txt);
177                                     //queueSelectionRefresh(context);
178                                 }
179                                 // FALL THROUGH
180                             case SWT.TRAVERSE_ESCAPE:
181                                 //System.out.println("TRAVERSE: ESCAPE");
182                                 text.dispose();
183                                 e.doit = false;
184                                 break;
185                             default:
186                                 //System.out.println("unhandled traversal: " + e.detail);
187                                 break;
188                         }
189                         break;
190                     }
191                 }
192             }
193         };
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);
198
199         text.setFocus();
200         text.text.selectAll();
201         text.getDisplay().asyncExec(new Runnable() {
202             @Override
203             public void run() {
204                 if (!text.isDisposed())
205                     text.openAssist();
206             }
207         });
208
209         return text;
210     }
211
212 }