Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 105188 Details for
Bug 233191
[DataBinding] Support for asynchronous validation/conversion on a Binding
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
MultiValidator asynchronous validation - proof of concept
patch_233191_2.txt (text/plain), 29.40 KB, created by
Matthew Hall
on 2008-06-17 14:16:12 EDT
(
hide
)
Description:
MultiValidator asynchronous validation - proof of concept
Filename:
MIME Type:
Creator:
Matthew Hall
Created:
2008-06-17 14:16:12 EDT
Size:
29.40 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.jface.examples.databinding >Index: src/org/eclipse/jface/examples/databinding/snippets/Snippet021MultiFieldValidation.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.jface.examples.databinding/src/org/eclipse/jface/examples/databinding/snippets/Snippet021MultiFieldValidation.java,v >retrieving revision 1.1 >diff -u -r1.1 Snippet021MultiFieldValidation.java >--- src/org/eclipse/jface/examples/databinding/snippets/Snippet021MultiFieldValidation.java 24 Mar 2008 22:55:56 -0000 1.1 >+++ src/org/eclipse/jface/examples/databinding/snippets/Snippet021MultiFieldValidation.java 17 Jun 2008 18:12:52 -0000 >@@ -12,7 +12,6 @@ > package org.eclipse.jface.examples.databinding.snippets; > > import java.util.ArrayList; >-import java.util.Iterator; > > import org.eclipse.core.databinding.DataBindingContext; > import org.eclipse.core.databinding.observable.Realm; >@@ -36,16 +35,16 @@ > import org.eclipse.jface.wizard.WizardDialog; > import org.eclipse.jface.wizard.WizardPage; > import org.eclipse.swt.SWT; >-import org.eclipse.swt.events.SelectionAdapter; >-import org.eclipse.swt.events.SelectionEvent; > import org.eclipse.swt.layout.GridData; > import org.eclipse.swt.layout.GridLayout; > import org.eclipse.swt.widgets.Button; > import org.eclipse.swt.widgets.Composite; > import org.eclipse.swt.widgets.Display; >+import org.eclipse.swt.widgets.Event; > import org.eclipse.swt.widgets.Group; > import org.eclipse.swt.widgets.Label; > import org.eclipse.swt.widgets.List; >+import org.eclipse.swt.widgets.Listener; > import org.eclipse.swt.widgets.Text; > > /** >@@ -82,7 +81,7 @@ > * @param parent > */ > public void createControl(Composite parent) { >- Composite container = new Composite(parent, SWT.NULL); >+ Composite container = new Composite(parent, SWT.NONE); > final GridLayout gridLayout = new GridLayout(); > gridLayout.numColumns = 2; > container.setLayout(gridLayout); >@@ -202,19 +201,18 @@ > } > > private void bindEvensAndOddsGroup(DataBindingContext dbc) { >- IObservableValue targetField1 = SWTObservables.observeText( >- field1Target, SWT.Modify); > final IObservableValue middleField1 = new WritableValue(null, > Integer.TYPE); >- dbc.bindValue(targetField1, middleField1, null, null); >+ dbc.bindValue(SWTObservables.observeText(field1Target, SWT.Modify), >+ middleField1, null, null); > >- IObservableValue targetField2 = SWTObservables.observeText( >- field2Target, SWT.Modify); > final IObservableValue middleField2 = new WritableValue(null, > Integer.TYPE); >- dbc.bindValue(targetField2, middleField2, null, null); >+ dbc.bindValue(SWTObservables.observeText(field2Target, SWT.Modify), >+ middleField2, null, null); > > MultiValidator validator = new MultiValidator() { >+ > protected IStatus validate() { > Integer field1 = (Integer) middleField1.getValue(); > Integer field2 = (Integer) middleField2.getValue(); >@@ -236,25 +234,24 @@ > dbc.bindValue(validator.observeValidatedValue(middleField2), > modelField2, null, null); > >- dbc.bindValue(SWTObservables.observeText(field1ModelValue, SWT.Modify), >+ dbc.bindValue(SWTObservables.observeText(field1ModelValue, SWT.None), > modelField1, null, null); >- dbc.bindValue(SWTObservables.observeText(field2ModelValue, SWT.Modify), >+ dbc.bindValue(SWTObservables.observeText(field2ModelValue, SWT.None), > modelField2, null, null); > } > > private void bindSumAndAddendsGroup(DataBindingContext dbc) { >- IObservableValue targetSum = SWTObservables.observeText(sumTarget, >- SWT.Modify); > final IObservableValue middleSum = new WritableValue(null, Integer.TYPE); >- dbc.bindValue(targetSum, middleSum, null, null); >+ dbc.bindValue(SWTObservables.observeText(sumTarget, SWT.Modify), >+ middleSum, null, null); > > final IObservableList targetAddends = new WritableList(new ArrayList(), > Integer.TYPE); > addendsTarget.setContentProvider(new ObservableListContentProvider()); > addendsTarget.setInput(targetAddends); > >- addAddendButton.addSelectionListener(new SelectionAdapter() { >- public void widgetSelected(final SelectionEvent e) { >+ addAddendButton.addListener(SWT.Selection, new Listener() { >+ public void handleEvent(Event event) { > InputDialog dialog = new InputDialog(getShell(), > "Input addend", "Enter an integer addend", "0", > new IInputValidator() { >@@ -275,8 +272,8 @@ > } > }); > >- removeAddendButton.addSelectionListener(new SelectionAdapter() { >- public void widgetSelected(SelectionEvent e) { >+ removeAddendButton.addListener(SWT.Selection, new Listener() { >+ public void handleEvent(Event event) { > IStructuredSelection selection = (IStructuredSelection) addendsTarget > .getSelection(); > if (!selection.isEmpty()) >@@ -286,24 +283,47 @@ > > IObservableValue modelSum = new WritableValue(new Integer(5), > Integer.TYPE); >- dbc.bindValue(SWTObservables.observeText(sumModelValue, SWT.Modify), >+ dbc.bindValue(SWTObservables.observeText(sumModelValue, SWT.None), > modelSum, null, null); > > IObservableList modelAddends = new WritableList(new ArrayList(), > Integer.TYPE); > > MultiValidator validator = new MultiValidator() { >- protected IStatus validate() { >- Integer sum = (Integer) middleSum.getValue(); >- int actualSum = 0; >- for (Iterator iterator = targetAddends.iterator(); iterator >- .hasNext();) { >- actualSum += ((Integer) iterator.next()).intValue(); >- } >- if (sum.intValue() != actualSum) >- return ValidationStatus.error("Sum of addends is " >- + actualSum + ", expecting " + sum); >- return ValidationStatus.ok(); >+ protected void validate(final StatusHandler callback) { >+ final Integer sum = (Integer) middleSum.getValue(); >+ final Integer[] addends = (Integer[]) targetAddends >+ .toArray(new Integer[targetAddends.size()]); >+ new Thread(new Runnable() { >+ public void run() { >+ try { >+ // artificial delay >+ Thread.sleep(1000); >+ } catch (InterruptedException e) { >+ callback.handleStatus(ValidationStatus.error(e >+ .getMessage(), e)); >+ } >+ >+ if (sum == null) { >+ callback.handleStatus(ValidationStatus >+ .error("sum is null")); >+ return; >+ } >+ >+ int actualSum = 0; >+ for (int i = 0; i < addends.length; i++) { >+ actualSum += addends[i].intValue(); >+ } >+ >+ if (sum.intValue() != actualSum) { >+ callback.handleStatus(ValidationStatus >+ .error("Sum of addends is " + actualSum >+ + ", expecting " + sum)); >+ } else { >+ callback.handleStatus(ValidationStatus.ok()); >+ } >+ } >+ }).start(); > } > }; > dbc.addValidationStatusProvider(validator); >#P org.eclipse.core.databinding >Index: src/org/eclipse/core/databinding/validation/MultiValidator.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/databinding/validation/MultiValidator.java,v >retrieving revision 1.1 >diff -u -r1.1 MultiValidator.java >--- src/org/eclipse/core/databinding/validation/MultiValidator.java 24 Mar 2008 22:55:58 -0000 1.1 >+++ src/org/eclipse/core/databinding/validation/MultiValidator.java 17 Jun 2008 18:12:54 -0000 >@@ -14,9 +14,11 @@ > > import java.util.ArrayList; > import java.util.Arrays; >+import java.util.List; > > import org.eclipse.core.databinding.ValidationStatusProvider; > import org.eclipse.core.databinding.observable.ChangeEvent; >+import org.eclipse.core.databinding.observable.Diffs; > import org.eclipse.core.databinding.observable.IChangeListener; > import org.eclipse.core.databinding.observable.IObservable; > import org.eclipse.core.databinding.observable.ObservableTracker; >@@ -31,6 +33,7 @@ > import org.eclipse.core.databinding.observable.set.IObservableSet; > import org.eclipse.core.databinding.observable.value.IObservableValue; > import org.eclipse.core.databinding.observable.value.WritableValue; >+import org.eclipse.core.internal.databinding.Util; > import org.eclipse.core.internal.databinding.observable.ValidatedObservableList; > import org.eclipse.core.internal.databinding.observable.ValidatedObservableMap; > import org.eclipse.core.internal.databinding.observable.ValidatedObservableSet; >@@ -115,7 +118,7 @@ > */ > public abstract class MultiValidator extends ValidationStatusProvider { > private Realm realm; >- private IObservableValue validationStatus; >+ private ValidationStatusObservableValue validationStatus; > private IObservableValue unmodifiableValidationStatus; > private WritableList targets; > private IObservableList unmodifiableTargets; >@@ -160,8 +163,7 @@ > Assert.isNotNull(realm, "Realm cannot be null"); //$NON-NLS-1$ > this.realm = realm; > >- validationStatus = new WritableValue(realm, ValidationStatus.ok(), >- IStatus.class); >+ validationStatus = new ValidationStatusObservableValue(realm); > > targets = new WritableList(realm, new ArrayList(), IObservable.class); > targets.addListChangeListener(targetsListener); >@@ -195,31 +197,107 @@ > } > > private void revalidate() { >+ validationStatus.makeStale(); >+ >+ final StatusHandler handler = new StatusHandler() { >+ public void handleStatus(final IStatus status) { >+ realm.exec(new Runnable() { >+ public void run() { >+ setStatus(status); >+ } >+ }); >+ } >+ }; > final IObservable[] dependencies = ObservableTracker.runAndMonitor( > new Runnable() { > public void run() { > try { >- IStatus status = validate(); >- if (status == null) >- status = ValidationStatus.ok(); >- validationStatus.setValue(status); >+ validate(handler); > } catch (RuntimeException e) { >- // Usually an NPE as dependencies are >- // init'ed >- validationStatus.setValue(ValidationStatus.error(e >- .getMessage(), e)); >+ // Usually an NPE as dependencies are init'ed >+ setStatus(ValidationStatus.error(e.getMessage(), e)); > } > } > }, null, null); > ObservableTracker.runAndIgnore(new Runnable() { > public void run() { >- targets.clear(); >- targets.addAll(Arrays.asList(dependencies)); >+ List dependencyList = new ArrayList(Arrays.asList(dependencies)); >+ // remove old targets not in the new dependency list >+ targets.retainAll(dependencyList); >+ // remove targets in the new dependency list which are already >+ // known >+ dependencyList.removeAll(targets); >+ // add the new dependencies >+ targets.addAll(dependencyList); > } > }); > } > > /** >+ * Callback interface for handling statuses >+ * >+ * @since 1.2 >+ */ >+ public interface StatusHandler { >+ /** >+ * Handles the given status object >+ * >+ * @param status >+ * the status >+ */ >+ void handleStatus(IStatus status); >+ } >+ >+ /** >+ * Calculates and passes the current validation status to the given >+ * callback. >+ * <p> >+ * Note: To ensure that the validation status is kept current, all >+ * dependencies used to calculate status should be accessed through >+ * {@link IObservable} instances. Each dependency observable must be in the >+ * same realm as the MultiValidator. >+ * <p> >+ * If validation is being performed asynchronously (i.e. in a different >+ * thread), then the observables which are used to calculate validation >+ * status should be accessed before forking, as follows: >+ * >+ * <pre> >+ * MultiValidator validator = new MultiValidator() { >+ * protected void validate(final StatusHandler callback) { >+ * // Observables must be accessed in the calling thread >+ * final Integer value0 = (Integer) middle0.getValue(); >+ * final Integer value1 = (Integer) middle1.getValue(); >+ * new Thread(new Runnable() { >+ * public void run() { >+ * // Calculate the validation status >+ * if (Math.abs(value0.intValue()) % 2 != Math.abs(value1 >+ * .intValue()) % 2) { >+ * callback.handleStatus(ValidationStatus.error( >+ * "Values must be both even or both odd"); >+ * } else { >+ * callback.handleStatus(ValidationStatus.ok()); >+ * } >+ * } >+ * }).start(); >+ * } >+ * }; >+ * </pre> >+ * >+ * @param callback >+ * the callback which is to receive the validation status. The >+ * callback may be called from outside the realm. >+ */ >+ protected void validate(StatusHandler callback) { >+ try { >+ callback.handleStatus(validate()); >+ } catch (RuntimeException e) { >+ // Usually an NPE as dependencies are >+ // init'ed >+ callback.handleStatus(ValidationStatus.error(e.getMessage(), e)); >+ } >+ } >+ >+ /** > * Return the current validation status. > * <p> > * Note: To ensure that the validation status is kept current, all >@@ -229,7 +307,10 @@ > * > * @return the current validation status. > */ >- protected abstract IStatus validate(); >+ protected IStatus validate() { >+ throw new IllegalStateException( >+ "Subclasses must override one of the validate() methods"); //$NON-NLS-1$ >+ } > > /** > * Returns a wrapper {@link IObservableValue} which stays in sync with the >@@ -321,8 +402,8 @@ > * The wrapper behaves as follows with respect to the validation status: > * <ul> > * <li>While valid, the wrapper stays in sync with its target observable. >- * <li>While invalid, the wrapper's entries are the target observable's >- * last valid entries. If the target changes entries, a stale event is fired >+ * <li>While invalid, the wrapper's entries are the target observable's last >+ * valid entries. If the target changes entries, a stale event is fired > * signaling that a change is pending. > * <li>When status changes from invalid to valid, the wrapper takes the > * entries of the target observable, and synchronization resumes. >@@ -366,4 +447,44 @@ > super.dispose(); > } > >+ private void setStatus(final IStatus status) { >+ ObservableTracker.runAndIgnore(new Runnable() { >+ public void run() { >+ validationStatus.setValue(status == null ? ValidationStatus >+ .ok() : status); >+ } >+ }); >+ } >+ >+ private class ValidationStatusObservableValue extends WritableValue { >+ boolean stale; >+ >+ public ValidationStatusObservableValue(Realm realm) { >+ super(realm, ValidationStatus.ok(), IStatus.class); >+ } >+ >+ void makeStale() { >+ this.stale = true; >+ fireStale(); >+ } >+ >+ public void doSetValue(Object value) { >+ boolean wasStale = this.stale; >+ this.stale = false; >+ Object oldValue = doGetValue(); >+ super.doSetValue(value); >+ if (wasStale && Util.equals(oldValue, value)) { >+ // In order to signal that the observable is not stale anymore, >+ // we must always fire a value change event, even if the >+ // validation status has not changed. In the latter case, we >+ // must do so explicitly. >+ fireValueChange(Diffs.createValueDiff(oldValue, value)); >+ } >+ } >+ >+ public boolean isStale() { >+ ObservableTracker.getterCalled(this); >+ return stale; >+ } >+ } > } >Index: src/org/eclipse/core/internal/databinding/observable/ValidatedObservableSet.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/ValidatedObservableSet.java,v >retrieving revision 1.1 >diff -u -r1.1 ValidatedObservableSet.java >--- src/org/eclipse/core/internal/databinding/observable/ValidatedObservableSet.java 24 Mar 2008 22:55:58 -0000 1.1 >+++ src/org/eclipse/core/internal/databinding/observable/ValidatedObservableSet.java 17 Jun 2008 18:12:54 -0000 >@@ -52,7 +52,7 @@ > if (updatingTarget) > return; > IStatus status = (IStatus) validationStatus.getValue(); >- if (isValid(status)) { >+ if (!validationStatus.isStale() && isValid(status)) { > if (stale) { > // this.stale means we are out of sync with target, > // so reset wrapped list to exactly mirror target >@@ -73,17 +73,10 @@ > } > }; > >- private IStaleListener targetStaleListener = new IStaleListener() { >- public void handleStale(StaleEvent staleEvent) { >- fireStale(); >- } >- }; >- > private IValueChangeListener validationStatusChangeListener = new IValueChangeListener() { > public void handleValueChange(ValueChangeEvent event) { >- IStatus oldStatus = (IStatus) event.diff.getOldValue(); > IStatus newStatus = (IStatus) event.diff.getNewValue(); >- if (stale && !isValid(oldStatus) && isValid(newStatus)) { >+ if (stale && !validationStatus.isStale() && isValid(newStatus)) { > // this.stale means we are out of sync with target, > // reset wrapped set to exactly mirror target > stale = false; >@@ -96,6 +89,16 @@ > } > }; > >+ private IStaleListener staleListener = new IStaleListener() { >+ public void handleStale(StaleEvent staleEvent) { >+ fireStale(); >+ } >+ }; >+ >+ private static boolean isValid(IStatus status) { >+ return !status.matches(IStatus.CANCEL | IStatus.ERROR); >+ } >+ > /** > * @param target > * @param validationStatus >@@ -111,8 +114,9 @@ > this.target = target; > this.validationStatus = validationStatus; > target.addSetChangeListener(targetChangeListener); >- target.addStaleListener(targetStaleListener); >+ target.addStaleListener(staleListener); > validationStatus.addValueChangeListener(validationStatusChangeListener); >+ validationStatus.addStaleListener(staleListener); > } > > private void updateWrappedSet(Set newSet) { >@@ -122,10 +126,6 @@ > fireSetChange(diff); > } > >- private static boolean isValid(IStatus status) { >- return status.isOK() || status.matches(IStatus.INFO | IStatus.WARNING); >- } >- > private void applyDiff(SetDiff diff, Set set) { > for (Iterator iterator = diff.getRemovals().iterator(); iterator > .hasNext();) { >@@ -160,7 +160,7 @@ > > public boolean isStale() { > getterCalled(); >- return stale || target.isStale(); >+ return stale || target.isStale() || validationStatus.isStale(); > } > > public boolean add(Object o) { >@@ -262,9 +262,10 @@ > > public synchronized void dispose() { > target.removeSetChangeListener(targetChangeListener); >- target.removeStaleListener(targetStaleListener); >+ target.removeStaleListener(staleListener); > validationStatus > .removeValueChangeListener(validationStatusChangeListener); >+ validationStatus.removeStaleListener(staleListener); > super.dispose(); > } > } >Index: src/org/eclipse/core/internal/databinding/observable/ValidatedObservableMap.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/ValidatedObservableMap.java,v >retrieving revision 1.1 >diff -u -r1.1 ValidatedObservableMap.java >--- src/org/eclipse/core/internal/databinding/observable/ValidatedObservableMap.java 24 Mar 2008 22:55:58 -0000 1.1 >+++ src/org/eclipse/core/internal/databinding/observable/ValidatedObservableMap.java 17 Jun 2008 18:12:54 -0000 >@@ -51,7 +51,7 @@ > if (updatingTarget) > return; > IStatus status = (IStatus) validationStatus.getValue(); >- if (isValid(status)) { >+ if (!validationStatus.isStale() && isValid(status)) { > if (stale) { > // this.stale means we are out of sync with target, > // so reset wrapped list to exactly mirror target >@@ -72,17 +72,10 @@ > } > }; > >- private IStaleListener targetStaleListener = new IStaleListener() { >- public void handleStale(StaleEvent staleEvent) { >- fireStale(); >- } >- }; >- > private IValueChangeListener validationStatusChangeListener = new IValueChangeListener() { > public void handleValueChange(ValueChangeEvent event) { >- IStatus oldStatus = (IStatus) event.diff.getOldValue(); > IStatus newStatus = (IStatus) event.diff.getNewValue(); >- if (stale && !isValid(oldStatus) && isValid(newStatus)) { >+ if (stale && !validationStatus.isStale() && isValid(newStatus)) { > // this.stale means we are out of sync with target, > // reset wrapped map to exactly mirror target > stale = false; >@@ -95,6 +88,12 @@ > } > }; > >+ private IStaleListener staleListener = new IStaleListener() { >+ public void handleStale(StaleEvent staleEvent) { >+ fireStale(); >+ } >+ }; >+ > /** > * @param target > * @param validationStatus >@@ -110,7 +109,7 @@ > this.target = target; > this.validationStatus = validationStatus; > target.addMapChangeListener(targetChangeListener); >- target.addStaleListener(targetStaleListener); >+ target.addStaleListener(staleListener); > validationStatus.addValueChangeListener(validationStatusChangeListener); > } > >@@ -122,7 +121,7 @@ > } > > private static boolean isValid(IStatus status) { >- return status.isOK() || status.matches(IStatus.INFO | IStatus.WARNING); >+ return !status.matches(IStatus.CANCEL | IStatus.ERROR); > } > > private void applyDiff(MapDiff diff, Map map) { >@@ -164,7 +163,7 @@ > > public boolean isStale() { > getterCalled(); >- return stale || target.isStale(); >+ return stale || target.isStale() || validationStatus.isStale(); > } > > public void clear() { >@@ -220,9 +219,10 @@ > > public synchronized void dispose() { > target.removeMapChangeListener(targetChangeListener); >- target.removeStaleListener(targetStaleListener); >+ target.removeStaleListener(staleListener); > validationStatus > .removeValueChangeListener(validationStatusChangeListener); >+ validationStatus.removeStaleListener(staleListener); > super.dispose(); > } > } >Index: src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableValue.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableValue.java,v >retrieving revision 1.2 >diff -u -r1.2 UnmodifiableObservableValue.java >--- src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableValue.java 22 Feb 2008 05:33:48 -0000 1.2 >+++ src/org/eclipse/core/internal/databinding/observable/UnmodifiableObservableValue.java 17 Jun 2008 18:12:54 -0000 >@@ -55,4 +55,8 @@ > public Object getValueType() { > return wrappedValue.getValueType(); > } >+ >+ public boolean isStale() { >+ return wrappedValue.isStale(); >+ } > } >Index: src/org/eclipse/core/internal/databinding/observable/ValidatedObservableList.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/ValidatedObservableList.java,v >retrieving revision 1.1 >diff -u -r1.1 ValidatedObservableList.java >--- src/org/eclipse/core/internal/databinding/observable/ValidatedObservableList.java 24 Mar 2008 22:55:58 -0000 1.1 >+++ src/org/eclipse/core/internal/databinding/observable/ValidatedObservableList.java 17 Jun 2008 18:12:54 -0000 >@@ -56,7 +56,7 @@ > if (updatingTarget) > return; > IStatus status = (IStatus) validationStatus.getValue(); >- if (isValid(status)) { >+ if (!validationStatus.isStale() && isValid(status)) { > if (stale) { > // this.stale means we are out of sync with target, > // so reset wrapped list to exactly mirror target >@@ -77,21 +77,10 @@ > } > }; > >- private static boolean isValid(IStatus status) { >- return status.isOK() || status.matches(IStatus.INFO | IStatus.WARNING); >- } >- >- private IStaleListener targetStaleListener = new IStaleListener() { >- public void handleStale(StaleEvent staleEvent) { >- fireStale(); >- } >- }; >- > private IValueChangeListener validationStatusChangeListener = new IValueChangeListener() { > public void handleValueChange(ValueChangeEvent event) { >- IStatus oldStatus = (IStatus) event.diff.getOldValue(); > IStatus newStatus = (IStatus) event.diff.getNewValue(); >- if (stale && !isValid(oldStatus) && isValid(newStatus)) { >+ if (stale && !validationStatus.isStale() && isValid(newStatus)) { > // this.stale means we are out of sync with target, > // reset wrapped list to exactly mirror target > stale = false; >@@ -104,6 +93,16 @@ > } > }; > >+ private IStaleListener staleListener = new IStaleListener() { >+ public void handleStale(StaleEvent staleEvent) { >+ fireStale(); >+ } >+ }; >+ >+ private static boolean isValid(IStatus status) { >+ return !status.matches(IStatus.CANCEL | IStatus.ERROR); >+ } >+ > /** > * @param target > * @param validationStatus >@@ -119,8 +118,9 @@ > this.target = target; > this.validationStatus = validationStatus; > target.addListChangeListener(targetChangeListener); >- target.addStaleListener(targetStaleListener); >+ target.addStaleListener(staleListener); > validationStatus.addValueChangeListener(validationStatusChangeListener); >+ validationStatus.addStaleListener(staleListener); > } > > private void makeStale() { >@@ -163,7 +163,7 @@ > > public boolean isStale() { > ObservableTracker.getterCalled(this); >- return stale || target.isStale(); >+ return stale || target.isStale() || validationStatus.isStale(); > } > > public void add(int index, Object element) { >@@ -385,9 +385,10 @@ > > public synchronized void dispose() { > target.removeListChangeListener(targetChangeListener); >- target.removeStaleListener(targetStaleListener); >+ target.removeStaleListener(staleListener); > validationStatus > .removeValueChangeListener(validationStatusChangeListener); >+ validationStatus.removeStaleListener(staleListener); > super.dispose(); > } > } >Index: src/org/eclipse/core/internal/databinding/observable/ValidatedObservableValue.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/internal/databinding/observable/ValidatedObservableValue.java,v >retrieving revision 1.1 >diff -u -r1.1 ValidatedObservableValue.java >--- src/org/eclipse/core/internal/databinding/observable/ValidatedObservableValue.java 24 Mar 2008 22:55:58 -0000 1.1 >+++ src/org/eclipse/core/internal/databinding/observable/ValidatedObservableValue.java 17 Jun 2008 18:12:54 -0000 >@@ -42,9 +42,9 @@ > * <p> > * Note: > * <ul> >- * <li>By default, a status is valid if its >- * {@link IStatus#getSeverity() severity} is {@link IStatus#OK OK}, >- * {@link IStatus#INFO INFO}, or {@link IStatus#WARNING WARNING} >+ * <li>By default, a status is valid if its {@link IStatus#getSeverity() >+ * severity} is {@link IStatus#OK OK}, {@link IStatus#INFO INFO}, or >+ * {@link IStatus#WARNING WARNING} > * <li>Calls to {@link #setValue(Object)} on the validated observable changes > * the value regardless of the validation status. > * <li>This class will not forward {@link ValueChangingEvent} events from a >@@ -66,33 +66,32 @@ > if (updatingTarget) > return; > IStatus status = (IStatus) validationStatus.getValue(); >- if (isValid(status)) >+ if (!validationStatus.isStale() && isValid(status)) > internalSetValue(event.diff.getNewValue(), false); > else > makeStale(); > } > }; > >- private static boolean isValid(IStatus status) { >- return status.isOK() || status.matches(IStatus.INFO | IStatus.WARNING); >- } >- >- private IStaleListener targetStaleListener = new IStaleListener() { >- public void handleStale(StaleEvent staleEvent) { >- fireStale(); >- } >- }; >- > private IValueChangeListener validationStatusChangeListener = new IValueChangeListener() { > public void handleValueChange(ValueChangeEvent event) { >- IStatus oldStatus = (IStatus) event.diff.getOldValue(); > IStatus newStatus = (IStatus) event.diff.getNewValue(); >- if (stale && !isValid(oldStatus) && isValid(newStatus)) { >+ if (stale && !validationStatus.isStale() && isValid(newStatus)) { > internalSetValue(target.getValue(), false); > } > } > }; > >+ private IStaleListener staleListener = new IStaleListener() { >+ public void handleStale(StaleEvent staleEvent) { >+ fireStale(); >+ } >+ }; >+ >+ private static boolean isValid(IStatus status) { >+ return !status.matches(IStatus.CANCEL | IStatus.ERROR); >+ } >+ > /** > * Constructs an observable value > * >@@ -115,8 +114,9 @@ > this.cachedValue = target.getValue(); > > target.addValueChangeListener(targetChangeListener); >- target.addStaleListener(targetStaleListener); >+ target.addStaleListener(staleListener); > validationStatus.addValueChangeListener(validationStatusChangeListener); >+ validationStatus.addStaleListener(staleListener); > } > > private void makeStale() { >@@ -128,7 +128,7 @@ > > public boolean isStale() { > ObservableTracker.getterCalled(this); >- return stale || target.isStale(); >+ return stale || target.isStale() || validationStatus.isStale(); > } > > protected Object doGetValue() { >@@ -136,6 +136,7 @@ > } > > private void internalSetValue(Object value, boolean updateTarget) { >+ boolean wasStale = this.stale; > Object oldValue = cachedValue; > cachedValue = value; > if (updateTarget) { >@@ -148,7 +149,7 @@ > } > } > stale = false; >- if (!Util.equals(oldValue, cachedValue)) >+ if (wasStale || !Util.equals(oldValue, cachedValue)) > fireValueChange(Diffs.createValueDiff(oldValue, cachedValue)); > } > >@@ -162,9 +163,10 @@ > > public synchronized void dispose() { > target.removeValueChangeListener(targetChangeListener); >- target.removeStaleListener(targetStaleListener); >+ target.removeStaleListener(staleListener); > validationStatus > .removeValueChangeListener(validationStatusChangeListener); >+ validationStatus.removeStaleListener(staleListener); > super.dispose(); > } > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 233191
:
105098
|
105180
| 105188 |
105214
|
105579
|
106547
|
106548