blob: dd335e1ccce84978eb70a9c68d6dc1767dc52df5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 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
*******************************************************************************/
package org.eclipse.jface.internal.databinding;
import org.eclipse.jface.databinding.BindingException;
import org.eclipse.jface.databinding.ChangeEvent;
import org.eclipse.jface.databinding.IBindSpec;
import org.eclipse.jface.databinding.IChangeListener;
import org.eclipse.jface.databinding.IUpdatableValue;
import org.eclipse.jface.databinding.converter.IConverter;
import org.eclipse.jface.databinding.validator.IValidator;
/**
* @since 3.2
*
*/
public class ValueBinding extends Binding {
private final IUpdatableValue target;
private final IUpdatableValue model;
private IValidator validator;
private IConverter converter;
private boolean updating = false;
/**
* @param context
* @param target
* @param model
* @param bindSpec
*/
public ValueBinding(DataBindingContext context, IUpdatableValue target,
IUpdatableValue model, IBindSpec bindSpec) {
super(context);
this.target = target;
this.model = model;
converter = bindSpec.getConverter();
if (converter == null) {
throw new BindingException("Missing converter from " + target.getValueType() + " to " + model.getValueType()); //$NON-NLS-1$ //$NON-NLS-2$
}
// FIXME: Waiting for M4 to ship to commit; also need to write a test case
if (!converter.getModelType().isAssignableFrom(model.getValueType())) {
throw new BindingException(
"Converter does not apply to model type. Expected: " + model.getValueType() + ", actual: " + converter.getModelType()); //$NON-NLS-1$ //$NON-NLS-2$
}
if (!converter.getTargetType().isAssignableFrom(target.getValueType())) {
throw new BindingException(
"Converter does not apply to target type. Expected: " + target.getValueType() + ", actual: " + converter.getTargetType()); //$NON-NLS-1$ //$NON-NLS-2$
}
validator = bindSpec.getValidator();
if (validator == null) {
throw new BindingException("Missing validator"); //$NON-NLS-1$
}
target.addChangeListener(targetChangeListener);
model.addChangeListener(modelChangeListener);
}
private final IChangeListener targetChangeListener = new IChangeListener() {
public void handleChange(ChangeEvent changeEvent) {
if (updating)
return;
if (changeEvent.getChangeType() == ChangeEvent.VERIFY) {
// we are notified of a pending change, do validation
// and veto the change if it is not valid
Object value = changeEvent.getNewValue();
String partialValidationError = validator
.isPartiallyValid(value);
context.updatePartialValidationError(this,
partialValidationError);
if (partialValidationError != null) {
changeEvent.setVeto(true);
}
} else {
// the target (usually a widget) has changed, validate
// the value and update the source
updateModelFromTarget();
}
}
};
private IChangeListener modelChangeListener = new IChangeListener() {
public void handleChange(ChangeEvent changeEvent) {
if (updating)
return;
// The model has changed so we must update the target
if (changeEvent.getChangeType() == ChangeEvent.VERIFY) {
} else {
updateTargetFromModel();
}
}
};
/**
* This also does validation.
*/
public void updateModelFromTarget() {
Object value = target.getValue();
String validationError = doValidateTarget(value);
context.updateValidationError(targetChangeListener, validationError);
if (validationError == null) {
try {
updating = true;
model.setValue(converter.convertTargetToModel(value));
} catch (Exception ex) {
context.updateValidationError(targetChangeListener, BindingMessages
.getString("ValueBinding_ErrorWhileSettingValue")); //$NON-NLS-1$
} finally {
updating = false;
}
}
}
/**
*
*/
public void validateTarget() {
Object value = target.getValue();
doValidateTarget(value);
}
private String doValidateTarget(Object value) {
String validationError = validator.isValid(value);
context.updatePartialValidationError(targetChangeListener, null);
context.updateValidationError(targetChangeListener, validationError);
return validationError;
}
/**
*
*/
public void updateTargetFromModel() {
try {
updating = true;
target.setValue(converter.convertModelToTarget(model.getValue()));
validateTarget();
} finally {
updating = false;
}
}
}