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 106547 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]
Latest code on asynchronous validation / conversion in ValueBinding using callbacks
clipboard.txt (text/plain), 24.06 KB, created by
Matthew Hall
on 2008-07-04 01:57:39 EDT
(
hide
)
Description:
Latest code on asynchronous validation / conversion in ValueBinding using callbacks
Filename:
MIME Type:
Creator:
Matthew Hall
Created:
2008-07-04 01:57:39 EDT
Size:
24.06 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.core.databinding >Index: src/org/eclipse/core/databinding/UpdateValueStrategy.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/databinding/UpdateValueStrategy.java,v >retrieving revision 1.15 >diff -u -r1.15 UpdateValueStrategy.java >--- src/org/eclipse/core/databinding/UpdateValueStrategy.java 9 May 2008 14:13:00 -0000 1.15 >+++ src/org/eclipse/core/databinding/UpdateValueStrategy.java 4 Jul 2008 05:44:39 -0000 >@@ -17,6 +17,7 @@ > import java.util.HashMap; > > import org.eclipse.core.databinding.conversion.IConverter; >+import org.eclipse.core.databinding.observable.Realm; > import org.eclipse.core.databinding.observable.value.IObservableValue; > import org.eclipse.core.databinding.validation.IValidator; > import org.eclipse.core.databinding.validation.ValidationStatus; >@@ -54,9 +55,8 @@ > import org.eclipse.core.runtime.Status; > > /** >- * Customizes a {@link Binding} between two >- * {@link IObservableValue observable values}. The following behaviors can be >- * customized via the strategy: >+ * Customizes a {@link Binding} between two {@link IObservableValue observable >+ * values}. The following behaviors can be customized via the strategy: > * <ul> > * <li>Validation</li> > * <li>Conversion</li> >@@ -73,8 +73,8 @@ > * </ol> > * </p> > * <p> >- * Validation:<br/> {@link IValidator Validators} validate the value at >- * multiple phases in the update process. Statuses returned from validators are >+ * Validation:<br/> {@link IValidator Validators} validate the value at multiple >+ * phases in the update process. Statuses returned from validators are > * aggregated into a <code>MultiStatus</code> until a status of > * <code>ERROR</code> or <code>CANCEL</code> is encountered. Either of these > * statuses will abort the update process. These statuses are available as the >@@ -91,7 +91,7 @@ > * construction of the strategy (e.g. {@link #POLICY_NEVER}, > * {@link #POLICY_CONVERT}, {@link #POLICY_ON_REQUEST}, {@link #POLICY_UPDATE}). > * </p> >- * >+ * > * @see DataBindingContext#bindValue(IObservableValue, IObservableValue, > * UpdateValueStrategy, UpdateValueStrategy) > * @see Binding#getValidationStatus() >@@ -118,8 +118,8 @@ > /** > * Policy constant denoting that the source observable's state should be > * tracked, including validating changes except for >- * {@link #validateBeforeSet(Object)}, but that the destination >- * observable's value should only be updated on request. >+ * {@link #validateBeforeSet(Object)}, but that the destination observable's >+ * value should only be updated on request. > */ > public static int POLICY_CONVERT = notInlined(4); > >@@ -135,7 +135,7 @@ > * Helper method allowing API evolution of the above constant values. The > * compiler will not inline constant values into client code if values are > * "computed" using this helper. >- * >+ * > * @param i > * an integer > * @return the same integer >@@ -149,6 +149,23 @@ > protected IValidator beforeSetValidator; > protected IConverter converter; > >+ /** >+ * @since 1.2 >+ */ >+ protected Realm afterGetValidatorRealm; >+ /** >+ * @since 1.2 >+ */ >+ protected Realm afterConvertValidatorRealm; >+ /** >+ * @since 1.2 >+ */ >+ protected Realm beforeSetValidatorRealm; >+ /** >+ * @since 1.2 >+ */ >+ protected Realm converterRealm; >+ > private int updatePolicy; > > private static ValidatorRegistry validatorRegistry = new ValidatorRegistry(); >@@ -175,7 +192,7 @@ > * Creates a new update value strategy with a configurable update policy. > * Default validators and a default converter will be provided. The defaults > * can be changed by calling one of the setter methods. >- * >+ * > * @param updatePolicy > * one of {@link #POLICY_NEVER}, {@link #POLICY_ON_REQUEST}, > * {@link #POLICY_CONVERT}, or {@link #POLICY_UPDATE} >@@ -187,9 +204,9 @@ > /** > * Creates a new update value strategy with a configurable update policy. > * Default validators and a default converter will be provided if >- * <code>provideDefaults</code> is <code>true</code>. The defaults can >- * be changed by calling one of the setter methods. >- * >+ * <code>provideDefaults</code> is <code>true</code>. The defaults can be >+ * changed by calling one of the setter methods. >+ * > * @param provideDefaults > * if <code>true</code>, default validators and a default > * converter will be provided based on the observable value's >@@ -204,13 +221,37 @@ > } > > /** >+ * Converts the given value from the source type to the destination type, >+ * and passes the converted value to the callback. >+ * <p> >+ * Default implementation will use the {@link #setConverter(IConverter) >+ * converter} if one exists. If no converter exists no conversion occurs. >+ * </p> >+ * >+ * @param value >+ * @param callback >+ * the callback for receiving the converted value >+ * @since 1.2 >+ */ >+ public void convert(final Object value, final Callback callback) { >+ if (converterRealm == null || converterRealm.isCurrent()) { >+ callback.handleResult(convert(value)); >+ } else { >+ converterRealm.exec(new Runnable() { >+ public void run() { >+ callback.handleResult(convert(value)); >+ } >+ }); >+ } >+ } >+ >+ /** > * Converts the value from the source type to the destination type. > * <p> >- * Default implementation will use the >- * {@link #setConverter(IConverter) converter} if one exists. If no >- * converter exists no conversion occurs. >+ * Default implementation will use the {@link #setConverter(IConverter) >+ * converter} if one exists. If no converter exists no conversion occurs. > * </p> >- * >+ * > * @param value > * @return the converted value > */ >@@ -220,9 +261,9 @@ > > /** > * Tries to create a validator that can validate values of type fromType. >- * Returns <code>null</code> if no validator could be created. Either >- * toType or modelDescription can be <code>null</code>, but not both. >- * >+ * Returns <code>null</code> if no validator could be created. Either toType >+ * or modelDescription can be <code>null</code>, but not both. >+ * > * @param fromType > * @param toType > * @return an IValidator, or <code>null</code> if unsuccessful >@@ -241,13 +282,13 @@ > } > > /** >- * Fills out default values based upon the provided <code>source</code> >- * and <code>destination</code>. If the strategy is to default values it >- * will attempt to default a converter. If the converter can be defaulted an >- * attempt is made to default the >- * {@link #validateAfterGet(Object) after get validator}. If a validator >- * cannot be defaulted it will be <code>null</code>. >- * >+ * Fills out default values based upon the provided <code>source</code> and >+ * <code>destination</code>. If the strategy is to default values it will >+ * attempt to default a converter. If the converter can be defaulted an >+ * attempt is made to default the {@link #validateAfterGet(Object) after get >+ * validator}. If a validator cannot be defaulted it will be >+ * <code>null</code>. >+ * > * @param source > * @param destination > */ >@@ -378,7 +419,7 @@ > /** > * Sets the validator to be invoked after the source value is converted to > * the type of the destination observable. >- * >+ * > * @param validator > * @return the receiver, to enable method call chaining > */ >@@ -390,7 +431,7 @@ > /** > * Sets the validator to be invoked after the source value is retrieved at > * the beginning of the synchronization process. >- * >+ * > * @param validator > * @return the receiver, to enable method call chaining > */ >@@ -402,7 +443,7 @@ > /** > * Sets the validator to be invoked before the value is to be set on the > * destination at the end of the synchronization process. >- * >+ * > * @param validator > * @return the receiver, to enable method call chaining > */ >@@ -414,7 +455,7 @@ > /** > * Sets the converter to be invoked when converting from the source type to > * the destination type. >- * >+ * > * @param converter > * @return the receiver, to enable method call chaining > */ >@@ -424,13 +465,88 @@ > } > > /** >+ * Sets the realm in which after-get validation should occur. >+ * >+ * @param realm >+ * the realm >+ * @return the receiver, to enable method call chaining >+ * @since 1.2 >+ */ >+ public UpdateValueStrategy setAfterGetValidatorRealm(Realm realm) { >+ this.afterGetValidatorRealm = realm; >+ return this; >+ } >+ >+ /** >+ * Sets the realm in which after-convert validation should occur. >+ * >+ * @param realm >+ * the realm >+ * @return the receiver, to enable method call chaining >+ * @since 1.2 >+ */ >+ public UpdateValueStrategy setAfterConvertValidatorRealm(Realm realm) { >+ this.afterConvertValidatorRealm = realm; >+ return this; >+ } >+ >+ /** >+ * Sets the realm in which before-set validation should occur. >+ * >+ * @param realm >+ * the realm >+ * @return the receiver, to enable method call chaining >+ * @since 1.2 >+ */ >+ public UpdateValueStrategy setBeforeSetValidatorRealm(Realm realm) { >+ this.beforeSetValidatorRealm = realm; >+ return this; >+ } >+ >+ /** >+ * Sets the realm in which conversion should occur. >+ * >+ * @param realm >+ * the realm >+ * @return the receiver, to enable method call chaining >+ * @since 1.2 >+ */ >+ public UpdateValueStrategy setConverterRealm(Realm realm) { >+ this.converterRealm = realm; >+ return this; >+ } >+ >+ /** >+ * Validates the given value after it is converted, passing the validation >+ * status to the callback. >+ * >+ * @param value >+ * the converted value to validate. >+ * @param callback >+ * the callback to which the validation status should be passed. >+ * @since 1.2 >+ */ >+ public void validateAfterConvert(final Object value, final StatusCallback callback) { >+ if (afterConvertValidatorRealm == null >+ || afterConvertValidatorRealm.isCurrent()) { >+ callback.handleStatus(validateAfterConvert(value)); >+ } else { >+ afterConvertValidatorRealm.exec(new Runnable() { >+ public void run() { >+ callback.handleStatus(validateAfterConvert(value)); >+ } >+ }); >+ } >+ } >+ >+ /** > * Validates the value after it is converted. > * <p> > * Default implementation will use the > * {@link #setAfterConvertValidator(IValidator) validator} if one exists. If > * one does not exist no validation will occur. > * </p> >- * >+ * > * @param value > * @return an ok status > */ >@@ -440,13 +556,36 @@ > } > > /** >+ * Validates the given value after it is retrieved from the source, passing >+ * the validation status to the callback. >+ * >+ * @param value >+ * the value to validate. >+ * @param callback >+ * the callback to which the validation status should be passed. >+ * @since 1.2 >+ */ >+ public void validateAfterGet(final Object value, final StatusCallback callback) { >+ if (afterGetValidatorRealm == null >+ || afterGetValidatorRealm.isCurrent()) { >+ callback.handleStatus(validateAfterGet(value)); >+ } else { >+ afterGetValidatorRealm.exec(new Runnable() { >+ public void run() { >+ callback.handleStatus(validateAfterGet(value)); >+ } >+ }); >+ } >+ } >+ >+ /** > * Validates the value after it is retrieved from the source. > * <p> > * Default implementation will use the > * {@link #setAfterGetValidator(IValidator) validator} if one exists. If one > * does not exist no validation will occur. > * </p> >- * >+ * > * @param value > * @return an ok status > */ >@@ -456,13 +595,36 @@ > } > > /** >+ * Validates the given value before it is set on the destination, passing >+ * the validation status to the callback. >+ * >+ * @param value >+ * the value to validate. >+ * @param callback >+ * the callback to which the validation status should be passed. >+ * @since 1.2 >+ */ >+ public void validateBeforeSet(final Object value, final StatusCallback callback) { >+ if (beforeSetValidatorRealm == null >+ || beforeSetValidatorRealm.isCurrent()) { >+ callback.handleStatus(validateBeforeSet(value)); >+ } else { >+ beforeSetValidatorRealm.exec(new Runnable() { >+ public void run() { >+ callback.handleStatus(validateBeforeSet(value)); >+ } >+ }); >+ } >+ } >+ >+ /** > * Validates the value before it is set on the destination. > * <p> > * Default implementation will use the > * {@link #setBeforeSetValidator(IValidator) validator} if one exists. If > * one does not exist no validation will occur. > * </p> >- * >+ * > * @param value > * @return an ok status > */ >@@ -474,7 +636,7 @@ > /** > * Sets the current value of the given observable to the given value. > * Clients may extend but must call the super implementation. >- * >+ * > * @param observableValue > * @param value > * @return status >@@ -483,9 +645,11 @@ > try { > observableValue.setValue(value); > } catch (Exception ex) { >- return ValidationStatus.error(BindingMessages >- .getString(BindingMessages.VALUEBINDING_ERROR_WHILE_SETTING_VALUE), >- ex); >+ return ValidationStatus >+ .error( >+ BindingMessages >+ .getString(BindingMessages.VALUEBINDING_ERROR_WHILE_SETTING_VALUE), >+ ex); > } > return Status.OK_STATUS; > } >@@ -535,7 +699,7 @@ > /** > * Associate a particular validator that can validate the conversion > * (fromClass, toClass) >- * >+ * > * @param fromClass > * The Class to convert from > * @param toClass >@@ -550,7 +714,7 @@ > > /** > * Return an IValidator for a specific fromClass and toClass. >- * >+ * > * @param fromClass > * The Class to convert from > * @param toClass >Index: src/org/eclipse/core/databinding/ValueBinding.java >=================================================================== >RCS file: /cvsroot/eclipse/org.eclipse.core.databinding/src/org/eclipse/core/databinding/ValueBinding.java,v >retrieving revision 1.8 >diff -u -r1.8 ValueBinding.java >--- src/org/eclipse/core/databinding/ValueBinding.java 24 Mar 2008 19:13:39 -0000 1.8 >+++ src/org/eclipse/core/databinding/ValueBinding.java 4 Jul 2008 05:44:39 -0000 >@@ -38,14 +38,18 @@ > private boolean updatingModel; > private IValueChangeListener targetChangeListener = new IValueChangeListener() { > public void handleValueChange(ValueChangeEvent event) { >- if (!updatingTarget && !Util.equals(event.diff.getOldValue(), event.diff.getNewValue())) { >+ if (!updatingTarget >+ && !Util.equals(event.diff.getOldValue(), event.diff >+ .getNewValue())) { > doUpdate(target, model, targetToModel, false, false); > } > } > }; > private IValueChangeListener modelChangeListener = new IValueChangeListener() { > public void handleValueChange(ValueChangeEvent event) { >- if (!updatingModel && !Util.equals(event.diff.getOldValue(), event.diff.getNewValue())) { >+ if (!updatingModel >+ && !Util.equals(event.diff.getOldValue(), event.diff >+ .getNewValue())) { > doUpdate(model, target, modelToTarget, false, false); > } > } >@@ -135,82 +139,167 @@ > if (policy == UpdateValueStrategy.POLICY_ON_REQUEST && !explicit) > return; > >- source.getRealm().exec(new Runnable() { >- public void run() { >- boolean destinationRealmReached = false; >- final MultiStatus multiStatus = BindingStatus.ok(); >+ final MultiStatus multiStatus = BindingStatus.ok(); >+ >+ abstract class BindingRunnable implements Runnable, StatusCallback, >+ Callback { >+ public final void run() { > try { >- // Get value >- Object value = source.getValue(); >+ doRun(); >+ } catch (Exception ex) { >+ handleError(ex); >+ } >+ } > >- // Validate after get >- IStatus status = updateValueStrategy >- .validateAfterGet(value); >- if (!mergeStatus(multiStatus, status)) >- return; >- >- // Convert value >- final Object convertedValue = updateValueStrategy >- .convert(value); >- >- // Validate after convert >- status = updateValueStrategy >- .validateAfterConvert(convertedValue); >- if (!mergeStatus(multiStatus, status)) >- return; >- if (policy == UpdateValueStrategy.POLICY_CONVERT >- && !explicit) >- return; >- >- // Validate before set >- status = updateValueStrategy >- .validateBeforeSet(convertedValue); >- if (!mergeStatus(multiStatus, status)) >- return; >- if (validateOnly) >- return; >- >- // Set value >- destinationRealmReached = true; >- destination.getRealm().exec(new Runnable() { >- public void run() { >- if (destination == target) { >- updatingTarget = true; >- } else { >- updatingModel = true; >- } >- try { >- IStatus setterStatus = updateValueStrategy >- .doSet(destination, convertedValue); >- >- mergeStatus(multiStatus, setterStatus); >- } finally { >- if (destination == target) { >- updatingTarget = false; >- } else { >- updatingModel = false; >- } >- setValidationStatus(multiStatus); >- } >- } >- }); >+ public final void handleStatus(IStatus status) { >+ try { >+ doHandleStatus(status); > } catch (Exception ex) { >- // This check is necessary as in 3.2.2 Status >- // doesn't accept a null message (bug 177264). >- String message = (ex.getMessage() != null) ? ex >- .getMessage() : ""; //$NON-NLS-1$ >- >- mergeStatus(multiStatus, new Status(IStatus.ERROR, >- Policy.JFACE_DATABINDING, IStatus.ERROR, message, >- ex)); >+ handleError(ex); >+ } >+ } >+ >+ public void handleResult(Object result) { >+ try { >+ doHandleResult(result); >+ } catch (Exception ex) { >+ handleError(ex); >+ } >+ } >+ >+ private void handleError(Exception ex) { >+ // This check is necessary as in 3.2.2 Status >+ // doesn't accept a null message (bug 177264). >+ String message = (ex.getMessage() != null) ? ex.getMessage() >+ : ""; //$NON-NLS-1$ >+ >+ mergeStatus(multiStatus, new Status(IStatus.ERROR, >+ Policy.JFACE_DATABINDING, IStatus.ERROR, message, ex)); >+ setValidationStatus(multiStatus); >+ } >+ >+ abstract void doRun(); >+ >+ void doHandleStatus(IStatus status) { >+ // do nothing >+ } >+ >+ void doHandleResult(Object result) { >+ // do nothing >+ } >+ } >+ >+ class SetValueRunnable extends BindingRunnable { >+ private final Object value; >+ >+ SetValueRunnable(Object value) { >+ this.value = value; >+ } >+ >+ void doRun() { >+ if (destination == target) { >+ updatingTarget = true; >+ } else { >+ updatingModel = true; >+ } >+ try { >+ IStatus setterStatus = updateValueStrategy.doSet( >+ destination, value); >+ >+ mergeStatus(multiStatus, setterStatus); > } finally { >- if (!destinationRealmReached) { >- setValidationStatus(multiStatus); >+ if (destination == target) { >+ updatingTarget = false; >+ } else { >+ updatingModel = false; > } >+ setValidationStatus(multiStatus); >+ } >+ } >+ } >+ >+ class ValidateBeforeSetRunnable extends BindingRunnable { >+ private final Object value; >+ >+ ValidateBeforeSetRunnable(Object value) { >+ this.value = value; >+ } >+ >+ void doRun() { >+ updateValueStrategy.validateBeforeSet(value, this); >+ } > >+ public void doHandleStatus(IStatus status) { >+ if (mergeStatus(multiStatus, status) && !validateOnly) { >+ destination.getRealm().exec(new SetValueRunnable(value)); >+ } else { >+ setValidationStatus(multiStatus); > } > } >- }); >+ } >+ >+ class ValidateAfterConvertRunnable extends BindingRunnable { >+ private final Object value; >+ >+ ValidateAfterConvertRunnable(Object value) { >+ this.value = value; >+ } >+ >+ void doRun() { >+ updateValueStrategy.validateAfterConvert(value, this); >+ } >+ >+ public void doHandleStatus(IStatus status) { >+ if (!mergeStatus(multiStatus, status)) { >+ setValidationStatus(multiStatus); >+ } else if (policy == UpdateValueStrategy.POLICY_CONVERT >+ && !explicit) { >+ setValidationStatus(multiStatus); >+ } else { >+ source.getRealm() >+ .exec(new ValidateBeforeSetRunnable(value)); >+ } >+ } >+ } >+ >+ class ConvertRunnable extends BindingRunnable { >+ private final Object value; >+ >+ ConvertRunnable(Object value) { >+ this.value = value; >+ } >+ >+ void doRun() { >+ updateValueStrategy.convert(value, this); >+ } >+ >+ public void doHandleResult(Object result) { >+ source.getRealm() >+ .exec(new ValidateAfterConvertRunnable(result)); >+ } >+ } >+ >+ class GetSourceValueAndValidateRunnable extends BindingRunnable { >+ private Object value; >+ >+ void doRun() { >+ // Get source value >+ value = source.getValue(); >+ >+ // Validate after get >+ updateValueStrategy.validateAfterGet(value, this); >+ } >+ >+ public void doHandleStatus(IStatus result) { >+ if (mergeStatus(multiStatus, result)) { >+ source.getRealm().exec(new ConvertRunnable(value)); >+ } else { >+ setValidationStatus(multiStatus); >+ } >+ } >+ } >+ >+ source.getRealm().exec(new GetSourceValueAndValidateRunnable()); > } > > public void validateModelToTarget() { >@@ -228,7 +317,7 @@ > } > }); > } >- >+ > public void dispose() { > if (targetChangeListener != null) { > target.removeValueChangeListener(targetChangeListener); >@@ -242,5 +331,4 @@ > model = null; > super.dispose(); > } >- > } >Index: src/org/eclipse/core/databinding/Callback.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/Callback.java >diff -N src/org/eclipse/core/databinding/Callback.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/databinding/Callback.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,27 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 Matthew Hall 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: >+ * Matthew Hall - initial API and implementation >+ ******************************************************************************/ >+ >+package org.eclipse.core.databinding; >+ >+/** >+ * Asynchronous callback interface for receiving a result. >+ * >+ * @since 1.2 >+ */ >+public interface Callback { >+ /** >+ * Handles the given status. >+ * >+ * @param result >+ * the result object >+ */ >+ public void handleResult(Object result); >+} >Index: src/org/eclipse/core/databinding/StatusCallback.java >=================================================================== >RCS file: src/org/eclipse/core/databinding/StatusCallback.java >diff -N src/org/eclipse/core/databinding/StatusCallback.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/org/eclipse/core/databinding/StatusCallback.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,29 @@ >+/******************************************************************************* >+ * Copyright (c) 2008 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.core.databinding; >+ >+import org.eclipse.core.runtime.IStatus; >+ >+/** >+ * Asynchronous callback interface for receiving a status. >+ * >+ * @since 1.2 >+ */ >+public interface StatusCallback { >+ /** >+ * Handles the given status. >+ * >+ * @param status >+ * the status object >+ */ >+ public void handleStatus(IStatus status); >+}
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