]>
Commit | Line | Data |
---|---|---|
1b2798f6 EK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2005, 2011 IBM Corporation and others. | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * IBM Corporation - initial API and implementation | |
10 | *******************************************************************************/ | |
11 | package org.eclipse.jdt.internal.ui.dialogs; | |
12 | ||
13 | import org.eclipse.swt.SWT; | |
14 | import org.eclipse.swt.events.FocusAdapter; | |
15 | import org.eclipse.swt.events.FocusEvent; | |
16 | import org.eclipse.swt.events.KeyAdapter; | |
17 | import org.eclipse.swt.events.KeyEvent; | |
18 | import org.eclipse.swt.events.ModifyEvent; | |
19 | import org.eclipse.swt.events.ModifyListener; | |
20 | import org.eclipse.swt.events.MouseAdapter; | |
21 | import org.eclipse.swt.events.MouseEvent; | |
22 | import org.eclipse.swt.events.SelectionAdapter; | |
23 | import org.eclipse.swt.events.SelectionEvent; | |
24 | import org.eclipse.swt.events.TraverseEvent; | |
25 | import org.eclipse.swt.events.TraverseListener; | |
26 | import org.eclipse.swt.widgets.Composite; | |
27 | import org.eclipse.swt.widgets.Control; | |
28 | import org.eclipse.swt.widgets.Text; | |
29 | ||
30 | import org.eclipse.core.runtime.Assert; | |
31 | ||
32 | import org.eclipse.jface.contentassist.SubjectControlContentAssistant; | |
33 | import org.eclipse.jface.viewers.CellEditor; | |
34 | import org.eclipse.jface.viewers.IStructuredSelection; | |
35 | import org.eclipse.jface.viewers.TableViewer; | |
36 | ||
37 | import org.eclipse.ui.contentassist.ContentAssistHandler; | |
38 | ||
39 | import org.eclipse.jdt.internal.corext.util.Messages; | |
40 | ||
41 | import org.eclipse.jdt.internal.ui.refactoring.ChangeParametersControl; | |
42 | import org.eclipse.jdt.internal.ui.refactoring.contentassist.ControlContentAssistHelper; | |
43 | import org.eclipse.jdt.internal.ui.refactoring.contentassist.JavaTypeCompletionProcessor; | |
44 | ||
45 | /** | |
46 | * <code>TableTextCellEditor</code> is a copy of TextCellEditor, with the | |
47 | * following changes: | |
48 | * | |
49 | * <ul> | |
50 | * <li> modify events are sent out as the text is changed, and not only after | |
51 | * editing is done </li> | |
52 | * | |
53 | * <li>a content assistant is supported</li> | |
54 | * | |
55 | * <li>the user can go to the next/previous row with up and down keys</li> | |
56 | * </ul> | |
57 | */ | |
58 | public class TableTextCellEditor extends CellEditor { | |
59 | public interface IActivationListener { | |
60 | public void activate(); | |
61 | } | |
62 | ||
63 | private final TableViewer fTableViewer; | |
64 | private final int fColumn; | |
65 | private final String fProperty; | |
66 | /** | |
67 | * The editor's value on activation. This value is reset to the | |
68 | * cell when the editor is left via ESC key. | |
69 | */ | |
70 | String fOriginalValue; | |
71 | SubjectControlContentAssistant fContentAssistant; | |
72 | private IActivationListener fActivationListener; | |
73 | ||
74 | protected Text text; | |
75 | ||
76 | private boolean isSelection = false; | |
77 | private boolean isDeleteable = false; | |
78 | private boolean isSelectable = false; | |
79 | ||
80 | private static final int defaultStyle = SWT.SINGLE; | |
81 | private ModifyListener fModifyListener; | |
82 | ||
83 | public TableTextCellEditor(TableViewer tableViewer, int column) { | |
84 | super(tableViewer.getTable(), defaultStyle); | |
85 | fTableViewer= tableViewer; | |
86 | fColumn= column; | |
87 | fProperty= (String) tableViewer.getColumnProperties()[column]; | |
88 | } | |
89 | ||
90 | @Override | |
91 | public void activate() { | |
92 | super.activate(); | |
93 | if (fActivationListener != null) | |
94 | fActivationListener.activate(); | |
95 | fOriginalValue= text.getText(); | |
96 | } | |
97 | ||
98 | private void fireModifyEvent(Object newValue) { | |
99 | fTableViewer.getCellModifier().modify( | |
100 | ((IStructuredSelection) fTableViewer.getSelection()).getFirstElement(), | |
101 | fProperty, newValue); | |
102 | } | |
103 | ||
104 | @Override | |
105 | protected void focusLost() { | |
106 | if (fContentAssistant != null && fContentAssistant.hasProposalPopupFocus()) { | |
107 | // skip focus lost if it went to the content assist popup | |
108 | } else { | |
109 | super.focusLost(); | |
110 | } | |
111 | } | |
112 | ||
113 | public void setContentAssistant(SubjectControlContentAssistant assistant) { | |
114 | fContentAssistant= assistant; | |
115 | } | |
116 | ||
117 | public void setActivationListener(IActivationListener listener) { | |
118 | fActivationListener= listener; | |
119 | } | |
120 | ||
121 | public Text getText() { | |
122 | return text; | |
123 | } | |
124 | ||
125 | protected void checkDeleteable() { | |
126 | boolean oldIsDeleteable = isDeleteable; | |
127 | isDeleteable = isDeleteEnabled(); | |
128 | if (oldIsDeleteable != isDeleteable) { | |
129 | fireEnablementChanged(DELETE); | |
130 | } | |
131 | } | |
132 | ||
133 | protected void checkSelectable() { | |
134 | boolean oldIsSelectable = isSelectable; | |
135 | isSelectable = isSelectAllEnabled(); | |
136 | if (oldIsSelectable != isSelectable) { | |
137 | fireEnablementChanged(SELECT_ALL); | |
138 | } | |
139 | } | |
140 | ||
141 | protected void checkSelection() { | |
142 | boolean oldIsSelection = isSelection; | |
143 | isSelection = text.getSelectionCount() > 0; | |
144 | if (oldIsSelection != isSelection) { | |
145 | fireEnablementChanged(COPY); | |
146 | fireEnablementChanged(CUT); | |
147 | } | |
148 | } | |
149 | ||
150 | private ModifyListener getModifyListener() { | |
151 | if (fModifyListener == null) { | |
152 | fModifyListener = new ModifyListener() { | |
153 | public void modifyText(ModifyEvent e) { | |
154 | editOccured(e); | |
155 | } | |
156 | }; | |
157 | } | |
158 | return fModifyListener; | |
159 | } | |
160 | ||
161 | /* (non-Javadoc) | |
162 | * Method declared on CellEditor. | |
163 | */ | |
164 | @Override | |
165 | protected Control createControl(Composite parent) { | |
166 | text= new Text(parent, getStyle()); | |
167 | text.addSelectionListener(new SelectionAdapter() { | |
168 | @Override | |
169 | public void widgetDefaultSelected(SelectionEvent e) { | |
170 | handleDefaultSelection(e); | |
171 | } | |
172 | }); | |
173 | text.addKeyListener(new KeyAdapter() { | |
174 | @Override | |
175 | public void keyPressed(KeyEvent e) { | |
176 | // support switching rows while editing: | |
177 | if (e.stateMask == SWT.MOD1 || e.stateMask == SWT.MOD2) { | |
178 | if (e.keyCode == SWT.ARROW_UP || e.keyCode == SWT.ARROW_DOWN) { | |
179 | // allow starting multi-selection even if in edit mode | |
180 | deactivate(); | |
181 | e.doit= false; | |
182 | return; | |
183 | } | |
184 | } | |
185 | ||
186 | if (e.stateMask != SWT.NONE) | |
187 | return; | |
188 | ||
189 | switch (e.keyCode) { | |
190 | case SWT.ARROW_DOWN : | |
191 | e.doit= false; | |
192 | int nextRow= fTableViewer.getTable().getSelectionIndex() + 1; | |
193 | if (nextRow >= fTableViewer.getTable().getItemCount()) | |
194 | break; | |
195 | editRow(nextRow); | |
196 | break; | |
197 | ||
198 | case SWT.ARROW_UP : | |
199 | e.doit= false; | |
200 | int prevRow= fTableViewer.getTable().getSelectionIndex() - 1; | |
201 | if (prevRow < 0) | |
202 | break; | |
203 | editRow(prevRow); | |
204 | break; | |
205 | ||
206 | case SWT.F2 : | |
207 | e.doit= false; | |
208 | deactivate(); | |
209 | break; | |
210 | } | |
211 | } | |
212 | ||
213 | private void editRow(int row) { | |
214 | fTableViewer.getTable().setSelection(row); | |
215 | IStructuredSelection newSelection= (IStructuredSelection) fTableViewer.getSelection(); | |
216 | if (newSelection.size() == 1) | |
217 | fTableViewer.editElement(newSelection.getFirstElement(), fColumn); | |
218 | } | |
219 | }); | |
220 | text.addKeyListener(new KeyAdapter() { | |
221 | // hook key pressed - see PR 14201 | |
222 | @Override | |
223 | public void keyPressed(KeyEvent e) { | |
224 | keyReleaseOccured(e); | |
225 | ||
226 | // as a result of processing the above call, clients may have | |
227 | // disposed this cell editor | |
228 | if ((getControl() == null) || getControl().isDisposed()) | |
229 | return; | |
230 | checkSelection(); // see explaination below | |
231 | checkDeleteable(); | |
232 | checkSelectable(); | |
233 | } | |
234 | }); | |
235 | text.addTraverseListener(new TraverseListener() { | |
236 | public void keyTraversed(TraverseEvent e) { | |
237 | if (e.detail == SWT.TRAVERSE_ESCAPE | |
238 | || e.detail == SWT.TRAVERSE_RETURN) { | |
239 | e.doit = false; | |
240 | } | |
241 | } | |
242 | }); | |
243 | // We really want a selection listener but it is not supported so we | |
244 | // use a key listener and a mouse listener to know when selection changes | |
245 | // may have occurred | |
246 | text.addMouseListener(new MouseAdapter() { | |
247 | @Override | |
248 | public void mouseUp(MouseEvent e) { | |
249 | checkSelection(); | |
250 | checkDeleteable(); | |
251 | checkSelectable(); | |
252 | } | |
253 | }); | |
254 | text.addFocusListener(new FocusAdapter() { | |
255 | @Override | |
256 | public void focusLost(FocusEvent e) { | |
257 | e.display.asyncExec(new Runnable() { | |
258 | public void run() { | |
259 | // without the asyncExec, focus has not had a chance to go to the content assist proposals | |
260 | TableTextCellEditor.this.focusLost(); | |
261 | } | |
262 | }); | |
263 | } | |
264 | }); | |
265 | text.setFont(parent.getFont()); | |
266 | text.setBackground(parent.getBackground()); | |
267 | text.setText("");//$NON-NLS-1$ | |
268 | text.addModifyListener(getModifyListener()); | |
269 | ||
270 | return text; | |
271 | } | |
272 | ||
273 | @Override | |
274 | protected void fireCancelEditor() { | |
275 | /* bug 58540: change signature refactoring interaction: validate as you type [refactoring] */ | |
276 | text.setText(fOriginalValue); | |
277 | super.fireApplyEditorValue(); | |
278 | } | |
279 | ||
280 | /** | |
281 | * The <code>TextCellEditor</code> implementation of | |
282 | * this <code>CellEditor</code> framework method returns | |
283 | * the text string. | |
284 | * | |
285 | * @return the text string | |
286 | */ | |
287 | @Override | |
288 | protected Object doGetValue() { | |
289 | return text.getText(); | |
290 | } | |
291 | ||
292 | @Override | |
293 | protected void doSetFocus() { | |
294 | if (text != null) { | |
295 | text.selectAll(); | |
296 | text.setFocus(); | |
297 | checkSelection(); | |
298 | checkDeleteable(); | |
299 | checkSelectable(); | |
300 | } | |
301 | } | |
302 | ||
303 | /** | |
304 | * The <code>TextCellEditor2</code> implementation of | |
305 | * this <code>CellEditor</code> framework method accepts | |
306 | * a text string (type <code>String</code>). | |
307 | * | |
308 | * @param value a text string (type <code>String</code>) | |
309 | */ | |
310 | @Override | |
311 | protected void doSetValue(Object value) { | |
312 | Assert.isTrue(text != null && (value instanceof String)); | |
313 | text.removeModifyListener(getModifyListener()); | |
314 | text.setText((String) value); | |
315 | text.addModifyListener(getModifyListener()); | |
316 | } | |
317 | ||
318 | /** | |
319 | * Processes a modify event that occurred in this text cell editor. | |
320 | * This framework method performs validation and sets the error message | |
321 | * accordingly, and then reports a change via <code>fireEditorValueChanged</code>. | |
322 | * Subclasses should call this method at appropriate times. Subclasses | |
323 | * may extend or reimplement. | |
324 | * | |
325 | * @param e the SWT modify event | |
326 | */ | |
327 | protected void editOccured(ModifyEvent e) { | |
328 | String value = text.getText(); | |
329 | boolean oldValidState = isValueValid(); | |
330 | boolean newValidState = isCorrect(value); | |
331 | if (!newValidState) { | |
332 | // try to insert the current value into the error message. | |
333 | setErrorMessage(Messages.format(getErrorMessage(), | |
334 | new Object[] { value })); | |
335 | } | |
336 | valueChanged(oldValidState, newValidState); | |
337 | fireModifyEvent(text.getText()); // update model on-the-fly | |
338 | } | |
339 | ||
340 | @Override | |
341 | public LayoutData getLayoutData() { | |
342 | return new LayoutData(); | |
343 | } | |
344 | ||
345 | protected void handleDefaultSelection(SelectionEvent event) { | |
346 | // same with enter-key handling code in keyReleaseOccured(e); | |
347 | fireApplyEditorValue(); | |
348 | deactivate(); | |
349 | } | |
350 | ||
351 | @Override | |
352 | public boolean isCopyEnabled() { | |
353 | if (text == null || text.isDisposed()) | |
354 | return false; | |
355 | return text.getSelectionCount() > 0; | |
356 | } | |
357 | ||
358 | @Override | |
359 | public boolean isCutEnabled() { | |
360 | if (text == null || text.isDisposed()) | |
361 | return false; | |
362 | return text.getSelectionCount() > 0; | |
363 | } | |
364 | ||
365 | @Override | |
366 | public boolean isDeleteEnabled() { | |
367 | if (text == null || text.isDisposed()) | |
368 | return false; | |
369 | return text.getSelectionCount() > 0 | |
370 | || text.getCaretPosition() < text.getCharCount(); | |
371 | } | |
372 | ||
373 | @Override | |
374 | public boolean isPasteEnabled() { | |
375 | if (text == null || text.isDisposed()) | |
376 | return false; | |
377 | return true; | |
378 | } | |
379 | ||
380 | @Override | |
381 | public boolean isSelectAllEnabled() { | |
382 | if (text == null || text.isDisposed()) | |
383 | return false; | |
384 | return text.getCharCount() > 0; | |
385 | } | |
386 | ||
387 | @Override | |
388 | protected void keyReleaseOccured(KeyEvent keyEvent) { | |
389 | if (keyEvent.character == '\r') { // Return key | |
390 | // Enter is handled in handleDefaultSelection. | |
391 | // Do not apply the editor value in response to an Enter key event | |
392 | // since this can be received from the IME when the intent is -not- | |
393 | // to apply the value. | |
394 | // See bug 39074 [CellEditors] [DBCS] canna input mode fires bogus event from Text Control | |
395 | // | |
396 | // An exception is made for Ctrl+Enter for multi-line texts, since | |
397 | // a default selection event is not sent in this case. | |
398 | if (text != null && !text.isDisposed() | |
399 | && (text.getStyle() & SWT.MULTI) != 0) { | |
400 | if ((keyEvent.stateMask & SWT.CTRL) != 0) { | |
401 | super.keyReleaseOccured(keyEvent); | |
402 | } | |
403 | } | |
404 | return; | |
405 | } | |
406 | super.keyReleaseOccured(keyEvent); | |
407 | } | |
408 | ||
409 | @Override | |
410 | public void performCopy() { | |
411 | text.copy(); | |
412 | } | |
413 | ||
414 | @Override | |
415 | public void performCut() { | |
416 | text.cut(); | |
417 | checkSelection(); | |
418 | checkDeleteable(); | |
419 | checkSelectable(); | |
420 | } | |
421 | ||
422 | @Override | |
423 | public void performDelete() { | |
424 | if (text.getSelectionCount() > 0) | |
425 | // remove the contents of the current selection | |
426 | text.insert(""); //$NON-NLS-1$ | |
427 | else { | |
428 | // remove the next character | |
429 | int pos = text.getCaretPosition(); | |
430 | if (pos < text.getCharCount()) { | |
431 | text.setSelection(pos, pos + 1); | |
432 | text.insert(""); //$NON-NLS-1$ | |
433 | } | |
434 | } | |
435 | checkSelection(); | |
436 | checkDeleteable(); | |
437 | checkSelectable(); | |
438 | } | |
439 | ||
440 | @Override | |
441 | public void performPaste() { | |
442 | text.paste(); | |
443 | checkSelection(); | |
444 | checkDeleteable(); | |
445 | checkSelectable(); | |
446 | } | |
447 | ||
448 | @Override | |
449 | public void performSelectAll() { | |
450 | text.selectAll(); | |
451 | checkSelection(); | |
452 | checkDeleteable(); | |
453 | } | |
454 | ||
455 | /* | |
456 | * @see org.eclipse.jface.viewers.CellEditor#dependsOnExternalFocusListener() | |
457 | */ | |
458 | @Override | |
459 | protected boolean dependsOnExternalFocusListener() { | |
460 | return false; | |
461 | } | |
462 | ||
463 | public void generated_8020750380894542173(final TableViewer tableViewer, JavaTypeCompletionProcessor superInterfaceCompletionProcessor) { | |
464 | SubjectControlContentAssistant contentAssistant= ControlContentAssistHelper.createJavaContentAssistant(superInterfaceCompletionProcessor); | |
465 | Text cellEditorText= getText(); | |
466 | ContentAssistHandler.createHandlerForText(cellEditorText, contentAssistant); | |
467 | TextFieldNavigationHandler.install(cellEditorText); | |
468 | setContentAssistant(contentAssistant); | |
469 | ||
470 | tableViewer.setCellEditors(new CellEditor[] { this }); | |
471 | } | |
472 | ||
473 | public void generated_3875397303026142273(final int editorColumn, final ChangeParametersControl changeparameterscontrol) { | |
474 | getText().addTraverseListener(new TraverseListener() { | |
475 | public void keyTraversed(TraverseEvent e) { | |
476 | switch (e.detail) { | |
477 | case SWT.TRAVERSE_TAB_NEXT : | |
478 | changeparameterscontrol.editColumnOrNextPossible(changeparameterscontrol.nextColumn(editorColumn)); | |
479 | e.detail= SWT.TRAVERSE_NONE; | |
480 | break; | |
481 | ||
482 | case SWT.TRAVERSE_TAB_PREVIOUS : | |
483 | changeparameterscontrol.editColumnOrPrevPossible(changeparameterscontrol.prevColumn(editorColumn)); | |
484 | e.detail= SWT.TRAVERSE_NONE; | |
485 | break; | |
486 | ||
487 | default : | |
488 | break; | |
489 | } | |
490 | } | |
491 | }); | |
492 | TextFieldNavigationHandler.install(getText()); | |
493 | } | |
494 | } |