package org.goko.common.preferences.fieldeditor.ui; import org.apache.commons.lang3.StringUtils; import org.eclipse.core.databinding.Binding; import org.eclipse.core.databinding.DataBindingContext; import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.core.databinding.beans.BeanProperties; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.databinding.validation.ValidationStatus; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.databinding.fieldassist.ControlDecorationSupport; import org.eclipse.jface.databinding.swt.WidgetProperties; import org.eclipse.swt.SWT; 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; import org.goko.common.bindings.AbstractModelObject; import org.goko.core.common.exception.GkException; /** * A field editor for a string type preference. * <p> * This class may be used as is, or subclassed as required. * </p> */ public class UiStringFieldEditor extends UiLabeledFieldEditor<Text> { /** * Text limit constant (value <code>-1</code>) indicating unlimited * text limit and width. */ public static int UNLIMITED = -1; /** * 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 = "Error"; /** * The valid state of this control */ private boolean isValid; /** * The old valid value */ private String oldValue; /** * Indicates whether the empty string is legal; * <code>true</code> by default. */ private boolean emptyStringAllowed = true; public UiStringFieldEditor(Composite parent, int style) { super(parent, style); //createControls(parent, style); } /** (inheritDoc) * @see org.goko.common.preferences.fieldeditor.preference.PreferenceFieldEditor#createControls(org.eclipse.swt.widgets.Composite, int) */ @Override protected void createControls(Composite parent, int style) { super.createControls(parent, style); control = new Text(this, SWT.BORDER | style); control.setText("Text"); control.setLayoutData(new GridData(SWT.LEFT, SWT.RIGHT, true, false, 1, 1)); control.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { valueChanged(); } }); control.pack(); this.pack(); } /** * 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() { boolean oldState = isValid; refreshValidState(); if (isValid != oldState) { fireStateChanged(IS_VALID, oldState, isValid); } String newValue = getText(); if (!StringUtils.equals(newValue, oldValue)) { fireValueChanged(VALUE, oldValue, newValue); oldValue = newValue; } } /** * Update the valid state of this input */ protected void refreshValidState() { isValid = true; if(textLimit != UNLIMITED && StringUtils.length(getText()) > textLimit){ isValid = false; } if( !emptyStringAllowed && StringUtils.isBlank(getText())){ isValid = false; } isValid = isValid && isValidValue(); } /** * Allow verification in subclass * @return <code>true</code> if the input is valid, <code>false</code> otherwise */ protected boolean isValidValue() { return true; } public String getValue(){ return oldValue; } protected String getText(){ return getControl().getText(); } /** * @return the widthInChars */ public int getWidthInChars() { return widthInChars; } /** * @param widthInChars the widthInChars to set */ public void setWidthInChars(int widthInChars) { this.widthInChars = widthInChars; updateControlLayout(); } private void updateControlLayout(){ GridData gd = new GridData(SWT.LEFT, SWT.RIGHT, true, false, 1, 1); if (widthInChars != UNLIMITED) { GC gc = new GC(control); try { Point extent = gc.textExtent("X");//$NON-NLS-1$ gd.widthHint = widthInChars * extent.x; } finally { gc.dispose(); } } control.setLayoutData(gd); pack(); } /** * @return the textLimit */ public int getTextLimit() { return textLimit; } /** * @param textLimit the textLimit to set */ public void setTextLimit(int textLimit) { this.textLimit = textLimit; } /** * @return the emptyStringAllowed */ public boolean isEmptyStringAllowed() { return emptyStringAllowed; } /** * @param emptyStringAllowed the emptyStringAllowed to set */ public void setEmptyStringAllowed(boolean emptyStringAllowed) { this.emptyStringAllowed = emptyStringAllowed; boolean oldState = isValid; refreshValidState(); if (isValid != oldState) { fireStateChanged(IS_VALID, oldState, isValid); } } @Override protected Binding getFieldEditorBinding(DataBindingContext bindingContext, AbstractModelObject modelObject) throws GkException { IObservableValue widgetObserver = WidgetProperties.text(SWT.Modify).observe(getControl()); IObservableValue modelObserver = BeanProperties.value(propertyName).observe(modelObject); UpdateValueStrategy targetToModelStrategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE); targetToModelStrategy.setBeforeSetValidator(this); UpdateValueStrategy modelToTargetStrategy = new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE); //modelToTargetStrategy.setBeforeSetValidator(this); if(getConverter() != null){ if(getConverter().getTargetToModelConverter() != null){ targetToModelStrategy.setConverter(getConverter().getTargetToModelConverter()); } if(getConverter().getModelToTargetConverter() != null){ modelToTargetStrategy.setConverter(getConverter().getModelToTargetConverter()); } } Binding bindValue = bindingContext.bindValue(widgetObserver, modelObserver, targetToModelStrategy, modelToTargetStrategy); // add some decorations to the control ControlDecorationSupport.create(bindValue, SWT.TOP | SWT.LEFT); return bindValue; } /** (inheritDoc) * @see org.goko.common.preferences.fieldeditor.preference.PreferenceFieldEditor#isValid() */ @Override public boolean isValid() { return isValid; } /** * @return the errorMessage */ public String getErrorMessage() { return errorMessage; } /** (inheritDoc) * @see org.eclipse.core.databinding.validation.IValidator#validate(java.lang.Object) */ @Override public IStatus validate(Object value) { refreshValidState(); if(isValid){ return ValidationStatus.OK_STATUS; } return ValidationStatus.error(errorMessage); } /** * @param errorMessage the errorMessage to set */ public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; } public IBindingConverter getConverter(){ return null; } /** (inheritDoc) * @see org.goko.common.preferences.fieldeditor.ui.UiFieldEditor#setEnabled(boolean) */ @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); getControl().setEnabled(enabled); } }