Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » JFace » [Databinding] ValueChangeListers on MultiValidator ValidationStatus don't fire
[Databinding] ValueChangeListers on MultiValidator ValidationStatus don't fire [message #487398] Wed, 23 September 2009 06:12 Go to next message
Ashley Cambrell is currently offline Ashley CambrellFriend
Messages: 5
Registered: July 2009
Junior Member
Hi All,

I'm attempting to use an IListChangeListener on the ValidationStatus of MultiValidator to update an FormPage's IMessageManager when the validation changes. When the initial state of the validator is ERROR, and the next state post-bind is also error, the ValueChangeListeners are not fired. This is due to the Util.equals check in MultiValidator$ValidationStatusObservableValue#doSetValue which prevents the event firing is it's value is the same as the previous value.

The catch is that the initial value is set BEFORE the ValueChageListener is added (as getValueStatus() calls revalidate which sets then causes the initial value to be set.

The is best shown in a test case.

public class MultiValiditatorValidationStatusTest
{
	private WritableValue value1;

	private WritableValue value2;

	private BooleanHolder booleanHolder;

	private DataBindingContext dataBindingContext;

	@Before
	public void beforeEach()
	{
		CurrentRealm.setDefault(SWTObservables.getRealm(Display.getCurrent()));

		value1 = new WritableValue();
		value2 = new WritableValue();
		booleanHolder = new BooleanHolder();
		dataBindingContext = new DataBindingContext();
	}

	@Test
	public void shouldCallHandleValueChangeOnIValueChangeListenersForMultiValidator() throws Exception
	{
// value1.setValue(Integer.valueOf(1));

		MultiValidator multiValidator = new MultiValidator()
		{
			@Override
			protected IStatus validate()
			{
				Object value = value1.getValue();

				if (value != null && value instanceof Number && ((Number) value).intValue() == 1)
				{
					return ValidationStatus.ok();
				}
				return ValidationStatus.error("Value was not one");
			}
		};
		multiValidator.getValidationStatus().addValueChangeListener(new IValueChangeListener()
		{

			@Override
			public void handleValueChange(ValueChangeEvent event)
			{
				booleanHolder.value = true;
			}
		});

		dataBindingContext.addValidationStatusProvider(multiValidator);

		dataBindingContext.bindValue(multiValidator.observeValidatedValue(value1), value2, null, new UpdateValueStrategy(
			UpdateValueStrategy.POLICY_NEVER));

		value1.setValue(Integer.valueOf(2));

		assertTrue(booleanHolder.value);
	}

	private static class CurrentRealm extends Realm
	{
		private boolean current;

		public CurrentRealm()
		{
			this(false);
		}

		public CurrentRealm(boolean current)
		{
			this.current = current;
		}

		public boolean isCurrent()
		{
			return current;
		}

		public void setCurrent(boolean current)
		{
			this.current = current;
		}

		protected void syncExec(Runnable runnable)
		{
			// do nothing
		}

		public void asyncExec(Runnable runnable)
		{
			// do nothing
		}

		protected static Realm setDefault(Realm realm)
		{
			return Realm.setDefault(realm);
		}
	}

	private static class BooleanHolder
	{
		public boolean value = false;
	}
}



When multiValidator.getValidationStatus() is called, the validator is fired and the initial value is set. So when value1.setValue(Integer.valueOf(2)); is called the nothing happens. In the real world, the IMessageManager doesn't get updated.

I can work around this in three ways:
1. Make sure the model is valid before the ValueChangeListener is added. (In the test case by doing value1.setValue(Integer.valueOf(1)) first off. Not really possible in the real world.)

2. toggle the value so the validators result is also toggled and the Util.equals check is passed (Also not possible in the real world).
		value1.setValue(Integer.valueOf(1));
		value1.setValue(Integer.valueOf(2));


3. Make the first value returned by the validator different to any of the possible following results (eg ValidationStatus.cancel("foo");), but still making sure any dependant IObservableValues are called (hence the Object value = value1.getValue(); before the firedFirst check).

MultiValidator multiValidator = new MultiValidator()
		{
			boolean firedFirst = false;

			@Override
			protected IStatus validate()
			{
				Object value = value1.getValue();

				if (!firedFirst)
				{
					firedFirst = true;
					return ValidationStatus.cancel("ignore first fire");
				}

				if (value != null && value instanceof Number && ((Number) value).intValue() == 1)
				{
					return ValidationStatus.ok();
				}
				return ValidationStatus.error("Value was not one");
			}
		};


Is this expected behaviour or a bug?

Cheers,

Ashley Cambrell
Re: [Databinding] ValueChangeListers on MultiValidator ValidationStatus don't fire [message #488485 is a reply to message #487398] Mon, 28 September 2009 20:55 Go to previous messageGo to next message
Matthew Hall is currently offline Matthew HallFriend
Messages: 368
Registered: July 2009
Senior Member
Ashley, would you file a bug report for this?

https://bugs.eclipse.org/bugs/enter_bug.cgi?classification=E clipse&product=Platform&component=UI&short_desc=[DataBinding]&version=3.6

Matthew

Ashley Cambrell wrote:
> Hi All,
>
> I'm attempting to use an IListChangeListener on the ValidationStatus of
> MultiValidator to update an FormPage's IMessageManager when the
> validation changes. When the initial state of the validator is ERROR,
> and the next state post-bind is also error, the ValueChangeListeners are
> not fired. This is due to the Util.equals check in
> MultiValidator$ValidationStatusObservableValue#doSetValue which prevents
> the event firing is it's value is the same as the previous value.
>
> The catch is that the initial value is set BEFORE the ValueChageListener
> is added (as getValueStatus() calls revalidate which sets then causes
> the initial value to be set.
>
> The is best shown in a test case.
>
>
> public class MultiValiditatorValidationStatusTest
> {
> private WritableValue value1;
>
> private WritableValue value2;
>
> private BooleanHolder booleanHolder;
>
> private DataBindingContext dataBindingContext;
>
> @Before
> public void beforeEach()
> {
>
> CurrentRealm.setDefault(SWTObservables.getRealm(Display.getC urrent()));
>
> value1 = new WritableValue();
> value2 = new WritableValue();
> booleanHolder = new BooleanHolder();
> dataBindingContext = new DataBindingContext();
> }
>
> @Test
> public void
> shouldCallHandleValueChangeOnIValueChangeListenersForMultiVa lidator()
> throws Exception
> {
> // value1.setValue(Integer.valueOf(1));
>
> MultiValidator multiValidator = new MultiValidator()
> {
> @Override
> protected IStatus validate()
> {
> Object value = value1.getValue();
>
> if (value != null && value instanceof Number &&
> ((Number) value).intValue() == 1)
> {
> return ValidationStatus.ok();
> }
> return ValidationStatus.error("Value was not one");
> }
> };
> multiValidator.getValidationStatus().addValueChangeListener( new
> IValueChangeListener()
> {
>
> @Override
> public void handleValueChange(ValueChangeEvent event)
> {
> booleanHolder.value = true;
> }
> });
>
> dataBindingContext.addValidationStatusProvider(multiValidato r);
>
>
> dataBindingContext.bindValue(multiValidator.observeValidated Value(value1),
> value2, null, new UpdateValueStrategy(
> UpdateValueStrategy.POLICY_NEVER));
>
> value1.setValue(Integer.valueOf(2));
>
> assertTrue(booleanHolder.value);
> }
>
> private static class CurrentRealm extends Realm
> {
> private boolean current;
>
> public CurrentRealm()
> {
> this(false);
> }
>
> public CurrentRealm(boolean current)
> {
> this.current = current;
> }
>
> public boolean isCurrent()
> {
> return current;
> }
>
> public void setCurrent(boolean current)
> {
> this.current = current;
> }
>
> protected void syncExec(Runnable runnable)
> {
> // do nothing
> }
>
> public void asyncExec(Runnable runnable)
> {
> // do nothing
> }
>
> protected static Realm setDefault(Realm realm)
> {
> return Realm.setDefault(realm);
> }
> }
>
> private static class BooleanHolder
> {
> public boolean value = false;
> }
> }
>
>
>
> When multiValidator.getValidationStatus() is called, the validator is
> fired and the initial value is set. So when
> value1.setValue(Integer.valueOf(2)); is called the nothing happens. In
> the real world, the IMessageManager doesn't get updated.
>
> I can work around this in three ways:
> 1. Make sure the model is valid before the ValueChangeListener is added.
> (In the test case by doing value1.setValue(Integer.valueOf(1)) first
> off. Not really possible in the real world.)
>
> 2. toggle the value so the validators result is also toggled and the
> Util.equals check is passed (Also not possible in the real world).
>
> value1.setValue(Integer.valueOf(1));
> value1.setValue(Integer.valueOf(2));
>
>
> 3. Make the first value returned by the validator different to any of
> the possible following results (eg ValidationStatus.cancel("foo");), but
> still making sure any dependant IObservableValues are called (hence the
> Object value = value1.getValue(); before the firedFirst check).
>
>
> MultiValidator multiValidator = new MultiValidator()
> {
> boolean firedFirst = false;
>
> @Override
> protected IStatus validate()
> {
> Object value = value1.getValue();
>
> if (!firedFirst)
> {
> firedFirst = true;
> return ValidationStatus.cancel("ignore first fire");
> }
>
> if (value != null && value instanceof Number &&
> ((Number) value).intValue() == 1)
> {
> return ValidationStatus.ok();
> }
> return ValidationStatus.error("Value was not one");
> }
> };
>
>
> Is this expected behaviour or a bug?
>
> Cheers,
>
> Ashley Cambrell
Re: [Databinding] ValueChangeListers on MultiValidator ValidationStatus don't fire [message #488493 is a reply to message #488485] Mon, 28 September 2009 21:50 Go to previous message
Ashley Cambrell is currently offline Ashley CambrellFriend
Messages: 5
Registered: July 2009
Junior Member
Done

https://bugs.eclipse.org/bugs/show_bug.cgi?id=290754
Previous Topic:How to use ComputedValue for content assistance?
Next Topic:MultiValidator does not attach to empty IObservableList
Goto Forum:
  


Current Time: Fri Apr 26 19:31:04 GMT 2024

Powered by FUDForum. Page generated in 0.03338 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top