// a cell editor implementation providing autocompletion capabilities for JTable editing
1
2 import java.text.MessageFormat;
3
4 import org.eclipse.jface.fieldassist.IContentProposalProvider;
5 import org.eclipse.jface.fieldassist.TextContentAdapter;
6 import org.eclipse.jface.fieldassist.TextControlCreator;
7 import org.eclipse.jface.util.Assert;
8 import org.eclipse.jface.viewers.CellEditor;
9 import org.eclipse.swt.SWT;
10 import org.eclipse.swt.events.FocusAdapter;
11 import org.eclipse.swt.events.FocusEvent;
12 import org.eclipse.swt.events.KeyAdapter;
13 import org.eclipse.swt.events.KeyEvent;
14 import org.eclipse.swt.events.ModifyEvent;
15 import org.eclipse.swt.events.ModifyListener;
16 import org.eclipse.swt.events.MouseAdapter;
17 import org.eclipse.swt.events.MouseEvent;
18 import org.eclipse.swt.events.SelectionAdapter;
19 import org.eclipse.swt.events.SelectionEvent;
20 import org.eclipse.swt.events.TraverseEvent;
21 import org.eclipse.swt.events.TraverseListener;
22 import org.eclipse.swt.widgets.Composite;
23 import org.eclipse.swt.widgets.Control;
24 import org.eclipse.swt.widgets.Text;
25 import org.eclipse.ui.fieldassist.ContentAssistField;
26 import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
27
28 /**
29 * A cell editor that manages a content assist field.
30 * The cell editor's value is the text string itself.
31 *
32 * This class may be instantiated; it is not intended to be subclassed.
33 *
34 */
35 public class ContentAssistFieldCellEditor extends CellEditor
36 {
37 protected ContentAssistField field;
38
39 protected IContentProposalProvider contentProposalProvider;
40
41 protected char[] completionProposalAutoActivationCharacters;
42
43 private ModifyListener modifyListener;
44
45 public ContentAssistFieldCellEditor( char[] completionProposalAutoActivationCharacters, IContentProposalProvider contentProposalProvider)
46 {
47 super();
48 this.completionProposalAutoActivationCharacters = completionProposalAutoActivationCharacters;
49 this.contentProposalProvider = contentProposalProvider;
50 }
51
52 /**
53 * Return the modify listener.
54 */
55 private ModifyListener getModifyListener() {
56 if (modifyListener == null) {
57 modifyListener = new ModifyListener() {
58 public void modifyText(ModifyEvent e) {
59 editOccured(e);
60 }
61 };
62 }
63 return modifyListener;
64 }
65
66 public ContentAssistFieldCellEditor(Composite parent, int style, char[] completionProposalAutoActivationCharacters, IContentProposalProvider contentProposalProvider) {
67 super( parent, style);
68 }
69
70 public ContentAssistFieldCellEditor(Composite parent,char[] completionProposalAutoActivationCharacters, IContentProposalProvider contentProposalProvider)
71 {
72 super(parent);
73 }
74
75 /**
76 * State information for updating action enablement
77 */
78 private boolean isSelection = false;
79
80 private boolean isDeleteable = false;
81
82 private boolean isSelectable = false;
83
84 private Text text;
85
86 @Override
87 protected Control createControl(Composite parent)
88 {
89 //SimpleContentProposalProvider proposelProvider = new SimpleContentProposalProvider( new String[] { "a", "b", "c"});
90
91 field = new ContentAssistField(
92 parent,
93 SWT.SINGLE,
94 new TextControlCreator(),
95 new TextContentAdapter(),
96 contentProposalProvider,
97 ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS,
98 completionProposalAutoActivationCharacters
99 );
100
101 text = (Text)field.getControl();
102 text.addSelectionListener(new SelectionAdapter() {
103 public void widgetDefaultSelected(SelectionEvent e) {
104 handleDefaultSelection(e);
105 }
106 });
107
108 text.addKeyListener(new KeyAdapter() {
109 // hook key pressed - see PR 14201
110 public void keyPressed(KeyEvent e) {
111 keyReleaseOccured(e);
112
113 // as a result of processing the above call, clients may have
114 // disposed this cell editor
115 if ((getControl() == null) || getControl().isDisposed()) {
116 return;
117 }
118 checkSelection(); // see explaination below
119 checkDeleteable();
120 checkSelectable();
121 }
122 });
123 text.addTraverseListener(new TraverseListener() {
124 public void keyTraversed(TraverseEvent e) {
125 if (e.detail == SWT.TRAVERSE_ESCAPE
126 || e.detail == SWT.TRAVERSE_RETURN) {
127 e.doit = false;
128 }
129 }
130 });
131 // We really want a selection listener but it is not supported so we
132 // use a key listener and a mouse listener to know when selection changes
133 // may have occured
134 text.addMouseListener(new MouseAdapter() {
135 public void mouseUp(MouseEvent e) {
136 checkSelection();
137 checkDeleteable();
138 checkSelectable();
139 }
140 });
141 text.addFocusListener(new FocusAdapter() {
142 public void focusLost(FocusEvent e) {
143 ContentAssistFieldCellEditor.this.focusLost();
144 }
145 });
146 text.setFont(parent.getFont());
147 text.setBackground(parent.getBackground());
148 text.setText("");//$NON-NLS-1$
149 text.addModifyListener( getModifyListener());
150
151 return field.getLayoutControl();
152 }
153
154 /**
155 * Checks to see if the "deleteable" state (can delete/
156 * nothing to delete) has changed and if so fire an
157 * enablement changed notification.
158 */
159 private void checkDeleteable() {
160 boolean oldIsDeleteable = isDeleteable;
161 isDeleteable = isDeleteEnabled();
162 if (oldIsDeleteable != isDeleteable) {
163 fireEnablementChanged(DELETE);
164 }
165 }
166
167 /**
168 * Checks to see if the "selectable" state (can select)
169 * has changed and if so fire an enablement changed notification.
170 */
171 private void checkSelectable() {
172 boolean oldIsSelectable = isSelectable;
173 isSelectable = isSelectAllEnabled();
174 if (oldIsSelectable != isSelectable) {
175 fireEnablementChanged(SELECT_ALL);
176 }
177 }
178
179 /**
180 * Checks to see if the selection state (selection /
181 * no selection) has changed and if so fire an
182 * enablement changed notification.
183 */
184 private void checkSelection() {
185 boolean oldIsSelection = isSelection;
186 isSelection = text.getSelectionCount() > 0;
187 if (oldIsSelection != isSelection) {
188 fireEnablementChanged(COPY);
189 fireEnablementChanged(CUT);
190 }
191 }
192
193 /**
194 * Processes a modify event that occurred in this text cell editor.
195 * This framework method performs validation and sets the error message
196 * accordingly, and then reports a change via fireEditorValueChanged.
197 * Subclasses should call this method at appropriate times. Subclasses
198 * may extend or reimplement.
199 *
200 * @param e the SWT modify event
201 */
202 protected void editOccured(ModifyEvent e) {
203 String value = text.getText();
204 if (value == null) {
205 value = "";//$NON-NLS-1$
206 }
207 Object typedValue = value;
208 boolean oldValidState = isValueValid();
209 boolean newValidState = isCorrect(typedValue);
210 if (typedValue == null && newValidState) {
211 Assert.isTrue(false,
212 "Validator isn't limiting the cell editor's type range");//$NON-NLS-1$
213 }
214 if (!newValidState) {
215 // try to insert the current value into the error message.
216 setErrorMessage(MessageFormat.format(getErrorMessage(),
217 new Object[] { value }));
218 }
219 valueChanged(oldValidState, newValidState);
220 }
221
222 /**
223 * Handles a default selection event from the text control by applying the editor
224 * value and deactivating this cell editor.
225 *
226 * @param event the selection event
227 */
228 protected void handleDefaultSelection(SelectionEvent event)
229 {
230 // same with enter-key handling code in keyReleaseOccured(e);
231 fireApplyEditorValue();
232 deactivate();
233 }
234
235 @Override
236 protected void doSetFocus()
237 {
238 if( field!= null) {
239 field.getControl().setFocus();
240 }
241 }
242
243 @Override
244 protected Object doGetValue()
245 {
246 return ((Text)field.getControl()).getText();
247 }
248
249 @Override
250 protected void doSetValue(Object value)
251 {
252 ((Text)field.getControl()).setText( value.toString());
253 }
254
255 /**
256 * The implementation of this
257 * method copies the
258 * current selection to the clipboard.
259 */
260 public void performCopy() {
261 text.copy();
262 }
263
264 /**
265 * The implementation of this
266 * method cuts the
267 * current selection to the clipboard.
268 */
269 public void performCut() {
270 text.cut();
271 checkSelection();
272 checkDeleteable();
273 checkSelectable();
274 }
275
276 /**
277 * The implementation of this
278 * method deletes the
279 * current selection or, if there is no selection,
280 * the character next character from the current position.
281 */
282 public void performDelete() {
283 if (text.getSelectionCount() > 0) {
284 // remove the contents of the current selection
285 text.insert(""); //$NON-NLS-1$
286 } else {
287 // remove the next character
288 int pos = text.getCaretPosition();
289 if (pos < text.getCharCount()) {
290 text.setSelection(pos, pos + 1);
291 text.insert(""); //$NON-NLS-1$
292 }
293 }
294 checkSelection();
295 checkDeleteable();
296 checkSelectable();
297 }
298
299 /**
300 * The implementation of this
301 * method pastes the
302 * the clipboard contents over the current selection.
303 */
304 public void performPaste() {
305 text.paste();
306 checkSelection();
307 checkDeleteable();
308 checkSelectable();
309 }
310
311 /**
312 * The implementation of this
313 * method selects all of the
314 * current text.
315 */
316 public void performSelectAll() {
317 text.selectAll();
318 checkSelection();
319 checkDeleteable();
320 }
321
322
323
324 /**
325 * Since a text editor field is scrollable we don't
326 * set a minimumSize.
327 */
328 public LayoutData getLayoutData() {
329 return new LayoutData();
330 }
331
332 /**
333 * Processes a key release event that occurred in this cell editor.
334 *
335 * The implementation of this framework method
336 * ignores when the RETURN key is pressed since this is handled in
337 * handleDefaultSelection.
338 * An exception is made for Ctrl+Enter for multi-line texts, since
339 * a default selection event is not sent in this case.
340 *
341 *
342 * @param keyEvent the key event
343 */
344 protected void keyReleaseOccured(KeyEvent keyEvent) {
345 if (keyEvent.character == '\r') { // Return key
346 // Enter is handled in handleDefaultSelection.
347 // Do not apply the editor value in response to an Enter key event
348 // since this can be received from the IME when the intent is -not-
349 // to apply the value.
350 // See bug 39074 [CellEditors] [DBCS] canna input mode fires bogus event from Text Control
351 //
352 // An exception is made for Ctrl+Enter for multi-line texts, since
353 // a default selection event is not sent in this case.
354 if (text != null && !text.isDisposed()
355 && (text.getStyle() & SWT.MULTI) != 0) {
356 if ((keyEvent.stateMask & SWT.CTRL) != 0) {
357 super.keyReleaseOccured(keyEvent);
358 }
359 }
360 return;
361 }
362 super.keyReleaseOccured(keyEvent);
363 }
364 }
365