Java tutorial
/* ==================================================================== * Copyright 2003-2004 Fabrizio Giustina. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ==================================================================== */ package net.sf.commonclipse.preferences; import org.eclipse.jface.preference.FieldEditor; import org.eclipse.jface.resource.JFaceResources; 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.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; /** * Implementation identical to StringFieldEditor but using a combo instead of a Text field. * @author fgiust * @version $Revision: 1.4 $ ($Author: fgiust $) */ public class ComboFieldEditor extends FieldEditor { /** * Text limit constant (value <code>-1</code>) indicating unlimited text limit and width. */ public static final int UNLIMITED = -1; /** * The text field, or <code>null</code> if none. */ Combo textField; /** * predefined values to be shown in list. */ private String[] predefinedValues; /** * Cached valid state. */ private boolean isValid; /** * Old text value. */ private String oldValue; /** * 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, or <code>null</code> if none. */ private String errorMessage; /** * Indicates whether the empty string is legal; <code>true</code> by default. */ private boolean emptyStringAllowed = true; /** * Creates a new string field editor. */ protected ComboFieldEditor() { } /** * Creates a string field editor. Use the method <code>setTextLimit</code> to limit the text. * @param name the name of the preference this field editor works on * @param labelText the label text of the field editor * @param width the width of the text input field in characters, or <code>UNLIMITED</code> for no limit * @param parent the parent of the field editor's control */ public ComboFieldEditor(String name, String labelText, int width, Composite parent) { init(name, labelText); this.widthInChars = width; this.isValid = false; this.errorMessage = JFaceResources.getString("StringFieldEditor.errorMessage"); //$NON-NLS-1$ createControl(parent); } /** * Creates a string field editor of unlimited width. Use the method <code>setTextLimit</code> to limit the text. * @param name the name of the preference this field editor works on * @param labelText the label text of the field editor * @param parent the parent of the field editor's control */ public ComboFieldEditor(String name, String labelText, Composite parent) { this(name, labelText, UNLIMITED, parent); } /** * Checks whether the text input field contains a valid value or not. * @return <code>true</code> if the field value is valid, and <code>false</code> if invalid */ protected boolean checkState() { boolean result = false; if (this.emptyStringAllowed) { result = true; } if (this.textField == null) { result = false; } String txt = this.textField.getText(); if (txt == null) { result = false; } result = (txt.trim().length() > 0) || this.emptyStringAllowed; // call hook for subclasses result = result && doCheckState(); if (result) { clearErrorMessage(); } else { showErrorMessage(this.errorMessage); } return result; } /** * @see org.eclipse.jface.preference.FieldEditor#doLoad() */ protected void doLoad() { if (this.textField != null) { addDefaultOptions(); String value = getPreferenceStore().getString(getPreferenceName()); this.textField.setText(value); this.oldValue = value; } } /** * @see org.eclipse.jface.preference.FieldEditor#doLoadDefault() */ protected void doLoadDefault() { if (this.textField != null) { addDefaultOptions(); String value = getPreferenceStore().getDefaultString(getPreferenceName()); this.textField.setText(value); } valueChanged(); } /** * @see org.eclipse.jface.preference.FieldEditor#doStore() */ protected void doStore() { getPreferenceStore().setValue(getPreferenceName(), this.textField.getText()); } /** * Returns the error message that will be displayed when and if an error occurs. * @return the error message, or <code>null</code> if none */ public String getErrorMessage() { return this.errorMessage; } /** * @see org.eclipse.jface.preference.FieldEditor#getNumberOfControls() */ public int getNumberOfControls() { return 2; } /** * Returns the field editor's value. * @return the current value */ public String getStringValue() { if (this.textField != null) { return this.textField.getText(); } return getPreferenceStore().getString(getPreferenceName()); } /** * Returns this field editor's text control. * @return the text control, or <code>null</code> if no text field is created yet */ protected Combo getTextControl() { return this.textField; } /** * Returns this field editor's text control. * <p> * The control is created if it does not yet exist * </p> * @param parent the parent * @return the text control */ public Combo getTextControl(Composite parent) { if (this.textField == null) { this.textField = new Combo(parent, SWT.SINGLE | SWT.BORDER); this.textField.setFont(parent.getFont()); this.textField.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent e) { valueChanged(); } }); this.textField.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { valueChanged(); } public void widgetDefaultSelected(SelectionEvent e) { valueChanged(); } }); this.textField.addFocusListener(new FocusAdapter() { public void focusGained(FocusEvent e) { refreshValidState(); } public void focusLost(FocusEvent e) { valueChanged(); clearErrorMessage(); } }); this.textField.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent event) { ComboFieldEditor.this.textField = null; } }); if (this.textLimit > 0) { // Only set limits above 0 - see SWT spec this.textField.setTextLimit(this.textLimit); } } else { checkParent(this.textField, parent); } return this.textField; } /** * Returns whether an empty string is a valid value. * @return <code>true</code> if an empty string is a valid value, and <code>false</code> if an empty string is * invalid * @see #setEmptyStringAllowed */ public boolean isEmptyStringAllowed() { return this.emptyStringAllowed; } /** * @see org.eclipse.jface.preference.FieldEditor # isValid() */ public boolean isValid() { return this.isValid; } /** * @see org.eclipse.jface.preference.FieldEditor#refreshValidState() */ protected void refreshValidState() { this.isValid = checkState(); } /** * Sets whether the empty string is a valid value or not. * @param b <code>true</code> if the empty string is allowed, and <code>false</code> if it is considered invalid */ public void setEmptyStringAllowed(boolean b) { this.emptyStringAllowed = b; } /** * Sets the error message that will be displayed when and if an error occurs. * @param message the error message */ public void setErrorMessage(String message) { this.errorMessage = message; } /** * @see org.eclipse.jface.preference.FieldEditor#setFocus() */ public void setFocus() { if (this.textField != null) { this.textField.setFocus(); } } /** * Sets this field editor's value. * @param value the new value, or <code>null</code> meaning the empty string */ public void setStringValue(String value) { if (this.textField != null) { String newValue = value; if (newValue == null) { newValue = ""; //$NON-NLS-1$ } this.oldValue = this.textField.getText(); if (!this.oldValue.equals(newValue)) { this.textField.setText(newValue); valueChanged(); } } } /** * Sets this text field's text limit. * @param limit the limit on the number of character in the text input field, or <code>UNLIMITED</code> for no * limit */ public void setTextLimit(int limit) { this.textLimit = limit; if (this.textField != null) { this.textField.setTextLimit(limit); } } /** * Shows the error message set via <code>setErrorMessage</code>. */ public void showErrorMessage() { showErrorMessage(this.errorMessage); } /** * Informs this field editor's listener, if it has one, about a change to the value (<code>VALUE</code> property) * provided that the old and new values are different. * <p> * This hook is <em>not</em> called when the text is initialized (or reset to the default value) from the * preference store. * </p> */ protected void valueChanged() { setPresentsDefaultValue(false); boolean oldState = this.isValid; refreshValidState(); if (this.isValid != oldState) { fireStateChanged(IS_VALID, oldState, this.isValid); } String newValue = this.textField.getText(); if (!newValue.equals(this.oldValue)) { fireValueChanged(VALUE, this.oldValue, newValue); this.oldValue = newValue; } } /** * @see org.eclipse.jface.preference.FieldEditor#setEnabled(boolean,Composite). */ public void setEnabled(boolean enabled, Composite parent) { super.setEnabled(enabled, parent); getTextControl(parent).setEnabled(enabled); } /** * Hook for subclasses to do specific state checks. * <p> * The default implementation of this framework method does nothing and returns <code>true</code>. Subclasses * should override this method to specific state checks. * </p> * @return <code>true</code> if the field value is valid, and <code>false</code> if invalid */ protected boolean doCheckState() { return true; } /** * @see org.eclipse.jface.preference.FieldEditor#adjustForNumColumns(int) */ protected void adjustForNumColumns(int numColumns) { GridData gd = (GridData) this.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; } /** * @see org.eclipse.jface.preference.FieldEditor#doFillIntoGrid(Composite, int) */ protected void doFillIntoGrid(Composite parent, int numColumns) { getLabelControl(parent); this.textField = getTextControl(parent); GridData gd = new GridData(); gd.horizontalSpan = numColumns - 1; if (this.widthInChars != UNLIMITED) { GC gc = new GC(this.textField); try { Point extent = gc.textExtent("X"); //$NON-NLS-1$ gd.widthHint = this.widthInChars * extent.x; } finally { gc.dispose(); } } else { gd.horizontalAlignment = GridData.FILL; gd.grabExcessHorizontalSpace = true; } this.textField.setLayoutData(gd); } /** * Sets a list of predefined values that must be shown in the combo. * @param strings array of Strings added to the combo */ public void setPredefinedValues(String[] strings) { this.predefinedValues = strings; } /** * Adds predefined options to the combo. */ private void addDefaultOptions() { if (this.textField != null && this.predefinedValues != null) { this.textField.setItems(this.predefinedValues); } } /** * @see org.eclipse.jface.preference.FieldEditor#clearErrorMessage() */ protected void clearErrorMessage() { super.clearErrorMessage(); } }