comparison org.eclipse.core.databinding/src/org/eclipse/core/databinding/ValueBinding.d @ 78:0a55d2d5a946

Added file for databinding
author Frank Benoit <benoit@tionex.de>
date Tue, 14 Apr 2009 11:35:29 +0200
parents
children 383ce7bd736b
comparison
equal deleted inserted replaced
76:f05e6e8b2f2d 78:0a55d2d5a946
1 /*******************************************************************************
2 * Copyright (c) 2007, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Matthew Hall - bug 220700
11 *******************************************************************************/
12
13 module org.eclipse.core.databinding.ValueBinding;
14
15 import java.lang.all;
16
17 import org.eclipse.core.databinding.observable.value.IObservableValue;
18 import org.eclipse.core.databinding.observable.value.IValueChangeListener;
19 import org.eclipse.core.databinding.observable.value.ValueChangeEvent;
20 import org.eclipse.core.databinding.observable.value.WritableValue;
21 import org.eclipse.core.databinding.util.Policy;
22 import org.eclipse.core.internal.databinding.BindingStatus;
23 import org.eclipse.core.internal.databinding.Util;
24 import org.eclipse.core.runtime.IStatus;
25 import org.eclipse.core.runtime.MultiStatus;
26 import org.eclipse.core.runtime.Status;
27
28 /**
29 * @since 1.0
30 *
31 */
32 class ValueBinding : Binding {
33 private final UpdateValueStrategy targetToModel;
34 private final UpdateValueStrategy modelToTarget;
35 private WritableValue validationStatusObservable;
36 private IObservableValue target;
37 private IObservableValue model;
38
39 private bool updatingTarget;
40 private bool updatingModel;
41 private IValueChangeListener targetChangeListener = new class() IValueChangeListener {
42 public void handleValueChange(ValueChangeEvent event) {
43 if (!updatingTarget && !Util.equals(event.diff.getOldValue(), event.diff.getNewValue())) {
44 doUpdate(target, model, targetToModel, false, false);
45 }
46 }
47 };
48 private IValueChangeListener modelChangeListener = new class() IValueChangeListener {
49 public void handleValueChange(ValueChangeEvent event) {
50 if (!updatingModel && !Util.equals(event.diff.getOldValue(), event.diff.getNewValue())) {
51 doUpdate(model, target, modelToTarget, false, false);
52 }
53 }
54 };
55
56 /**
57 * @param targetObservableValue
58 * @param modelObservableValue
59 * @param targetToModel
60 * @param modelToTarget
61 */
62 public this(IObservableValue targetObservableValue,
63 IObservableValue modelObservableValue,
64 UpdateValueStrategy targetToModel, UpdateValueStrategy modelToTarget) {
65 super(targetObservableValue, modelObservableValue);
66 this.target = targetObservableValue;
67 this.model = modelObservableValue;
68 this.targetToModel = targetToModel;
69 this.modelToTarget = modelToTarget;
70 if ((targetToModel.getUpdatePolicy() & (UpdateValueStrategy.POLICY_CONVERT | UpdateValueStrategy.POLICY_UPDATE)) !is 0) {
71 target.addValueChangeListener(targetChangeListener);
72 } else {
73 targetChangeListener = null;
74 }
75 if ((modelToTarget.getUpdatePolicy() & (UpdateValueStrategy.POLICY_CONVERT | UpdateValueStrategy.POLICY_UPDATE)) !is 0) {
76 model.addValueChangeListener(modelChangeListener);
77 } else {
78 modelChangeListener = null;
79 }
80 }
81
82 protected void preInit() {
83 validationStatusObservable = new WritableValue(context
84 .getValidationRealm(), Status.OK_STATUS, IStatus.classinfo);
85 }
86
87 protected void postInit() {
88 if (modelToTarget.getUpdatePolicy() is UpdateValueStrategy.POLICY_UPDATE) {
89 updateModelToTarget();
90 }
91 if (targetToModel.getUpdatePolicy() !is UpdateValueStrategy.POLICY_NEVER) {
92 validateTargetToModel();
93 }
94 }
95
96 public IObservableValue getValidationStatus() {
97 return validationStatusObservable;
98 }
99
100 public void updateTargetToModel() {
101 doUpdate(target, model, targetToModel, true, false);
102 }
103
104 public void updateModelToTarget() {
105 doUpdate(model, target, modelToTarget, true, false);
106 }
107
108 /**
109 * Incorporates the provided <code>newStats</code> into the
110 * <code>multieStatus</code>.
111 *
112 * @param multiStatus
113 * @param newStatus
114 * @return <code>true</code> if the update should proceed
115 */
116 /* package */bool mergeStatus(MultiStatus multiStatus, IStatus newStatus) {
117 if (!newStatus.isOK()) {
118 multiStatus.add(newStatus);
119 return multiStatus.getSeverity() < IStatus.ERROR;
120 }
121 return true;
122 }
123
124 /*
125 * This method may be moved to UpdateValueStrategy in the future if clients
126 * need more control over how the source value is copied to the destination
127 * observable.
128 */
129 private void doUpdate(IObservableValue source,
130 IObservableValue destination,
131 UpdateValueStrategy updateValueStrategy,
132 bool explicit, bool validateOnly) {
133
134 final int policy = updateValueStrategy.getUpdatePolicy();
135 if (policy is UpdateValueStrategy.POLICY_NEVER)
136 return;
137 if (policy is UpdateValueStrategy.POLICY_ON_REQUEST && !explicit)
138 return;
139
140 source.getRealm().exec(dgRunnable((
141 IObservableValue source_,
142 IObservableValue destination_,
143 UpdateValueStrategy updateValueStrategy_,
144 bool explicit_, bool validateOnly_) {
145 bool destinationRealmReached = false;
146 final MultiStatus multiStatus = BindingStatus.ok();
147 try {
148 // Get value
149 Object value = source_.getValue();
150
151 // Validate after get
152 IStatus status = updateValueStrategy_
153 .validateAfterGet(value);
154 if (!mergeStatus(multiStatus, status))
155 return;
156
157 // Convert value
158 final Object convertedValue = updateValueStrategy_
159 .convert(value);
160
161 // Validate after convert
162 status = updateValueStrategy_
163 .validateAfterConvert(convertedValue);
164 if (!mergeStatus(multiStatus, status))
165 return;
166 if (policy is UpdateValueStrategy.POLICY_CONVERT
167 && !explicit_)
168 return;
169
170 // Validate before set
171 status = updateValueStrategy_
172 .validateBeforeSet(convertedValue);
173 if (!mergeStatus(multiStatus, status))
174 return;
175 if (validateOnly_)
176 return;
177
178 // Set value
179 destinationRealmReached = true;
180 destination_.getRealm().exec(dgRunnable((
181 IObservableValue destination__,
182 UpdateValueStrategy updateValueStrategy__) {
183 if (destination__ is target) {
184 updatingTarget = true;
185 } else {
186 updatingModel = true;
187 }
188 try {
189 IStatus setterStatus = updateValueStrategy__
190 .doSet(destination__, convertedValue);
191
192 mergeStatus(multiStatus, setterStatus);
193 } finally {
194 if (destination__ is target) {
195 updatingTarget = false;
196 } else {
197 updatingModel = false;
198 }
199 setValidationStatus(multiStatus);
200 }
201 }, destination_, updateValueStrategy_ ));
202 } catch (Exception ex) {
203 // This check is necessary as in 3.2.2 Status
204 // doesn't accept a null message (bug 177264).
205 String message = (ex.getMessage() !is null) ? ex
206 .getMessage() : ""; //$NON-NLS-1$
207
208 mergeStatus(multiStatus, new Status(IStatus.ERROR,
209 Policy.JFACE_DATABINDING, IStatus.ERROR, message,
210 ex));
211 } finally {
212 if (!destinationRealmReached) {
213 setValidationStatus(multiStatus);
214 }
215
216 }
217 }, source, destination, updateValueStrategy, explicit, validateOnly));
218 }
219
220 public void validateModelToTarget() {
221 doUpdate(model, target, modelToTarget, true, true);
222 }
223
224 public void validateTargetToModel() {
225 doUpdate(target, model, targetToModel, true, true);
226 }
227
228 private void setValidationStatus( IStatus status) {
229 validationStatusObservable.getRealm().exec(dgRunnable((IStatus status_) {
230 validationStatusObservable.setValue(status_);
231 }, status));
232 }
233
234 public void dispose() {
235 if (targetChangeListener !is null) {
236 target.removeValueChangeListener(targetChangeListener);
237 targetChangeListener = null;
238 }
239 if (modelChangeListener !is null) {
240 model.removeValueChangeListener(modelChangeListener);
241 modelChangeListener = null;
242 }
243 target = null;
244 model = null;
245 super.dispose();
246 }
247
248 }