comparison dwtx/jface/viewers/TextCellEditor.d @ 10:b6c35faf97c8

Viewers
author Frank Benoit <benoit@tionex.de>
date Mon, 31 Mar 2008 00:47:19 +0200
parents
children ea8ff534f622
comparison
equal deleted inserted replaced
9:6c14e54dfc11 10:b6c35faf97c8
1 /*******************************************************************************
2 * Copyright (c) 2000, 2007 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 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13
14 module dwtx.jface.viewers.TextCellEditor;
15
16 import dwtx.jface.viewers.CellEditor;
17
18 import dwt.DWT;
19 import dwt.events.FocusAdapter;
20 import dwt.events.FocusEvent;
21 import dwt.events.KeyAdapter;
22 import dwt.events.KeyEvent;
23 import dwt.events.ModifyEvent;
24 import dwt.events.ModifyListener;
25 import dwt.events.MouseAdapter;
26 import dwt.events.MouseEvent;
27 import dwt.events.SelectionAdapter;
28 import dwt.events.SelectionEvent;
29 import dwt.events.TraverseEvent;
30 import dwt.events.TraverseListener;
31 import dwt.widgets.Composite;
32 import dwt.widgets.Control;
33 import dwt.widgets.Text;
34 import dwtx.core.runtime.Assert;
35
36 import dwt.dwthelper.utils;
37 import tango.text.convert.Format;
38
39 /**
40 * A cell editor that manages a text entry field.
41 * The cell editor's value is the text string itself.
42 * <p>
43 * This class may be instantiated; it is not intended to be subclassed.
44 * </p>
45 */
46 public class TextCellEditor : CellEditor {
47
48 /**
49 * The text control; initially <code>null</code>.
50 */
51 protected Text text;
52
53 private ModifyListener modifyListener;
54
55 /**
56 * State information for updating action enablement
57 */
58 private bool isSelection = false;
59
60 private bool isDeleteable = false;
61
62 private bool isSelectable = false;
63
64 /**
65 * Default TextCellEditor style
66 * specify no borders on text widget as cell outline in table already
67 * provides the look of a border.
68 */
69 private static const int defaultStyle = DWT.SINGLE;
70
71 /**
72 * Creates a new text string cell editor with no control
73 * The cell editor value is the string itself, which is initially the empty
74 * string. Initially, the cell editor has no cell validator.
75 *
76 * @since 2.1
77 */
78 public this() {
79 setStyle(defaultStyle);
80 }
81
82 /**
83 * Creates a new text string cell editor parented under the given control.
84 * The cell editor value is the string itself, which is initially the empty string.
85 * Initially, the cell editor has no cell validator.
86 *
87 * @param parent the parent control
88 */
89 public this(Composite parent) {
90 this(parent, defaultStyle);
91 }
92
93 /**
94 * Creates a new text string cell editor parented under the given control.
95 * The cell editor value is the string itself, which is initially the empty string.
96 * Initially, the cell editor has no cell validator.
97 *
98 * @param parent the parent control
99 * @param style the style bits
100 * @since 2.1
101 */
102 public this(Composite parent, int style) {
103 super(parent, style);
104 }
105
106 /**
107 * Checks to see if the "deletable" state (can delete/
108 * nothing to delete) has changed and if so fire an
109 * enablement changed notification.
110 */
111 private void checkDeleteable() {
112 bool oldIsDeleteable = isDeleteable;
113 isDeleteable = isDeleteEnabled();
114 if (oldIsDeleteable !is isDeleteable) {
115 fireEnablementChanged(DELETE);
116 }
117 }
118
119 /**
120 * Checks to see if the "selectable" state (can select)
121 * has changed and if so fire an enablement changed notification.
122 */
123 private void checkSelectable() {
124 bool oldIsSelectable = isSelectable;
125 isSelectable = isSelectAllEnabled();
126 if (oldIsSelectable !is isSelectable) {
127 fireEnablementChanged(SELECT_ALL);
128 }
129 }
130
131 /**
132 * Checks to see if the selection state (selection /
133 * no selection) has changed and if so fire an
134 * enablement changed notification.
135 */
136 private void checkSelection() {
137 bool oldIsSelection = isSelection;
138 isSelection = text.getSelectionCount() > 0;
139 if (oldIsSelection !is isSelection) {
140 fireEnablementChanged(COPY);
141 fireEnablementChanged(CUT);
142 }
143 }
144
145 /* (non-Javadoc)
146 * Method declared on CellEditor.
147 */
148 protected Control createControl(Composite parent) {
149 text = new Text(parent, getStyle());
150 text.addSelectionListener(new class SelectionAdapter {
151 public void widgetDefaultSelected(SelectionEvent e) {
152 handleDefaultSelection(e);
153 }
154 });
155 text.addKeyListener(new class KeyAdapter {
156 // hook key pressed - see PR 14201
157 public void keyPressed(KeyEvent e) {
158 keyReleaseOccured(e);
159
160 // as a result of processing the above call, clients may have
161 // disposed this cell editor
162 if ((getControl() is null) || getControl().isDisposed()) {
163 return;
164 }
165 checkSelection(); // see explanation below
166 checkDeleteable();
167 checkSelectable();
168 }
169 });
170 text.addTraverseListener(new class TraverseListener {
171 public void keyTraversed(TraverseEvent e) {
172 if (e.detail is DWT.TRAVERSE_ESCAPE
173 || e.detail is DWT.TRAVERSE_RETURN) {
174 e.doit = false;
175 }
176 }
177 });
178 // We really want a selection listener but it is not supported so we
179 // use a key listener and a mouse listener to know when selection changes
180 // may have occurred
181 text.addMouseListener(new class MouseAdapter {
182 public void mouseUp(MouseEvent e) {
183 checkSelection();
184 checkDeleteable();
185 checkSelectable();
186 }
187 });
188 text.addFocusListener(new class FocusAdapter {
189 public void focusLost(FocusEvent e) {
190 this.outer.focusLost();
191 }
192 });
193 text.setFont(parent.getFont());
194 text.setBackground(parent.getBackground());
195 text.setText("");//$NON-NLS-1$
196 text.addModifyListener(getModifyListener());
197 return text;
198 }
199
200 /**
201 * The <code>TextCellEditor</code> implementation of
202 * this <code>CellEditor</code> framework method returns
203 * the text string.
204 *
205 * @return the text string
206 */
207 protected Object doGetValue() {
208 return new ArrayWrapperString(text.getText());
209 }
210
211 /* (non-Javadoc)
212 * Method declared on CellEditor.
213 */
214 protected void doSetFocus() {
215 if (text !is null) {
216 text.selectAll();
217 text.setFocus();
218 checkSelection();
219 checkDeleteable();
220 checkSelectable();
221 }
222 }
223
224 /**
225 * The <code>TextCellEditor</code> implementation of
226 * this <code>CellEditor</code> framework method accepts
227 * a text string (type <code>String</code>).
228 *
229 * @param value a text string (type <code>String</code>)
230 */
231 protected void doSetValue(Object value) {
232 Assert.isTrue(text !is null && ( cast(ArrayWrapperString)value ));
233 text.removeModifyListener(getModifyListener());
234 text.setText((cast(ArrayWrapperString)value).array);
235 text.addModifyListener(getModifyListener());
236 }
237
238 /**
239 * Processes a modify event that occurred in this text cell editor.
240 * This framework method performs validation and sets the error message
241 * accordingly, and then reports a change via <code>fireEditorValueChanged</code>.
242 * Subclasses should call this method at appropriate times. Subclasses
243 * may extend or reimplement.
244 *
245 * @param e the DWT modify event
246 */
247 protected void editOccured(ModifyEvent e) {
248 String value = text.getText();
249 if (value is null) {
250 value = "";//$NON-NLS-1$
251 }
252 Object typedValue = new ArrayWrapperString(value);
253 bool oldValidState = isValueValid();
254 bool newValidState = isCorrect(typedValue);
255 if (typedValue is null && newValidState) {
256 Assert.isTrue(false,
257 "Validator isn't limiting the cell editor's type range");//$NON-NLS-1$
258 }
259 if (!newValidState) {
260 // try to insert the current value into the error message.
261 setErrorMessage(Format(getErrorMessage(), value ));
262 }
263 valueChanged(oldValidState, newValidState);
264 }
265
266 /**
267 * Since a text editor field is scrollable we don't
268 * set a minimumSize.
269 */
270 public LayoutData getLayoutData() {
271 return new LayoutData();
272 }
273
274 /**
275 * Return the modify listener.
276 */
277 private ModifyListener getModifyListener() {
278 if (modifyListener is null) {
279 modifyListener = new class ModifyListener {
280 public void modifyText(ModifyEvent e) {
281 editOccured(e);
282 }
283 };
284 }
285 return modifyListener;
286 }
287
288 /**
289 * Handles a default selection event from the text control by applying the editor
290 * value and deactivating this cell editor.
291 *
292 * @param event the selection event
293 *
294 * @since 3.0
295 */
296 protected void handleDefaultSelection(SelectionEvent event) {
297 // same with enter-key handling code in keyReleaseOccured(e);
298 fireApplyEditorValue();
299 deactivate();
300 }
301
302 /**
303 * The <code>TextCellEditor</code> implementation of this
304 * <code>CellEditor</code> method returns <code>true</code> if
305 * the current selection is not empty.
306 */
307 public bool isCopyEnabled() {
308 if (text is null || text.isDisposed()) {
309 return false;
310 }
311 return text.getSelectionCount() > 0;
312 }
313
314 /**
315 * The <code>TextCellEditor</code> implementation of this
316 * <code>CellEditor</code> method returns <code>true</code> if
317 * the current selection is not empty.
318 */
319 public bool isCutEnabled() {
320 if (text is null || text.isDisposed()) {
321 return false;
322 }
323 return text.getSelectionCount() > 0;
324 }
325
326 /**
327 * The <code>TextCellEditor</code> implementation of this
328 * <code>CellEditor</code> method returns <code>true</code>
329 * if there is a selection or if the caret is not positioned
330 * at the end of the text.
331 */
332 public bool isDeleteEnabled() {
333 if (text is null || text.isDisposed()) {
334 return false;
335 }
336 return text.getSelectionCount() > 0
337 || text.getCaretPosition() < text.getCharCount();
338 }
339
340 /**
341 * The <code>TextCellEditor</code> implementation of this
342 * <code>CellEditor</code> method always returns <code>true</code>.
343 */
344 public bool isPasteEnabled() {
345 if (text is null || text.isDisposed()) {
346 return false;
347 }
348 return true;
349 }
350
351 /**
352 * Check if save all is enabled
353 * @return true if it is
354 */
355 public bool isSaveAllEnabled() {
356 if (text is null || text.isDisposed()) {
357 return false;
358 }
359 return true;
360 }
361
362 /**
363 * Returns <code>true</code> if this cell editor is
364 * able to perform the select all action.
365 * <p>
366 * This default implementation always returns
367 * <code>false</code>.
368 * </p>
369 * <p>
370 * Subclasses may override
371 * </p>
372 * @return <code>true</code> if select all is possible,
373 * <code>false</code> otherwise
374 */
375 public bool isSelectAllEnabled() {
376 if (text is null || text.isDisposed()) {
377 return false;
378 }
379 return text.getCharCount() > 0;
380 }
381
382 /**
383 * Processes a key release event that occurred in this cell editor.
384 * <p>
385 * The <code>TextCellEditor</code> implementation of this framework method
386 * ignores when the RETURN key is pressed since this is handled in
387 * <code>handleDefaultSelection</code>.
388 * An exception is made for Ctrl+Enter for multi-line texts, since
389 * a default selection event is not sent in this case.
390 * </p>
391 *
392 * @param keyEvent the key event
393 */
394 protected void keyReleaseOccured(KeyEvent keyEvent) {
395 if (keyEvent.character is '\r') { // Return key
396 // Enter is handled in handleDefaultSelection.
397 // Do not apply the editor value in response to an Enter key event
398 // since this can be received from the IME when the intent is -not-
399 // to apply the value.
400 // See bug 39074 [CellEditors] [DBCS] canna input mode fires bogus event from Text Control
401 //
402 // An exception is made for Ctrl+Enter for multi-line texts, since
403 // a default selection event is not sent in this case.
404 if (text !is null && !text.isDisposed()
405 && (text.getStyle() & DWT.MULTI) !is 0) {
406 if ((keyEvent.stateMask & DWT.CTRL) !is 0) {
407 super.keyReleaseOccured(keyEvent);
408 }
409 }
410 return;
411 }
412 super.keyReleaseOccured(keyEvent);
413 }
414
415 /**
416 * The <code>TextCellEditor</code> implementation of this
417 * <code>CellEditor</code> method copies the
418 * current selection to the clipboard.
419 */
420 public void performCopy() {
421 text.copy();
422 }
423
424 /**
425 * The <code>TextCellEditor</code> implementation of this
426 * <code>CellEditor</code> method cuts the
427 * current selection to the clipboard.
428 */
429 public void performCut() {
430 text.cut();
431 checkSelection();
432 checkDeleteable();
433 checkSelectable();
434 }
435
436 /**
437 * The <code>TextCellEditor</code> implementation of this
438 * <code>CellEditor</code> method deletes the
439 * current selection or, if there is no selection,
440 * the character next character from the current position.
441 */
442 public void performDelete() {
443 if (text.getSelectionCount() > 0) {
444 // remove the contents of the current selection
445 text.insert(""); //$NON-NLS-1$
446 } else {
447 // remove the next character
448 int pos = text.getCaretPosition();
449 if (pos < text.getCharCount()) {
450 text.setSelection(pos, pos + 1);
451 text.insert(""); //$NON-NLS-1$
452 }
453 }
454 checkSelection();
455 checkDeleteable();
456 checkSelectable();
457 }
458
459 /**
460 * The <code>TextCellEditor</code> implementation of this
461 * <code>CellEditor</code> method pastes the
462 * the clipboard contents over the current selection.
463 */
464 public void performPaste() {
465 text.paste();
466 checkSelection();
467 checkDeleteable();
468 checkSelectable();
469 }
470
471 /**
472 * The <code>TextCellEditor</code> implementation of this
473 * <code>CellEditor</code> method selects all of the
474 * current text.
475 */
476 public void performSelectAll() {
477 text.selectAll();
478 checkSelection();
479 checkDeleteable();
480 }
481
482 bool dependsOnExternalFocusListener() {
483 return this.classinfo !is TextCellEditor.classinfo;
484 }
485 }