comparison dwtx/cdt/managedbuilder/ui/properties/MultiLineTextFieldEditor.d @ 110:a26bb7394581

Add two field editor from the CDT project, thanks yidabu for the port.
author Frank Benoit <benoit@tionex.de>
date Thu, 07 Aug 2008 17:37:04 +0200
parents
children
comparison
equal deleted inserted replaced
106:8ab6fb387666 110:a26bb7394581
1 /**********************************************************************
2 * Copyright (c) 2004 BitMethods Inc and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
7 *
8 * Contributors:
9 * BitMethods Inc - Initial API and implementation
10 * Ported to the D programming language
11 * yidabu ( D Programming Language China : http://www.d-programming-language-china.org/ )
12 ***********************************************************************/
13 module dwtx.cdt.managedbuilder.ui.properties.MultiLineTextFieldEditor;
14
15 //import org.eclipse.cdt.managedbuilder.internal.ui.ManagedBuilderUIMessages;
16 import dwtx.jface.preference.FieldEditor;
17 import dwtx.jface.util.Assert;
18 import dwt.DWT;
19 import dwt.events.DisposeEvent;
20 import dwt.events.DisposeListener;
21 import dwt.events.FocusAdapter;
22 import dwt.events.FocusEvent;
23 import dwt.events.KeyAdapter;
24 import dwt.events.KeyEvent;
25 import dwt.layout.GridData;
26 import dwt.widgets.Composite;
27 import dwt.widgets.Label;
28 import dwt.widgets.Text;
29
30 import dwt.dwthelper.utils;
31
32 /**
33 * MultiLineTextFieldEditor.
34 * Field editor that is same as string field editor but
35 * will have the multi line text field for user input.
36 */
37 public class MultiLineTextFieldEditor : FieldEditor {
38
39 alias FieldEditor.showErrorMessage showErrorMessage;
40 private static final String ERROR_MESSAGE = "Multiline.error.message"; //$NON-NLS-1$
41 private static final String ERROR_MESSAGE_CONST = "Please give correct input"; //$NON-NLS-1$
42
43 /**
44 * Validation strategy constant (value <code>0</code>) indicating that
45 * the editor should perform validation after every key stroke.
46 *
47 * @see #setValidateStrategy
48 */
49 public static const int VALIDATE_ON_KEY_STROKE = 0;
50
51 /**
52 * Validation strategy constant (value <code>1</code>) indicating that
53 * the editor should perform validation only when the text widget
54 * loses focus.
55 *
56 * @see #setValidateStrategy
57 */
58 public static const int VALIDATE_ON_FOCUS_LOST = 1;
59
60 /**
61 * Text limit constant (value <code>-1</code>) indicating unlimited
62 * text limit and width.
63 */
64 public static int UNLIMITED = -1;
65
66 /**
67 * Cached valid state.
68 */
69 private bool isValid_;
70
71 /**
72 * Old text value.
73 */
74 private String oldValue;
75 private String compTitle;
76 private Label title;
77
78 /**
79 * The text field, or <code>null</code> if none.
80 */
81 private Text textField;
82
83 /**
84 * Width of text field in characters; initially unlimited.
85 */
86 private int widthInChars;
87
88 /**
89 * Text limit of text field in characters; initially unlimited.
90 */
91 private int textLimit;
92
93 /**
94 * The error message, or <code>null</code> if none.
95 */
96 private String errorMessage;
97
98 /**
99 * Indicates whether the empty string is legal;
100 * <code>true</code> by default.
101 */
102 private bool emptyStringAllowed = true;
103
104 /**
105 * The validation strategy;
106 * <code>VALIDATE_ON_KEY_STROKE</code> by default.
107 */
108 private int validateStrategy;
109 /**
110 * Creates a new string field editor
111 */
112 protected this() {
113 widthInChars = UNLIMITED;
114 textLimit = UNLIMITED;
115 validateStrategy = VALIDATE_ON_KEY_STROKE;
116 }
117 /**
118 * Creates a string field editor.
119 * Use the method <code>setTextLimit</code> to limit the text.
120 *
121 * @param name the name of the preference this field editor works on
122 * @param labelText the label text of the field editor
123 * @param width the width of the text input field in characters,
124 * or <code>UNLIMITED</code> for no limit
125 * @param strategy either <code>VALIDATE_ON_KEY_STROKE</code> to perform
126 * on the fly checking (the default), or <code>VALIDATE_ON_FOCUS_LOST</code> to
127 * perform validation only after the text has been typed in
128 * @param parent the parent of the field editor's control
129 * @since 2.0
130 */
131 public this(
132 String name,
133 String labelText,
134 int width,
135 int strategy,
136 Composite parent) {
137 this();
138 init(name, labelText);
139 widthInChars = width;
140 setValidateStrategy(strategy);
141 isValid_ = false;
142 //errorMessage = ManagedBuilderUIMessages.getResourceString(ERROR_MESSAGE);
143 errorMessage = ERROR_MESSAGE_CONST;
144 createControl(parent);
145 }
146
147 /**
148 * Creates a string field editor.
149 * Use the method <code>setTextLimit</code> to limit the text.
150 *
151 * @param name the name of the preference this field editor works on
152 * @param labelText the label text of the field editor
153 * @param width the width of the text input field in characters,
154 * or <code>UNLIMITED</code> for no limit
155 * @param parent the parent of the field editor's control
156 */
157 public this(String name, String labelText, int width, Composite parent) {
158 this(name, labelText, width, VALIDATE_ON_KEY_STROKE, parent);
159 this.compTitle = labelText;
160 }
161 /**
162 * Creates a string field editor of unlimited width.
163 * Use the method <code>setTextLimit</code> to limit the text.
164 *
165 * @param name the name of the preference this field editor works on
166 * @param labelText the label text of the field editor
167 * @param parent the parent of the field editor's control
168 */
169 public this(String name, String labelText, Composite parent) {
170 this(name, labelText, UNLIMITED, parent);
171 }
172
173 /**
174 * Adjusts the horizontal span of this field editor's basic controls
175 * <p>
176 * Subclasses must implement this method to adjust the horizontal span
177 * of controls so they appear correct in the given number of columns.
178 * </p>
179 * <p>
180 * The number of columns will always be equal to or greater than the
181 * value returned by this editor's <code>getNumberOfControls</code> method.
182 *
183 * @param numColumns the number of columns
184 */
185 protected void adjustForNumColumns(int numColumns) {
186 GridData gd = cast(GridData) textField.getLayoutData();
187 gd.horizontalSpan = numColumns - 1;
188 // We only grab excess space if we have to
189 // If another field editor has more columns then
190 // we assume it is setting the width.
191 gd.grabExcessHorizontalSpace = gd.horizontalSpan == 1;
192 }
193 /**
194 * Checks whether the text input field contains a valid value or not.
195 *
196 * @return <code>true</code> if the field value is valid,
197 * and <code>false</code> if invalid
198 */
199 protected bool checkState() {
200 bool result = false;
201 if (emptyStringAllowed)
202 result = true;
203
204 if (textField is null)
205 result = false;
206
207 String txt = textField.getText();
208
209 if (txt is null)
210 result = false;
211
212 result = (txt.trim().length > 0) || emptyStringAllowed;
213
214 // call hook for subclasses
215 result = result && doCheckState();
216
217 if (result)
218 clearErrorMessage();
219 else
220 showErrorMessage(errorMessage);
221
222 return result;
223 }
224 /**
225 * Hook for subclasses to do specific state checks.
226 * <p>
227 * The default implementation of this framework method does
228 * nothing and returns <code>true</code>. Subclasses should
229 * override this method to specific state checks.
230 * </p>
231 *
232 * @return <code>true</code> if the field value is valid,
233 * and <code>false</code> if invalid
234 */
235 protected bool doCheckState() {
236 return true;
237 }
238 /**
239 * Fills this field editor's basic controls into the given parent.
240 * <p>
241 * The string field implementation of this <code>FieldEditor</code>
242 * framework method contributes the text field. Subclasses may override
243 * but must call <code>super.doFillIntoGrid</code>.
244 * </p>
245 */
246 protected void doFillIntoGrid(Composite parent, int numColumns) {
247
248 title = new Label(parent, DWT.UP);
249 title.setFont(parent.getFont());
250 this.compTitle = getLabelText();
251 title.setText(this.compTitle);
252 title.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
253
254 textField = getTextControl(parent);
255 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
256 gd.widthHint = 100;
257 gd.heightHint = 70;
258 textField.setLayoutData(gd);
259
260 }
261
262 /**
263 * Initializes this field editor with the preference value from
264 * the preference store.
265 * <p>
266 * Subclasses must implement this method to properly initialize
267 * the field editor.
268 * </p>
269 */
270 protected void doLoad() {
271 if (textField !is null) {
272 String value = getPreferenceStore().getString(getPreferenceName());
273 textField.setText(value);
274 oldValue = value;
275 }
276 }
277
278 /**
279 * Initializes this field editor with the default preference value from
280 * the preference store.
281 * <p>
282 * Subclasses must implement this method to properly initialize
283 * the field editor.
284 * </p>
285 */
286 protected void doLoadDefault() {
287 if (textField !is null) {
288 String value =
289 getPreferenceStore().getDefaultString(getPreferenceName());
290 textField.setText(value);
291 }
292 valueChanged();
293 }
294
295 /* (non-Javadoc)
296 * @see dwtx.jface.preference.FieldEditor#doStore()
297 */
298 protected void doStore() {
299 getPreferenceStore().setValue(getPreferenceName(), textField.getText());
300 }
301
302 /**
303 * Returns the error message that will be displayed when and if
304 * an error occurs.
305 *
306 * @return the error message, or <code>null</code> if none
307 */
308 public String getErrorMessage() {
309 return errorMessage;
310 }
311 /**
312 * Returns the number of basic controls this field editor consists of.
313 *
314 * @return the number of controls
315 */
316 public int getNumberOfControls() {
317 return 2;
318 }
319 /**
320 * Returns the field editor's value.
321 *
322 * @return the current value
323 */
324 public String getStringValue() {
325 if (textField !is null)
326 return textField.getText();
327 else
328 return getPreferenceStore().getString(getPreferenceName());
329 }
330
331 /**
332 * Returns this field editor's text control.
333 *
334 * @param parent the parent
335 * @return the text control, or <code>null</code> if no
336 * text field is created yet
337 */
338 protected Text getTextControl() {
339 return textField;
340 }
341
342 /**
343 * Returns this field editor's text control.
344 * <p>
345 * The control is created if it does not yet exist
346 * </p>
347 *
348 * @param parent the parent
349 * @return the text control
350 */
351 public Text getTextControl(Composite parent) {
352 if (textField is null) {
353 textField =
354 new Text(
355 parent,
356 DWT.MULTI | DWT.V_SCROLL | DWT.BORDER | DWT.WRAP);
357 textField.setFont(parent.getFont());
358 switch (validateStrategy) {
359 case VALIDATE_ON_KEY_STROKE :
360 textField.addKeyListener(new class() KeyAdapter {
361 public void keyPressed(KeyEvent e) {
362 valueChanged();
363 }
364 });
365
366 textField.addFocusListener(new class() FocusAdapter {
367 public void focusGained(FocusEvent e) {
368 refreshValidState();
369 }
370 public void focusLost(FocusEvent e) {
371 clearErrorMessage();
372 }
373 });
374 break;
375 case VALIDATE_ON_FOCUS_LOST :
376 textField.addKeyListener(new class() KeyAdapter {
377 public void keyPressed(KeyEvent e) {
378 clearErrorMessage();
379 }
380 });
381 textField.addFocusListener(new class() FocusAdapter {
382 public void focusGained(FocusEvent e) {
383 refreshValidState();
384 }
385 public void focusLost(FocusEvent e) {
386 valueChanged();
387 clearErrorMessage();
388 }
389 });
390 break;
391 default :
392 Assert.isTrue(false, "Unknown validate strategy"); //$NON-NLS-1$
393 }
394 textField.addDisposeListener(new class() DisposeListener {
395 public void widgetDisposed(DisposeEvent event) {
396 textField = null;
397 }
398 });
399 if (textLimit > 0) { //Only set limits above 0 - see SWT spec
400 textField.setTextLimit(textLimit);
401 }
402 } else {
403 checkParent(textField, parent);
404 }
405 return textField;
406 }
407
408 /**
409 * Returns whether an empty string is a valid value.
410 *
411 * @return <code>true</code> if an empty string is a valid value, and
412 * <code>false</code> if an empty string is invalid
413 * @see #setEmptyStringAllowed
414 */
415 public bool isEmptyStringAllowed() {
416 return emptyStringAllowed;
417 }
418
419 /**
420 * Returns whether this field editor contains a valid value.
421 * <p>
422 * The default implementation of this framework method
423 * returns <code>true</code>. Subclasses wishing to perform
424 * validation should override both this method and
425 * <code>refreshValidState</code>.
426 * </p>
427 *
428 * @return <code>true</code> if the field value is valid,
429 * and <code>false</code> if invalid
430 * @see #refreshValidState
431 */
432 public bool isValid() {
433 return isValid_;
434 }
435
436 /**
437 * Refreshes this field editor's valid state after a value change
438 * and fires an <code>IS_VALID</code> property change event if
439 * warranted.
440 * <p>
441 * The default implementation of this framework method does
442 * nothing. Subclasses wishing to perform validation should override
443 * both this method and <code>isValid_</code>.
444 * </p>
445 * @see #isValid_
446 */
447 protected void refreshValidState() {
448 isValid_ = checkState();
449 }
450
451 /**
452 * Sets whether the empty string is a valid value or not.
453 *
454 * @param b <code>true</code> if the empty string is allowed,
455 * and <code>false</code> if it is considered invalid
456 */
457 public void setEmptyStringAllowed(bool b) {
458 emptyStringAllowed = b;
459 }
460
461 /**
462 * Sets the error message that will be displayed when and if
463 * an error occurs.
464 *
465 * @param message the error message
466 */
467 public void setErrorMessage(String message) {
468 errorMessage = message;
469 }
470
471 /**
472 * Sets the focus to this field editor.
473 * <p>
474 * The default implementation of this framework method
475 * does nothing. Subclasses may reimplement.
476 * </p>
477 */
478 public void setFocus() {
479 if (textField !is null) {
480 textField.setFocus();
481 }
482 }
483
484 /**
485 * Sets this field editor's value.
486 *
487 * @param value the new value, or <code>null</code> meaning the empty string
488 */
489 public void setStringValue(String value) {
490 if (textField !is null) {
491 if (value is null)
492 value = ""; //$NON-NLS-1$
493 oldValue = textField.getText();
494 if (!oldValue.equals(value)) {
495 textField.setText(value);
496 valueChanged();
497 }
498 }
499 }
500
501 /**
502 * Sets this text field's text limit.
503 *
504 * @param limit the limit on the number of character in the text
505 * input field, or <code>UNLIMITED</code> for no limit
506 */
507 public void setTextLimit(int limit) {
508 textLimit = limit;
509 if (textField !is null)
510 textField.setTextLimit(limit);
511 }
512
513 /**
514 * Sets the strategy for validating the text.
515 * <p>
516 * Calling this method has no effect after <code>createPartControl</code>
517 * is called. Thus this method is really only useful for subclasses to call
518 * in their constructor. However, it has public visibility for backward
519 * compatibility.
520 * </p>
521 *
522 * @param value either <code>VALIDATE_ON_KEY_STROKE</code> to perform
523 * on the fly checking (the default), or <code>VALIDATE_ON_FOCUS_LOST</code> to
524 * perform validation only after the text has been typed in
525 */
526 public void setValidateStrategy(int value) {
527 Assert.isTrue(
528 value == VALIDATE_ON_FOCUS_LOST || value == VALIDATE_ON_KEY_STROKE);
529 validateStrategy = value;
530 }
531
532 /**
533 * Shows the error message set via <code>setErrorMessage</code>.
534 */
535 public void showErrorMessage() {
536 showErrorMessage(errorMessage);
537 }
538
539 /**
540 * Informs this field editor's listener, if it has one, about a change
541 * to the value (<code>VALUE</code> property) provided that the old and
542 * new values are different.
543 * <p>
544 * This hook is <em>not</em> called when the text is initialized
545 * (or reset to the default value) from the preference store.
546 * </p>
547 */
548 protected void valueChanged() {
549 setPresentsDefaultValue(false);
550 bool oldState = isValid_;
551 refreshValidState();
552
553 if (isValid_ !is oldState)
554 fireStateChanged(IS_VALID, oldState, isValid_);
555
556 String newValue = textField.getText();
557 if (!newValue.equals(oldValue)) {
558 fireValueChanged(VALUE, stringcast(oldValue), stringcast(newValue));
559 oldValue = newValue;
560 }
561 }
562 }