Mercurial > projects > dwt-addons
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 } |