comparison org.eclipse.core.databinding/src/org/eclipse/core/databinding/SetBinding.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) 2008 Matthew Hall 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 * Matthew Hall - initial API and implementation (bug 124684)
10 * IBM Corporation - through ListBinding.java
11 ******************************************************************************/
12
13 module org.eclipse.core.databinding.SetBinding;
14
15 import java.lang.all;
16
17 import java.util.Collections;
18 import java.util.Iterator;
19
20 import org.eclipse.core.databinding.observable.Diffs;
21 import org.eclipse.core.databinding.observable.set.IObservableSet;
22 import org.eclipse.core.databinding.observable.set.ISetChangeListener;
23 import org.eclipse.core.databinding.observable.set.SetChangeEvent;
24 import org.eclipse.core.databinding.observable.set.SetDiff;
25 import org.eclipse.core.databinding.observable.value.IObservableValue;
26 import org.eclipse.core.databinding.observable.value.WritableValue;
27 import org.eclipse.core.internal.databinding.BindingStatus;
28 import org.eclipse.core.runtime.IStatus;
29 import org.eclipse.core.runtime.MultiStatus;
30 import org.eclipse.core.runtime.Status;
31
32 /**
33 * @since 1.1
34 *
35 */
36 public class SetBinding : Binding {
37
38 private UpdateSetStrategy targetToModel;
39 private UpdateSetStrategy modelToTarget;
40 private IObservableValue validationStatusObservable;
41 private bool updatingTarget;
42 private bool updatingModel;
43
44 private ISetChangeListener targetChangeListener = new class() ISetChangeListener {
45 public void handleSetChange(SetChangeEvent event) {
46 if (!updatingTarget) {
47 doUpdate(cast(IObservableSet) getTarget(),
48 cast(IObservableSet) getModel(), event.diff, targetToModel,
49 false, false);
50 }
51 }
52 };
53
54 private ISetChangeListener modelChangeListener = new class() ISetChangeListener {
55 public void handleSetChange(SetChangeEvent event) {
56 if (!updatingModel) {
57 doUpdate(cast(IObservableSet) getModel(),
58 cast(IObservableSet) getTarget(), event.diff,
59 modelToTarget, false, false);
60 }
61 }
62 };
63
64 /**
65 * @param target
66 * @param model
67 * @param modelToTargetStrategy
68 * @param targetToModelStrategy
69 */
70 public this(IObservableSet target, IObservableSet model,
71 UpdateSetStrategy targetToModelStrategy,
72 UpdateSetStrategy modelToTargetStrategy) {
73 super(target, model);
74 this.targetToModel = targetToModelStrategy;
75 this.modelToTarget = modelToTargetStrategy;
76 if ((targetToModel.getUpdatePolicy() & UpdateSetStrategy.POLICY_UPDATE) !is 0) {
77 target.addSetChangeListener(targetChangeListener);
78 } else {
79 targetChangeListener = null;
80 }
81 if ((modelToTarget.getUpdatePolicy() & UpdateSetStrategy.POLICY_UPDATE) !is 0) {
82 model.addSetChangeListener(modelChangeListener);
83 } else {
84 modelChangeListener = null;
85 }
86 }
87
88 public IObservableValue getValidationStatus() {
89 return validationStatusObservable;
90 }
91
92 protected void preInit() {
93 validationStatusObservable = new WritableValue(context
94 .getValidationRealm(), Status.OK_STATUS, IStatus.classinfo);
95 }
96
97 protected void postInit() {
98 if (modelToTarget.getUpdatePolicy() is UpdateSetStrategy.POLICY_UPDATE) {
99 updateModelToTarget();
100 }
101 if (targetToModel.getUpdatePolicy() !is UpdateSetStrategy.POLICY_NEVER) {
102 validateTargetToModel();
103 }
104 }
105
106 public void updateModelToTarget() {
107 final IObservableSet modelSet = cast(IObservableSet) getModel();
108 modelSet.getRealm().exec(new class() Runnable {
109 public void run() {
110 SetDiff diff = Diffs.computeSetDiff(Collections.EMPTY_SET,
111 modelSet);
112 doUpdate(modelSet, cast(IObservableSet) getTarget(), diff,
113 modelToTarget, true, true);
114 }
115 });
116 }
117
118 public void updateTargetToModel() {
119 final IObservableSet targetSet = cast(IObservableSet) getTarget();
120 targetSet.getRealm().exec(new class() Runnable {
121 public void run() {
122 SetDiff diff = Diffs.computeSetDiff(Collections.EMPTY_SET,
123 targetSet);
124 doUpdate(targetSet, cast(IObservableSet) getModel(), diff,
125 targetToModel, true, true);
126 }
127 });
128 }
129
130 public void validateModelToTarget() {
131 // nothing for now
132 }
133
134 public void validateTargetToModel() {
135 // nothing for now
136 }
137
138 /*
139 * This method may be moved to UpdateSetStrategy in the future if clients
140 * need more control over how the two sets are kept in sync.
141 */
142 private void doUpdate(IObservableSet source,
143 IObservableSet destination, SetDiff diff,
144 UpdateSetStrategy updateSetStrategy, bool explicit,
145 bool clearDestination) {
146 final int policy = updateSetStrategy.getUpdatePolicy();
147 if (policy is UpdateSetStrategy.POLICY_NEVER)
148 return;
149 if (policy is UpdateSetStrategy.POLICY_ON_REQUEST && !explicit)
150 return;
151 destination.getRealm().exec(dgRunnable((IObservableSet destination_, SetDiff diff_, UpdateSetStrategy updateSetStrategy_, bool clearDestination_) {
152 if (destination_ is getTarget()) {
153 updatingTarget = true;
154 } else {
155 updatingModel = true;
156 }
157 MultiStatus multiStatus = BindingStatus.ok();
158
159 try {
160 if (clearDestination_) {
161 destination_.clear();
162 }
163
164 for (Iterator iterator = diff_.getRemovals().iterator(); iterator
165 .hasNext();) {
166 IStatus setterStatus = updateSetStrategy_.doRemove(
167 destination_, updateSetStrategy_.convert(iterator
168 .next()));
169
170 mergeStatus(multiStatus, setterStatus);
171 // TODO - at this point, the two sets
172 // will be out of sync if an error
173 // occurred...
174 }
175
176 for (Iterator iterator = diff_.getAdditions().iterator(); iterator
177 .hasNext();) {
178 IStatus setterStatus = updateSetStrategy_.doAdd(
179 destination_, updateSetStrategy_.convert(iterator
180 .next()));
181
182 mergeStatus(multiStatus, setterStatus);
183 // TODO - at this point, the two sets
184 // will be out of sync if an error
185 // occurred...
186 }
187 } finally {
188 validationStatusObservable.setValue(multiStatus);
189
190 if (destination_ is getTarget()) {
191 updatingTarget = false;
192 } else {
193 updatingModel = false;
194 }
195 }
196 }, destination, diff, updateSetStrategy, clearDestination_));
197 }
198
199 /**
200 * Merges the provided <code>newStatus</code> into the
201 * <code>multiStatus</code>.
202 *
203 * @param multiStatus
204 * @param newStatus
205 */
206 /* package */void mergeStatus(MultiStatus multiStatus, IStatus newStatus) {
207 if (!newStatus.isOK()) {
208 multiStatus.add(newStatus);
209 }
210 }
211
212 public void dispose() {
213 if (targetChangeListener !is null) {
214 (cast(IObservableSet) getTarget())
215 .removeSetChangeListener(targetChangeListener);
216 targetChangeListener = null;
217 }
218 if (modelChangeListener !is null) {
219 (cast(IObservableSet) getModel())
220 .removeSetChangeListener(modelChangeListener);
221 modelChangeListener = null;
222 }
223 super.dispose();
224 }
225 }