package com.ibm.sai.aspen.core.prefs; /******************************************************************************* * Copyright (c) 2000, 2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ import org.eclipse.jface.preference.FieldEditor; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.util.Assert; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.KeyAdapter; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; /** * A field editor for a string type preference. It has been modified to allow * clients to supply their own validation method(s), examples of which include * the InetAddressFieldEditor and the RegexFieldEditor. *
* This class may be used as is, or subclassed as required. *
*/ public class StringFieldEditor extends FieldEditor { /** * Validation strategy constant (value0
) indicating that
* the editor should perform validation after every key stroke.
*
* @see #setValidateStrategy
*/
public static final int VALIDATE_ON_KEY_STROKE = 0;
/**
* Validation strategy constant (value 1
) indicating that
* the editor should perform validation only when the text widget loses
* focus.
*
* @see #setValidateStrategy
*/
public static final int VALIDATE_ON_FOCUS_LOST = 1;
/**
* Text limit constant (value -1
) indicating unlimited text
* limit and width.
*/
public static int UNLIMITED = -1;
/**
* Creates a new string field editor, unitialized.
* Used by IntegerFieldEditor, but there are integer-fields that do not * create an IntegerFieldEditor, e.g., General -> Workspace -> Local History * and General -> Editors -> Text Editors.
*/ protected StringFieldEditor() { } /** * Creates a string field editor. Use the methodsetTextLimit
* to limit the text.
*
* @param name (String) of the preference this field editor works on
* @param labelText (String) of the field editor
* @param width (int) of the text input field in characters, or
* UNLIMITED
for no limit
* @param strategy (int) either VALIDATE_ON_KEY_STROKE
to
* perform on-the-fly checking (the default), or
* VALIDATE_ON_FOCUS_LOST
to perform validation
* only after the text has been typed in
* @param parent (Composite) of the field editor's control
* @since 2.0
*/
public StringFieldEditor(String name, String labelText, int width,
int strategy, Composite parent) {
init(name, labelText);
widthInChars = width;
setValidateStrategy(strategy);
isValid = false;
errorMessage = JFaceResources.getString("StringFieldEditor.errorMessage");//$NON-NLS-1$
createControl(parent);
}
/**
* Creates a string field editor. Use the method setTextLimit
* to limit the text.
*
* @param name (String) of the preference this field editor works on
* @param labelText (String) of the field editor
* @param width (int) of the text input field in characters, or
* UNLIMITED
for no limit
* @param parent (Composite) of the field editor's control
*/
public StringFieldEditor(String name, String labelText, int width, Composite parent) {
this(name, labelText, width, VALIDATE_ON_KEY_STROKE, parent);
}
/**
* Creates a string field editor of unlimited width.
*
* @param name (String) of the preference this field editor works on
* @param labelText (String) of the field editor
* @param parent (Composite) of the field editor's control
*/
public StringFieldEditor(String name, String labelText, Composite parent) {
this(name, labelText, UNLIMITED, parent);
}
/**
* Returns the error message that will be displayed when and if an error
* occurs.
*
* @return the error message, or null
if none
*/
public String getErrorMessage() {
return errorMessage;
}
/**
* Returns the field editor's value.
*
* @return the current value
*/
public String getStringValue() {
if (textField != null) {
return textField.getText();
}
return getPreferenceStore().getString(getPreferenceName());
}
/**
* Returns this field editor's text control.
* * The control is created if it does not yet exist *
* * @param parent (Composite) * @return the text control */ public Text getTextControl(Composite parent) { if (textField == null) { textField = new Text(parent, SWT.SINGLE | SWT.BORDER); textField.setFont(parent.getFont()); switch (validateStrategy) { case VALIDATE_ON_KEY_STROKE: textField.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent e) { valueChanged(); } }); break; case VALIDATE_ON_FOCUS_LOST: textField.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { clearErrorMessage(); } }); textField.addFocusListener(new FocusAdapter() { public void focusGained(FocusEvent e) { refreshValidState(); } public void focusLost(FocusEvent e) { valueChanged(); clearErrorMessage(); } }); break; default: handleFurtherValidationStrategies(); } textField.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent event) { textField = null; } }); if (textLimit > 0) {// only set limits above 0 - see SWT spec textField.setTextLimit(textLimit); } } else { checkParent(textField, parent); } return textField; } /** * Returns whether an empty string is a valid value. * * @returntrue
if an empty string is a valid value, and
* false
if an empty string is invalid
* @see #setEmptyStringAllowed
*/
public boolean isEmptyStringAllowed() {
return emptyStringAllowed;
}
/**
* Sets whether the empty string is a valid value or not.
*
* @param b
* true
if the empty string is allowed, and
* false
if it is considered invalid
*/
public void setEmptyStringAllowed(boolean b) {
emptyStringAllowed = b;
}
/**
* Sets the error message that will be displayed when and if an error
* occurs.
*
* @param message (String) the error message
*/
public void setErrorMessage(String message) {
errorMessage = message;
}
/**
* Sets this field editor's value.
*
* @param value (String) new value, or null
meaning the empty string
*/
public void setStringValue(String value) {
if (textField != null) {
if (value == null) {
value = "";//$NON-NLS-1$
}
oldValue = textField.getText();
if (!oldValue.equals(value)) {
textField.setText(value);
valueChanged();
}
}
}
/**
* Sets this text field's text limit.
*
* @param limit (int) on the number of characters in the text input field,
* or UNLIMITED
for no limit
*
*/
public void setTextLimit(int limit) {
textLimit = limit;
if (textField != null) {
textField.setTextLimit(limit);
}
}
/**
* Sets the strategy for validating the text.
*
* Calling this method has no effect after createPartControl
* is called. Thus this method is really only useful for subclasses to call
* in their constructor. However, it has public visibility for backward
* compatibility.
*
TODO 151469: Clients that allow other validate-strategies must override this method. *
* * @param value * eitherVALIDATE_ON_KEY_STROKE
to perform on the
* fly checking (the default), or
* VALIDATE_ON_FOCUS_LOST
to perform validation
* only after the text has been typed in, and user has changed
* focus
*/
public void setValidateStrategy(int value) {
Assert.isTrue(value == VALIDATE_ON_FOCUS_LOST
|| value == VALIDATE_ON_KEY_STROKE);
validateStrategy = value;
}
/**
* Shows the error message set via setErrorMessage
.
*/
public void showErrorMessage() {
showErrorMessage(errorMessage);
}
/**
* Checks whether the text input field contains a valid value or not.
*
* @return true
if the field value is valid, and
* false
if invalid
*/
protected boolean checkState() {
boolean result = false;
if (emptyStringAllowed) {
result = true;
}
if (textField == null) {
result = false;
}
String txt = textField.getText();
result = (txt.trim().length() > 0) || emptyStringAllowed;
// call hook for subclasses
result = result && doCheckState();
if (result) {
clearErrorMessage();
} else {
showErrorMessage(errorMessage);
}
return result;
}
/**
* Hook for subclasses to do specific state checks.
*
* The default implementation of this framework method does nothing and
* returns true
. Subclasses should override this method to
* specific state checks.
*
true
if the field value is valid, and
* false
if invalid
*/
protected boolean doCheckState() {
return true;
}
/**
* Returns this field editor's text control.
*
* @return the text control, or null
if no text field is
* created yet
*/
protected Text getTextControl() {
return textField;
}
/**
* TODO 151469: Client code has requested an "extended" validate-strategy, and should override this method, attaching a suitable listener to the {@link #textField}, based on the value of {@link #validateStrategy}.
* (I.e., one other than {@link #VALIDATE_ON_KEY_STROKE} or * {@link #VALIDATE_ON_FOCUS_LOST}.)
*/ protected void handleFurtherValidationStrategies() { Assert.isTrue(false, "Unknown validate strategy");//$NON-NLS-1$ } /** * Informs this field editor's listener, if it has one, about a change to * the value (VALUE
property) provided that the old and new
* values are different.
* * This hook is not called when the text is initialized (or reset * to the default value) from the preference store. *
*/ protected void valueChanged() { setPresentsDefaultValue(false); boolean oldState = isValid; refreshValidState(); if (isValid != oldState) { fireStateChanged(IS_VALID, oldState, isValid); } String newValue = textField.getText(); if (!newValue.equals(oldValue)) { fireValueChanged(VALUE, oldValue, newValue); oldValue = newValue; } } /* (non-Javadoc) * @see org.eclipse.jface.preference.FieldEditor#getNumberOfControls() */ public int getNumberOfControls() { return 2; } /* (non-Javadoc) * @see org.eclipse.jface.preference.FieldEditor#isValid() */ public boolean isValid() { return isValid; } /* (non-Javadoc) * @see org.eclipse.jface.preference.FieldEditor#setEnabled(boolean, org.eclipse.swt.widgets.Composite) */ public void setEnabled(boolean enabled, Composite parent) { super.setEnabled(enabled, parent); getTextControl(parent).setEnabled(enabled); } /* (non-Javadoc) * @see org.eclipse.jface.preference.FieldEditor#setFocus() */ public void setFocus() { if (textField != null) { textField.setFocus(); } } /* (non-Javadoc) * @see org.eclipse.jface.preference.FieldEditor#adjustForNumColumns(int) */ protected void adjustForNumColumns(int numColumns) { GridData gd = (GridData) textField.getLayoutData(); gd.horizontalSpan = numColumns - 1; // We only grab excess space if we have to // If another field editor has more columns then // we assume it is setting the width. gd.grabExcessHorizontalSpace = gd.horizontalSpan == 1; } /** * Fills this field editor's basic controls into the given parent. *
* The string field implementation of this FieldEditor
* framework method contributes the text field. Subclasses may override but
* must call super.doFillIntoGrid
.
*
null
if none.
* TODO 151469: protected not package, to ease overriding {@link #handleFurtherValidationStrategies()} *
*/ protected Text textField; /** * Width of text field in characters; initially unlimited. */ private int widthInChars = UNLIMITED; /** * Text limit of text field in characters; initially unlimited. */ private int textLimit = UNLIMITED; /** * The error message, ornull
if none.
*/
private String errorMessage;
/**
* Indicates whether the empty string is legal; true
by
* default.
*/
private boolean emptyStringAllowed = true;
/**
* The validation strategy; VALIDATE_ON_KEY_STROKE
by
* default.
* TODO 151469: must be protected (or available via accessor) not private, to allow overriding {@link #setValidateStrategy(int)} *
*/ protected int validateStrategy = VALIDATE_ON_KEY_STROKE; }