Free tutorials for Java, Eclipse and Web programming



Follow me on twitter

6. Customer Validations and ControlDecoration

This section will give a detailed example of the usage of validators and decorators with JFace Data Binding.

Create a new Eclipse RCP project "de.vogella.databinding.validation" use "RCP application with a view" as a template and re-create the POJO example . Re

Create the following class "StringLongerThenTwo" which implements org.eclipse.core.databinding.validation.IValidator.

			
package de.vogella.databinding.validation.validators;

import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.fieldassist.ControlDecoration;

public class StringLongerThenTwo implements IValidator {

	private final String message;
	private final ControlDecoration controlDecoration;

	public StringLongerThenTwo(String message,
			ControlDecoration controlDecoration) {
		super();
		this.message = message;
		this.controlDecoration = controlDecoration;
	}

	@Override
	public IStatus validate(Object value) {
		if (value instanceof String) {
			String s = (String) value;
			// We check if the string is longer then 2 signs
			if (s.length() > 2) {
				controlDecoration.hide();
				return Status.OK_STATUS;
			} else {
				controlDecoration.show();
				return ValidationStatus.error(message);
			}
		} else {
			throw new RuntimeException(
					"Not supposed to be called for non-strings.");
		}
	}
}

		

The usage of the validator is defined via the UpdateValueStrategy. We also add a label to the UI which displays the status in case something is wrong in this field. In addition we registering a change listener to the field "lastName" and change the background color of the field if the input is not correct. So you see both how to use a decorator and how to change a field based on the values.

The following shows the coding for the view.

			
package de.vogella.databinding.validation;

import org.eclipse.core.databinding.AggregateValidationStatus;

public class View extends ViewPart {
	private static final String MESSAGE = "Name must be longer two letters";
	public static final String ID = "de.vogella.databinding.validation.view";
	private PersonPojo person;
	private Text firstName;
	private Text lastName;
	private Label errorLabel;
	

	@Override
	public void createPartControl(Composite parent) {
		person = new PersonPojo();
		person.setFirstName("Lars");
		person.setLastName("Vogel");
		person.setGender("m");
		person.setAge(12);
		// Lets put thing to order
		Layout layout = new GridLayout(2, false);
		parent.setLayout(layout);

		// Firstname
		Label nameLabel = new Label(parent, SWT.None);
		nameLabel.setText("Firstname: ");
		firstName = new Text(parent, SWT.BORDER);
		
		GridData gridData = new GridData();
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessHorizontalSpace = true;
		firstName.setLayoutData(gridData);

		// Lastname
		nameLabel = new Label(parent, SWT.None);
		nameLabel.setText("Lastname: ");
		lastName = new Text(parent, SWT.BORDER);
		
		lastName.setLayoutData(gridData);

		Button button1 = new Button(parent, SWT.PUSH);
		button1.setText("Write model");
		button1.addSelectionListener(new SelectionAdapter() {

			@Override
			public void widgetSelected(SelectionEvent e) {
				System.out.println(person.getFirstName());
				System.out.println(person.getLastName());
			}
		});
		// Button should take 2 rows
		gridData = new GridData();
		gridData.horizontalSpan = 2;
		button1.setLayoutData(gridData);

		// This label will display all errors of all bindings
		Label descAllLabel = new Label(parent, SWT.NONE);
		descAllLabel.setText("All Validation Problems:");
		errorLabel = new Label(parent, SWT.NONE);
		gridData = new GridData();
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessHorizontalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		gridData.horizontalSpan = 1;
		errorLabel.setLayoutData(gridData);

		bindValues();

	}

	@Override
	public void setFocus() {
	}

	private ControlDecoration createDecorator(Text text, String message) {
		ControlDecoration controlDecoration = new ControlDecoration(text,
				SWT.LEFT | SWT.TOP);
		controlDecoration.setDescriptionText(message);
		FieldDecoration fieldDecoration = FieldDecorationRegistry.getDefault()
				.getFieldDecoration(FieldDecorationRegistry.DEC_ERROR);
		controlDecoration.setImage(fieldDecoration.getImage());
		return controlDecoration;
	}

	private void bindValues() {
		// The DataBindingContext object will manage the databindings
		DataBindingContext bindingContext = new DataBindingContext();
		
		// Create the decorator which make the error message look really nice
		 ControlDecoration firstNameDecorator = createDecorator(firstName, MESSAGE);
		
		// First we bind the text field to the model
		// Here we define the UpdateValueStrategy
		UpdateValueStrategy update = new UpdateValueStrategy();
		update.setAfterConvertValidator(new StringLongerThenTwo(MESSAGE,
				firstNameDecorator));
		// Bind firstName

		bindingContext
				.bindValue(
						WidgetProperties.text(SWT.Modify).observe(firstName),
						PojoProperties.value("firstName").observe(person),
						update, null);

		
		// Create the decorator which make the error message look really nice
		 ControlDecoration lastNameDecorator = createDecorator(lastName, MESSAGE);
		// Bind lastName
		bindingContext.bindValue(
				WidgetProperties.text(SWT.Modify).observe(lastName),
				PojoProperties.value("firstName").observe(person),
				new UpdateValueStrategy()
						.setAfterConvertValidator(new StringLongerThenTwo(
								MESSAGE, lastNameDecorator)), null);

		// We listen to all errors via this binding
		// We don't need to listen to any SWT event on this label as it never changes independently
		final IObservableValue errrorObservable = WidgetProperties.text().observe(errorLabel);
		// This one listenes to all changes
		bindingContext.bindValue(errrorObservable, new AggregateValidationStatus(
				bindingContext.getBindings(),
				AggregateValidationStatus.MAX_SEVERITY), null, null);

		// Lets change the color of the field lastName
		errrorObservable.addChangeListener(new IChangeListener() {
			@Override
			public void handleChange(ChangeEvent event) {
				if (errrorObservable.getValue().equals("OK")) {
					lastName.setBackground(Display.getCurrent().getSystemColor(
							SWT.COLOR_WHITE));

				} else {
					lastName.setBackground(Display.getCurrent().getSystemColor(
							SWT.COLOR_RED));
				}
			}
		});
	}
}