comparison org.eclipse.jface/src/org/eclipse/jface/preference/StringFieldEditor.d @ 12:bc29606a740c

Added dwt-addons in original directory structure of eclipse.org
author Frank Benoit <benoit@tionex.de>
date Sat, 14 Mar 2009 18:23:29 +0100
parents
children
comparison
equal deleted inserted replaced
11:43904fec5dca 12:bc29606a740c
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 module org.eclipse.jface.preference.StringFieldEditor;
14
15 import org.eclipse.jface.preference.FieldEditor;
16
17 import org.eclipse.swt.SWT;
18 import org.eclipse.swt.events.DisposeEvent;
19 import org.eclipse.swt.events.DisposeListener;
20 import org.eclipse.swt.events.FocusAdapter;
21 import org.eclipse.swt.events.FocusEvent;
22 import org.eclipse.swt.events.KeyAdapter;
23 import org.eclipse.swt.events.KeyEvent;
24 import org.eclipse.swt.graphics.GC;
25 import org.eclipse.swt.graphics.Point;
26 import org.eclipse.swt.layout.GridData;
27 import org.eclipse.swt.widgets.Composite;
28 import org.eclipse.swt.widgets.Text;
29 import org.eclipse.core.runtime.Assert;
30 import org.eclipse.jface.resource.JFaceResources;
31
32 import java.lang.all;
33 import java.util.Set;
34
35 /**
36 * A field editor for a string type preference.
37 * <p>
38 * This class may be used as is, or subclassed as required.
39 * </p>
40 */
41 public class StringFieldEditor : FieldEditor {
42
43 alias FieldEditor.showErrorMessage showErrorMessage;
44 /**
45 * Validation strategy constant (value <code>0</code>) indicating that
46 * the editor should perform validation after every key stroke.
47 *
48 * @see #setValidateStrategy
49 */
50 public static const int VALIDATE_ON_KEY_STROKE = 0;
51
52 /**
53 * Validation strategy constant (value <code>1</code>) indicating that
54 * the editor should perform validation only when the text widget
55 * loses focus.
56 *
57 * @see #setValidateStrategy
58 */
59 public static const int VALIDATE_ON_FOCUS_LOST = 1;
60
61 /**
62 * Text limit constant (value <code>-1</code>) indicating unlimited
63 * text limit and width.
64 */
65 public static int UNLIMITED = -1;
66
67 /**
68 * Cached valid state.
69 */
70 private bool isValid_;
71
72 /**
73 * Old text value.
74 * @since 3.4 this field is protected.
75 */
76 protected String oldValue;
77
78 /**
79 * The text field, or <code>null</code> if none.
80 */
81 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 /**
111 * Creates a new string field editor
112 */
113 protected this() {
114 widthInChars = UNLIMITED;
115 textLimit = UNLIMITED;
116 validateStrategy = VALIDATE_ON_KEY_STROKE;
117 }
118
119 /**
120 * Creates a string field editor.
121 * Use the method <code>setTextLimit</code> to limit the text.
122 *
123 * @param name the name of the preference this field editor works on
124 * @param labelText the label text of the field editor
125 * @param width the width of the text input field in characters,
126 * or <code>UNLIMITED</code> for no limit
127 * @param strategy either <code>VALIDATE_ON_KEY_STROKE</code> to perform
128 * on the fly checking (the default), or <code>VALIDATE_ON_FOCUS_LOST</code> to
129 * perform validation only after the text has been typed in
130 * @param parent the parent of the field editor's control
131 * @since 2.0
132 */
133 public this(String name, String labelText, int width,
134 int strategy, Composite parent) {
135 this();
136 init(name, labelText);
137 widthInChars = width;
138 setValidateStrategy(strategy);
139 isValid_ = false;
140 errorMessage = JFaceResources
141 .getString("StringFieldEditor.errorMessage");//$NON-NLS-1$
142 createControl(parent);
143 }
144
145 /**
146 * Creates a string field editor.
147 * Use the method <code>setTextLimit</code> to limit the text.
148 *
149 * @param name the name of the preference this field editor works on
150 * @param labelText the label text of the field editor
151 * @param width the width of the text input field in characters,
152 * or <code>UNLIMITED</code> for no limit
153 * @param parent the parent of the field editor's control
154 */
155 public this(String name, String labelText, int width,
156 Composite parent) {
157 this(name, labelText, width, VALIDATE_ON_KEY_STROKE, parent);
158 }
159
160 /**
161 * Creates a string field editor of unlimited width.
162 * Use the method <code>setTextLimit</code> to limit the text.
163 *
164 * @param name the name of the preference this field editor works on
165 * @param labelText the label text of the field editor
166 * @param parent the parent of the field editor's control
167 */
168 public this(String name, String labelText, Composite parent) {
169 this(name, labelText, UNLIMITED, parent);
170 }
171
172 /* (non-Javadoc)
173 * Method declared on FieldEditor.
174 */
175 protected override void adjustForNumColumns(int numColumns) {
176 GridData gd = cast(GridData) textField.getLayoutData();
177 gd.horizontalSpan = numColumns - 1;
178 // We only grab excess space if we have to
179 // If another field editor has more columns then
180 // we assume it is setting the width.
181 gd.grabExcessHorizontalSpace = gd.horizontalSpan is 1;
182 }
183
184 /**
185 * Checks whether the text input field contains a valid value or not.
186 *
187 * @return <code>true</code> if the field value is valid,
188 * and <code>false</code> if invalid
189 */
190 protected bool checkState() {
191 bool result = false;
192 if (emptyStringAllowed) {
193 result = true;
194 }
195
196 if (textField is null) {
197 result = false;
198 }
199
200 String txt = textField.getText();
201
202 result = (txt.trim().length > 0) || emptyStringAllowed;
203
204 // call hook for subclasses
205 result = result && doCheckState();
206
207 if (result) {
208 clearErrorMessage();
209 } else {
210 showErrorMessage(errorMessage);
211 }
212
213 return result;
214 }
215
216 /**
217 * Hook for subclasses to do specific state checks.
218 * <p>
219 * The default implementation of this framework method does
220 * nothing and returns <code>true</code>. Subclasses should
221 * override this method to specific state checks.
222 * </p>
223 *
224 * @return <code>true</code> if the field value is valid,
225 * and <code>false</code> if invalid
226 */
227 protected bool doCheckState() {
228 return true;
229 }
230
231 /**
232 * Fills this field editor's basic controls into the given parent.
233 * <p>
234 * The string field implementation of this <code>FieldEditor</code>
235 * framework method contributes the text field. Subclasses may override
236 * but must call <code>super.doFillIntoGrid</code>.
237 * </p>
238 */
239 protected override void doFillIntoGrid(Composite parent, int numColumns) {
240 getLabelControl(parent);
241
242 textField = getTextControl(parent);
243 GridData gd = new GridData();
244 gd.horizontalSpan = numColumns - 1;
245 if (widthInChars !is UNLIMITED) {
246 GC gc = new GC(textField);
247 try {
248 Point extent = gc.textExtent("X");//$NON-NLS-1$
249 gd.widthHint = widthInChars * extent.x;
250 } finally {
251 gc.dispose();
252 }
253 } else {
254 gd.horizontalAlignment = GridData.FILL;
255 gd.grabExcessHorizontalSpace = true;
256 }
257 textField.setLayoutData(gd);
258 }
259
260 /* (non-Javadoc)
261 * Method declared on FieldEditor.
262 */
263 protected override void doLoad() {
264 if (textField !is null) {
265 String value = getPreferenceStore().getString(getPreferenceName());
266 textField.setText(value);
267 oldValue = value;
268 }
269 }
270
271 /* (non-Javadoc)
272 * Method declared on FieldEditor.
273 */
274 protected override void doLoadDefault() {
275 if (textField !is null) {
276 String value = getPreferenceStore().getDefaultString(
277 getPreferenceName());
278 textField.setText(value);
279 }
280 valueChanged();
281 }
282
283 /* (non-Javadoc)
284 * Method declared on FieldEditor.
285 */
286 protected override void doStore() {
287 getPreferenceStore().setValue(getPreferenceName(), textField.getText());
288 }
289
290 /**
291 * Returns the error message that will be displayed when and if
292 * an error occurs.
293 *
294 * @return the error message, or <code>null</code> if none
295 */
296 public String getErrorMessage() {
297 return errorMessage;
298 }
299
300 /* (non-Javadoc)
301 * Method declared on FieldEditor.
302 */
303 public override int getNumberOfControls() {
304 return 2;
305 }
306
307 /**
308 * Returns the field editor's value.
309 *
310 * @return the current value
311 */
312 public String getStringValue() {
313 if (textField !is null) {
314 return textField.getText();
315 }
316
317 return getPreferenceStore().getString(getPreferenceName());
318 }
319
320 /**
321 * Returns this field editor's text control.
322 *
323 * @return the text control, or <code>null</code> if no
324 * text field is created yet
325 */
326 protected Text getTextControl() {
327 return textField;
328 }
329
330 /**
331 * Returns this field editor's text control.
332 * <p>
333 * The control is created if it does not yet exist
334 * </p>
335 *
336 * @param parent the parent
337 * @return the text control
338 */
339 public Text getTextControl(Composite parent) {
340 if (textField is null) {
341 textField = new Text(parent, SWT.SINGLE | SWT.BORDER);
342 textField.setFont(parent.getFont());
343 switch (validateStrategy) {
344 case VALIDATE_ON_KEY_STROKE:
345 textField.addKeyListener(new class KeyAdapter {
346
347 /* (non-Javadoc)
348 * @see org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.KeyEvent)
349 */
350 public void keyReleased(KeyEvent e) {
351 valueChanged();
352 }
353 });
354
355 break;
356 case VALIDATE_ON_FOCUS_LOST:
357 textField.addKeyListener(new class KeyAdapter {
358 public void keyPressed(KeyEvent e) {
359 clearErrorMessage();
360 }
361 });
362 textField.addFocusListener(new class FocusAdapter {
363 public void focusGained(FocusEvent e) {
364 refreshValidState();
365 }
366
367 public void focusLost(FocusEvent e) {
368 valueChanged();
369 clearErrorMessage();
370 }
371 });
372 break;
373 default:
374 Assert.isTrue(false, "Unknown validate strategy");//$NON-NLS-1$
375 }
376 textField.addDisposeListener(new class DisposeListener {
377 public void widgetDisposed(DisposeEvent event) {
378 textField = null;
379 }
380 });
381 if (textLimit > 0) {//Only set limits above 0 - see SWT spec
382 textField.setTextLimit(textLimit);
383 }
384 } else {
385 checkParent(textField, parent);
386 }
387 return textField;
388 }
389
390 /**
391 * Returns whether an empty string is a valid value.
392 *
393 * @return <code>true</code> if an empty string is a valid value, and
394 * <code>false</code> if an empty string is invalid
395 * @see #setEmptyStringAllowed
396 */
397 public bool isEmptyStringAllowed() {
398 return emptyStringAllowed;
399 }
400
401 /* (non-Javadoc)
402 * Method declared on FieldEditor.
403 */
404 public override bool isValid() {
405 return isValid_;
406 }
407
408 /* (non-Javadoc)
409 * Method declared on FieldEditor.
410 */
411 protected override void refreshValidState() {
412 isValid_ = checkState();
413 }
414
415 /**
416 * Sets whether the empty string is a valid value or not.
417 *
418 * @param b <code>true</code> if the empty string is allowed,
419 * and <code>false</code> if it is considered invalid
420 */
421 public void setEmptyStringAllowed(bool b) {
422 emptyStringAllowed = b;
423 }
424
425 /**
426 * Sets the error message that will be displayed when and if
427 * an error occurs.
428 *
429 * @param message the error message
430 */
431 public void setErrorMessage(String message) {
432 errorMessage = message;
433 }
434
435 /* (non-Javadoc)
436 * Method declared on FieldEditor.
437 */
438 public override void setFocus() {
439 if (textField !is null) {
440 textField.setFocus();
441 }
442 }
443
444 /**
445 * Sets this field editor's value.
446 *
447 * @param value the new value, or <code>null</code> meaning the empty string
448 */
449 public void setStringValue(String value) {
450 if (textField !is null) {
451 if (value is null) {
452 value = "";//$NON-NLS-1$
453 }
454 oldValue = textField.getText();
455 if (!oldValue.equals(value)) {
456 textField.setText(value);
457 valueChanged();
458 }
459 }
460 }
461
462 /**
463 * Sets this text field's text limit.
464 *
465 * @param limit the limit on the number of character in the text
466 * input field, or <code>UNLIMITED</code> for no limit
467
468 */
469 public void setTextLimit(int limit) {
470 textLimit = limit;
471 if (textField !is null) {
472 textField.setTextLimit(limit);
473 }
474 }
475
476 /**
477 * Sets the strategy for validating the text.
478 * <p>
479 * Calling this method has no effect after <code>createPartControl</code>
480 * is called. Thus this method is really only useful for subclasses to call
481 * in their constructor. However, it has public visibility for backward
482 * compatibility.
483 * </p>
484 *
485 * @param value either <code>VALIDATE_ON_KEY_STROKE</code> to perform
486 * on the fly checking (the default), or <code>VALIDATE_ON_FOCUS_LOST</code> to
487 * perform validation only after the text has been typed in
488 */
489 public void setValidateStrategy(int value) {
490 Assert.isTrue(value is VALIDATE_ON_FOCUS_LOST
491 || value is VALIDATE_ON_KEY_STROKE);
492 validateStrategy = value;
493 }
494
495 /**
496 * Shows the error message set via <code>setErrorMessage</code>.
497 */
498 public void showErrorMessage() {
499 showErrorMessage(errorMessage);
500 }
501
502 /**
503 * Informs this field editor's listener, if it has one, about a change
504 * to the value (<code>VALUE</code> property) provided that the old and
505 * new values are different.
506 * <p>
507 * This hook is <em>not</em> called when the text is initialized
508 * (or reset to the default value) from the preference store.
509 * </p>
510 */
511 protected void valueChanged() {
512 setPresentsDefaultValue(false);
513 bool oldState = isValid_;
514 refreshValidState();
515
516 if (isValid_ !is oldState) {
517 fireStateChanged(IS_VALID, oldState, isValid_);
518 }
519
520 String newValue = textField.getText();
521 if (!newValue.equals(oldValue)) {
522 fireValueChanged(VALUE, stringcast(oldValue), stringcast(newValue));
523 oldValue = newValue;
524 }
525 }
526
527 /*
528 * @see FieldEditor.setEnabled(bool,Composite).
529 */
530 public override void setEnabled(bool enabled, Composite parent) {
531 super.setEnabled(enabled, parent);
532 getTextControl(parent).setEnabled(enabled);
533 }
534 }