Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 194734 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/core/databinding/property/set/SimpleSetPropertyObservableSet.java (-51 / +142 lines)
Lines 57-63 Link Here
57
57
58
	protected void firstListenerAdded() {
58
	protected void firstListenerAdded() {
59
		if (!isDisposed()) {
59
		if (!isDisposed()) {
60
			cachedSet = property.getSet(source);
60
			cachedSet = getSet();
61
61
62
			if (listener == null) {
62
			if (listener == null) {
63
				listener = property
63
				listener = property
Lines 96-102 Link Here
96
	}
96
	}
97
97
98
	protected Set getWrappedSet() {
98
	protected Set getWrappedSet() {
99
		return property.getSet(source);
99
		return getSet();
100
	}
100
	}
101
101
102
	public Object getElementType() {
102
	public Object getElementType() {
Lines 105-112 Link Here
105
105
106
	// Queries
106
	// Queries
107
107
108
	private Set getSet() {
109
		return property.getSet(source);
110
	}
111
112
	public boolean contains(Object o) {
113
		getterCalled();
114
		return getSet().contains(o);
115
	}
116
117
	public boolean containsAll(Collection c) {
118
		getterCalled();
119
		return getSet().containsAll(c);
120
	}
121
108
	protected int doGetSize() {
122
	protected int doGetSize() {
109
		return property.size(source);
123
		return getSet().size();
124
	}
125
126
	public boolean isEmpty() {
127
		getterCalled();
128
		return getSet().isEmpty();
129
	}
130
131
	public Object[] toArray() {
132
		getterCalled();
133
		return getSet().toArray();
134
	}
135
136
	public Object[] toArray(Object[] a) {
137
		getterCalled();
138
		return getSet().toArray(a);
110
	}
139
	}
111
140
112
	// Single change operations
141
	// Single change operations
Lines 114-135 Link Here
114
	public boolean add(Object o) {
143
	public boolean add(Object o) {
115
		checkRealm();
144
		checkRealm();
116
145
117
		boolean changed;
146
		Set set = new HashSet(getSet());
147
		if (!set.add(o))
148
			return false;
149
150
		SetDiff diff = Diffs.createSetDiff(Collections.singleton(o),
151
				Collections.EMPTY_SET);
118
152
119
		boolean wasUpdating = updating;
153
		boolean wasUpdating = updating;
154
		boolean changed;
120
		updating = true;
155
		updating = true;
121
		try {
156
		try {
122
			changed = property.add(source, o);
157
			changed = property.setSet(source, set, diff);
123
			modCount++;
158
			modCount++;
124
		} finally {
159
		} finally {
125
			updating = wasUpdating;
160
			updating = wasUpdating;
126
		}
161
		}
127
162
128
		cachedSet = property.getSet(source);
163
		if (changed) {
129
164
			cachedSet = getSet();
130
		if (changed)
165
			fireSetChange(diff);
131
			fireSetChange(Diffs.createSetDiff(Collections.singleton(o),
166
		}
132
					Collections.EMPTY_SET));
133
167
134
		return changed;
168
		return changed;
135
	}
169
	}
Lines 138-156 Link Here
138
		getterCalled();
172
		getterCalled();
139
		return new Iterator() {
173
		return new Iterator() {
140
			int expectedModCount = modCount;
174
			int expectedModCount = modCount;
141
			Iterator delegate = new HashSet(property.getSet(source)).iterator();
175
			Set set = new HashSet(getSet());
176
			Iterator iterator = set.iterator();
142
			Object last = null;
177
			Object last = null;
143
178
144
			public boolean hasNext() {
179
			public boolean hasNext() {
145
				getterCalled();
180
				getterCalled();
146
				checkForComodification();
181
				checkForComodification();
147
				return delegate.hasNext();
182
				return iterator.hasNext();
148
			}
183
			}
149
184
150
			public Object next() {
185
			public Object next() {
151
				getterCalled();
186
				getterCalled();
152
				checkForComodification();
187
				checkForComodification();
153
				last = delegate.next();
188
				last = iterator.next();
154
				return last;
189
				return last;
155
			}
190
			}
156
191
Lines 158-181 Link Here
158
				checkRealm();
193
				checkRealm();
159
				checkForComodification();
194
				checkForComodification();
160
195
161
				delegate.remove(); // stay in sync
196
				iterator.remove(); // stay in sync
197
				SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET,
198
						Collections.singleton(last));
162
199
163
				boolean wasUpdating = updating;
200
				boolean wasUpdating = updating;
201
				boolean changed;
164
				updating = true;
202
				updating = true;
165
				try {
203
				try {
166
					property.remove(source, last);
204
					changed = property.setSet(source, set, diff);
167
					modCount++;
205
					modCount++;
168
				} finally {
206
				} finally {
169
					updating = wasUpdating;
207
					updating = wasUpdating;
170
				}
208
				}
171
209
172
				cachedSet = property.getSet(source);
210
				if (changed) {
211
					cachedSet = getSet();
212
					fireSetChange(diff);
173
213
174
				fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET,
214
					last = null;
175
						Collections.singleton(last)));
215
					expectedModCount = modCount;
176
216
				}
177
				last = null;
178
				expectedModCount = modCount;
179
			}
217
			}
180
218
181
			private void checkForComodification() {
219
			private void checkForComodification() {
Lines 188-207 Link Here
188
	public boolean remove(Object o) {
226
	public boolean remove(Object o) {
189
		getterCalled();
227
		getterCalled();
190
228
191
		boolean changed;
229
		Set set = new HashSet(getSet());
230
		if (!set.remove(o))
231
			return false;
232
233
		SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, Collections
234
				.singleton(o));
192
235
193
		boolean wasUpdating = updating;
236
		boolean wasUpdating = updating;
237
		boolean changed;
194
		updating = true;
238
		updating = true;
195
		try {
239
		try {
196
			changed = property.remove(source, o);
240
			changed = property.setSet(source, set, diff);
197
			modCount++;
241
			modCount++;
198
		} finally {
242
		} finally {
199
			updating = wasUpdating;
243
			updating = wasUpdating;
200
		}
244
		}
201
245
202
		cachedSet = property.getSet(source);
246
		if (changed) {
203
		fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, Collections
247
			cachedSet = property.getSet(source);
204
				.singleton(o)));
248
			fireSetChange(diff);
249
		}
205
250
206
		return changed;
251
		return changed;
207
	}
252
	}
Lines 214-269 Link Here
214
		if (c.isEmpty())
259
		if (c.isEmpty())
215
			return false;
260
			return false;
216
261
262
		Set set = new HashSet(getSet());
263
217
		Set additions = new HashSet(c);
264
		Set additions = new HashSet(c);
218
		additions.removeAll(property.getSet(source));
265
		for (Iterator it = c.iterator(); it.hasNext();) {
266
			Object element = it.next();
267
			if (set.add(element))
268
				additions.add(element);
269
		}
270
219
		if (additions.isEmpty())
271
		if (additions.isEmpty())
220
			return false;
272
			return false;
221
273
274
		SetDiff diff = Diffs.createSetDiff(additions, Collections.EMPTY_SET);
275
222
		boolean wasUpdating = updating;
276
		boolean wasUpdating = updating;
277
		boolean changed;
223
		updating = true;
278
		updating = true;
224
		try {
279
		try {
225
			property.addAll(source, c);
280
			changed = property.setSet(source, set, diff);
226
			modCount++;
281
			modCount++;
227
		} finally {
282
		} finally {
228
			updating = wasUpdating;
283
			updating = wasUpdating;
229
		}
284
		}
230
285
231
		cachedSet = property.getSet(source);
286
		if (changed) {
232
		fireSetChange(Diffs.createSetDiff(additions, Collections.EMPTY_SET));
287
			cachedSet = property.getSet(source);
288
			fireSetChange(diff);
289
		}
233
290
234
		return true;
291
		return changed;
235
	}
292
	}
236
293
237
	public boolean removeAll(Collection c) {
294
	public boolean removeAll(Collection c) {
238
		getterCalled();
295
		getterCalled();
239
296
240
		if (property.isEmpty(source) || c.isEmpty())
297
		Set set = getSet();
298
		if (set.isEmpty())
299
			return false;
300
		if (c.isEmpty())
241
			return false;
301
			return false;
242
302
303
		set = new HashSet(set);
304
243
		Set removals = new HashSet(c);
305
		Set removals = new HashSet(c);
244
		removals.retainAll(property.getSet(source));
306
		for (Iterator it = c.iterator(); it.hasNext();) {
307
			Object element = it.next();
308
			if (set.remove(element))
309
				removals.add(element);
310
		}
311
245
		if (removals.isEmpty())
312
		if (removals.isEmpty())
246
			return false;
313
			return false;
247
314
315
		SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, removals);
316
248
		boolean wasUpdating = updating;
317
		boolean wasUpdating = updating;
318
		boolean changed;
249
		updating = true;
319
		updating = true;
250
		try {
320
		try {
251
			property.removeAll(source, c);
321
			changed = property.setSet(source, set, diff);
252
			modCount++;
322
			modCount++;
253
		} finally {
323
		} finally {
254
			updating = wasUpdating;
324
			updating = wasUpdating;
255
		}
325
		}
256
326
257
		cachedSet = property.getSet(source);
327
		if (changed) {
258
		fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removals));
328
			cachedSet = property.getSet(source);
329
			fireSetChange(diff);
330
		}
259
331
260
		return true;
332
		return changed;
261
	}
333
	}
262
334
263
	public boolean retainAll(Collection c) {
335
	public boolean retainAll(Collection c) {
264
		getterCalled();
336
		getterCalled();
265
337
266
		if (property.isEmpty(source))
338
		Set set = getSet();
339
		if (set.isEmpty())
267
			return false;
340
			return false;
268
341
269
		if (c.isEmpty()) {
342
		if (c.isEmpty()) {
Lines 271-325 Link Here
271
			return true;
344
			return true;
272
		}
345
		}
273
346
274
		Set removals = new HashSet(property.getSet(source));
347
		set = new HashSet(set);
275
		removals.removeAll(c);
348
349
		Set removals = new HashSet();
350
		for (Iterator it = set.iterator(); it.hasNext();) {
351
			Object element = it.next();
352
			if (!c.contains(element)) {
353
				it.remove();
354
				removals.add(element);
355
			}
356
		}
357
276
		if (removals.isEmpty())
358
		if (removals.isEmpty())
277
			return false;
359
			return false;
278
360
361
		SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, removals);
362
279
		boolean wasUpdating = updating;
363
		boolean wasUpdating = updating;
364
		boolean changed;
280
		updating = true;
365
		updating = true;
281
		try {
366
		try {
282
			property.retainAll(source, c);
367
			changed = property.setSet(source, set, diff);
283
			modCount++;
368
			modCount++;
284
		} finally {
369
		} finally {
285
			updating = wasUpdating;
370
			updating = wasUpdating;
286
		}
371
		}
287
372
288
		cachedSet = property.getSet(source);
373
		if (changed) {
289
		fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removals));
374
			cachedSet = property.getSet(source);
375
			fireSetChange(diff);
376
		}
290
377
291
		return true;
378
		return changed;
292
	}
379
	}
293
380
294
	public void clear() {
381
	public void clear() {
295
		getterCalled();
382
		getterCalled();
296
383
297
		if (property.isEmpty(source))
384
		Set set = getSet();
385
		if (set.isEmpty())
298
			return;
386
			return;
299
387
300
		Set removals = new HashSet(property.getSet(source));
388
		SetDiff diff = Diffs.createSetDiff(Collections.EMPTY_SET, set);
301
389
302
		boolean wasUpdating = updating;
390
		boolean wasUpdating = updating;
391
		boolean changed;
303
		updating = true;
392
		updating = true;
304
		try {
393
		try {
305
			property.clear(source);
394
			changed = property.setSet(source, Collections.EMPTY_SET, diff);
306
			modCount++;
395
			modCount++;
307
		} finally {
396
		} finally {
308
			updating = wasUpdating;
397
			updating = wasUpdating;
309
		}
398
		}
310
399
311
		cachedSet = property.getSet(source);
400
		if (changed) {
312
		fireSetChange(Diffs.createSetDiff(Collections.EMPTY_SET, removals));
401
			cachedSet = property.getSet(source);
402
			fireSetChange(diff);
403
		}
313
	}
404
	}
314
405
315
	public boolean equals(Object o) {
406
	public boolean equals(Object o) {
316
		getterCalled();
407
		getterCalled();
317
		return property.equals(source, o);
408
		return getSet().equals(o);
318
	}
409
	}
319
410
320
	public int hashCode() {
411
	public int hashCode() {
321
		getterCalled();
412
		getterCalled();
322
		return property.hashCode(source);
413
		return getSet().hashCode();
323
	}
414
	}
324
415
325
	public Object getObserved() {
416
	public Object getObserved() {
(-)src/org/eclipse/core/databinding/property/set/SimpleSetProperty.java (-294 / +21 lines)
Lines 11-23 Link Here
11
11
12
package org.eclipse.core.databinding.property.set;
12
package org.eclipse.core.databinding.property.set;
13
13
14
import java.util.Collection;
15
import java.util.Collections;
14
import java.util.Collections;
16
import java.util.HashSet;
17
import java.util.Iterator;
18
import java.util.Set;
15
import java.util.Set;
19
16
20
import org.eclipse.core.databinding.observable.Diffs;
21
import org.eclipse.core.databinding.observable.IObservable;
17
import org.eclipse.core.databinding.observable.IObservable;
22
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.core.databinding.observable.Realm;
23
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
19
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
Lines 53-58 Link Here
53
		this.elementType = elementType;
49
		this.elementType = elementType;
54
	}
50
	}
55
51
52
	public IObservableSet observeSet(Realm realm, Object source) {
53
		return new SimpleSetPropertyObservableSet(realm, source, this);
54
	}
55
56
	public IObservableSet observeDetailSet(IObservableValue master) {
57
		final Realm realm = master.getRealm();
58
		IObservableFactory factory = new IObservableFactory() {
59
			public IObservable createObservable(Object target) {
60
				return SimpleSetProperty.this.observeSet(realm, target);
61
			}
62
		};
63
		return MasterDetailObservables.detailSet(master, factory,
64
				getElementType());
65
	}
66
56
	/**
67
	/**
57
	 * Returns the type of the elements in the collection or <code>null</code>
68
	 * Returns the type of the elements in the collection or <code>null</code>
58
	 * if untyped
69
	 * if untyped
Lines 65-101 Link Here
65
		return elementType;
76
		return elementType;
66
	}
77
	}
67
78
68
	/**
79
	// Accessors
69
	 * Returns whether the source's collection property contains the given
70
	 * element.
71
	 * 
72
	 * @param source
73
	 *            the property source
74
	 * @param o
75
	 *            the element
76
	 * @return whether the source's collection property contains the given
77
	 *         element.
78
	 * @noreference This method is not intended to be referenced by clients.
79
	 */
80
	protected boolean contains(Object source, Object o) {
81
		return getSet(source).contains(o);
82
	}
83
84
	/**
85
	 * Returns whether the source's collection property contains all elements in
86
	 * the given collection
87
	 * 
88
	 * @param source
89
	 *            the property source
90
	 * @param c
91
	 *            the collection of elements to test for
92
	 * @return whether the source's collection property contains all elements in
93
	 *         the given collection
94
	 * @noreference This method is not intended to be referenced by clients.
95
	 */
96
	protected boolean containsAll(Object source, Collection c) {
97
		return getSet(source).containsAll(c);
98
	}
99
80
100
	/**
81
	/**
101
	 * Returns a Set with the current contents of the source's set property
82
	 * Returns a Set with the current contents of the source's set property
Lines 121-205 Link Here
121
	 */
102
	 */
122
	protected abstract Set doGetSet(Object source);
103
	protected abstract Set doGetSet(Object source);
123
104
124
	/**
105
	// Mutators
125
	 * Returns whether the source's collection property is equal to the
126
	 * argument.
127
	 * 
128
	 * @param source
129
	 *            the property source
130
	 * @param o
131
	 *            the object to test for equality to the source's collection
132
	 *            property
133
	 * @return whether the source's collection property is equal to the argument
134
	 * @noreference This method is not intended to be referenced by clients.
135
	 */
136
	protected boolean equals(Object source, Object o) {
137
		return getSet(source).equals(o);
138
	}
139
140
	/**
141
	 * Returns the hash code of the source's collection property.
142
	 * 
143
	 * @param source
144
	 *            the property source
145
	 * @return the hash code of the source's collection property
146
	 * @noreference This method is not intended to be referenced by clients.
147
	 */
148
	protected int hashCode(Object source) {
149
		return getSet(source).hashCode();
150
	}
151
152
	/**
153
	 * Returns whether the source's collection property is empty
154
	 * 
155
	 * @param source
156
	 *            the property source
157
	 * @return whether the source's collection property is empty
158
	 * @noreference This method is not intended to be referenced by clients.
159
	 */
160
	protected boolean isEmpty(Object source) {
161
		return getSet(source).isEmpty();
162
	}
163
164
	/**
165
	 * Returns the size of the source's collection property
166
	 * 
167
	 * @param source
168
	 *            the property source
169
	 * @return the size of the source's collection property
170
	 * @noreference This method is not intended to be referenced by clients.
171
	 */
172
	protected int size(Object source) {
173
		return getSet(source).size();
174
	}
175
176
	/**
177
	 * Returns an array of all elements in the source's collection property
178
	 * 
179
	 * @param source
180
	 *            the property source
181
	 * @param array
182
	 *            the array into which the elements will be copied. If the array
183
	 *            is not large enough to hold all elements, the elements will be
184
	 *            returned in a new array of the same runtime type.
185
	 * @return an array of all elements in the source's collection property
186
	 * @noreference This method is not intended to be referenced by clients.
187
	 */
188
	protected Object[] toArray(Object source, Object[] array) {
189
		return getSet(source).toArray(array);
190
	}
191
192
	/**
193
	 * Returns an array of all elements in the source's collection property
194
	 * 
195
	 * @param source
196
	 *            the property source
197
	 * @return an array of all elements in the source's collection property
198
	 * @noreference This method is not intended to be referenced by clients.
199
	 */
200
	protected Object[] toArray(Object source) {
201
		return getSet(source).toArray();
202
	}
203
106
204
	/**
107
	/**
205
	 * Updates the property on the source with the specified change.
108
	 * Updates the property on the source with the specified change.
Lines 210-383 Link Here
210
	 *            the new set
113
	 *            the new set
211
	 * @param diff
114
	 * @param diff
212
	 *            a diff describing the change
115
	 *            a diff describing the change
116
	 * @return true if the property was modified on the source object, false
117
	 *         otherwise
213
	 * @noreference This method is not intended to be referenced by clients.
118
	 * @noreference This method is not intended to be referenced by clients.
214
	 */
119
	 */
215
	protected abstract void setSet(Object source, Set set, SetDiff diff);
120
	protected abstract boolean setSet(Object source, Set set, SetDiff diff);
216
217
	/**
218
	 * Adds the element to the source's collection property
219
	 * 
220
	 * @param source
221
	 *            the property source
222
	 * @param o
223
	 *            the element to add
224
	 * @return whether the element was added to the source's collection property
225
	 * @noreference This method is not intended to be referenced by clients.
226
	 */
227
	protected boolean add(Object source, Object o) {
228
		Set set = getSet(source);
229
		if (!set.contains(o)) {
230
			set = new HashSet(set);
231
			boolean added = set.add(o);
232
			if (added) {
233
				setSet(source, set, Diffs.createSetDiff(Collections
234
						.singleton(o), Collections.EMPTY_SET));
235
			}
236
			return added;
237
		}
238
		return false;
239
	}
240
241
	/**
242
	 * Adds all elements in the specified collection to the source's collection
243
	 * property.
244
	 * 
245
	 * @param source
246
	 *            the property source
247
	 * @param c
248
	 *            the collection of elements to add.
249
	 * @return whether the source's collection property was changed
250
	 * @noreference This method is not intended to be referenced by clients.
251
	 */
252
	protected boolean addAll(Object source, Collection c) {
253
		if (c.isEmpty())
254
			return false;
255
256
		Set set = getSet(source);
257
		Set additions = new HashSet();
258
		for (Iterator it = c.iterator(); it.hasNext();) {
259
			Object o = it.next();
260
			if (!set.contains(o)) {
261
				additions.add(o);
262
			}
263
		}
264
		boolean changed = !additions.isEmpty();
265
		if (changed) {
266
			set = new HashSet(set);
267
			set.addAll(additions);
268
269
			setSet(source, set, Diffs.createSetDiff(additions,
270
					Collections.EMPTY_SET));
271
		}
272
		return changed;
273
	}
274
275
	/**
276
	 * Removes all elements from the source's collection property.
277
	 * 
278
	 * @param source
279
	 *            the property source
280
	 * @noreference This method is not intended to be referenced by clients.
281
	 */
282
	protected void clear(Object source) {
283
		if (!isEmpty(source)) {
284
			setSet(source, new HashSet(), Diffs.createSetDiff(
285
					Collections.EMPTY_SET, getSet(source)));
286
		}
287
	}
288
289
	/**
290
	 * Removes the element from the source's collection property
291
	 * 
292
	 * @param source
293
	 *            the property source
294
	 * @param o
295
	 *            the element to remove
296
	 * @return whether the element was removed from the source's collection
297
	 *         property
298
	 * @noreference This method is not intended to be referenced by clients.
299
	 */
300
	protected boolean remove(Object source, Object o) {
301
		Set set = getSet(source);
302
		if (set.contains(o)) {
303
			set = new HashSet(set);
304
			boolean removed = set.remove(o);
305
			if (removed) {
306
				setSet(source, set, Diffs.createSetDiff(Collections.EMPTY_SET,
307
						Collections.singleton(o)));
308
			}
309
			return removed;
310
		}
311
		return false;
312
	}
313
314
	/**
315
	 * Removes all elements from the source's collection property which are
316
	 * contained in the specified collection.
317
	 * 
318
	 * @param source
319
	 *            the property source
320
	 * @param c
321
	 *            the collection of elements to be removed
322
	 * @return whether the source's collection property was changed
323
	 * @noreference This method is not intended to be referenced by clients.
324
	 */
325
	protected boolean removeAll(Object source, Collection c) {
326
		if (c.isEmpty())
327
			return false;
328
329
		Set set = new HashSet(getSet(source));
330
		Set removals = new HashSet();
331
		for (Iterator it = set.iterator(); it.hasNext();) {
332
			Object o = it.next();
333
			if (c.contains(o)) {
334
				removals.add(o);
335
				it.remove();
336
			}
337
		}
338
		boolean changed = !removals.isEmpty();
339
		if (changed) {
340
			setSet(source, set, Diffs.createSetDiff(Collections.EMPTY_SET,
341
					removals));
342
		}
343
		return changed;
344
	}
345
121
346
	/**
122
	// Listeners
347
	 * Removes all elements from the source's collection property which are not
348
	 * contained in the specified collection.
349
	 * 
350
	 * @param source
351
	 *            the property source
352
	 * @param c
353
	 *            the collection of elements to retain
354
	 * @return whether the source's collection property was changed
355
	 * @noreference This method is not intended to be referenced by clients.
356
	 */
357
	protected boolean retainAll(Object source, Collection c) {
358
		if (isEmpty(source))
359
			return false;
360
		if (c.isEmpty()) {
361
			clear(source);
362
			return true;
363
		}
364
365
		Set set = new HashSet(getSet(source));
366
		Set removals = new HashSet();
367
		for (Iterator it = set.iterator(); it.hasNext();) {
368
			Object o = it.next();
369
			if (!c.contains(o)) {
370
				removals.add(o);
371
				it.remove();
372
			}
373
		}
374
		boolean changed = !removals.isEmpty();
375
		if (changed) {
376
			setSet(source, set, Diffs.createSetDiff(Collections.EMPTY_SET,
377
					removals));
378
		}
379
		return changed;
380
	}
381
123
382
	/**
124
	/**
383
	 * Returns a listener which implements the correct listener interface for
125
	 * Returns a listener which implements the correct listener interface for
Lines 430-448 Link Here
430
	 */
172
	 */
431
	protected abstract void removeListener(Object source,
173
	protected abstract void removeListener(Object source,
432
			INativePropertyListener listener);
174
			INativePropertyListener listener);
433
434
	public IObservableSet observeSet(Realm realm, Object source) {
435
		return new SimpleSetPropertyObservableSet(realm, source, this);
436
	}
437
438
	public IObservableSet observeDetailSet(IObservableValue master) {
439
		final Realm realm = master.getRealm();
440
		IObservableFactory factory = new IObservableFactory() {
441
			public IObservable createObservable(Object target) {
442
				return SimpleSetProperty.this.observeSet(realm, target);
443
			}
444
		};
445
		return MasterDetailObservables.detailSet(master, factory,
446
				getElementType());
447
	}
448
}
175
}
(-)src/org/eclipse/core/databinding/property/map/SimpleMapProperty.java (-231 / +35 lines)
Lines 12-24 Link Here
12
package org.eclipse.core.databinding.property.map;
12
package org.eclipse.core.databinding.property.map;
13
13
14
import java.util.Collections;
14
import java.util.Collections;
15
import java.util.HashMap;
16
import java.util.HashSet;
17
import java.util.Iterator;
18
import java.util.Map;
15
import java.util.Map;
19
import java.util.Set;
20
16
21
import org.eclipse.core.databinding.observable.Diffs;
22
import org.eclipse.core.databinding.observable.IObservable;
17
import org.eclipse.core.databinding.observable.IObservable;
23
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.core.databinding.observable.Realm;
24
import org.eclipse.core.databinding.observable.map.IObservableMap;
19
import org.eclipse.core.databinding.observable.map.IObservableMap;
Lines 27-33 Link Here
27
import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables;
22
import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables;
28
import org.eclipse.core.databinding.observable.value.IObservableValue;
23
import org.eclipse.core.databinding.observable.value.IObservableValue;
29
import org.eclipse.core.databinding.property.INativePropertyListener;
24
import org.eclipse.core.databinding.property.INativePropertyListener;
30
import org.eclipse.core.internal.databinding.Util;
31
25
32
/**
26
/**
33
 * Simplified abstract implementation of IMapProperty. This class takes care of
27
 * Simplified abstract implementation of IMapProperty. This class takes care of
Lines 58-63 Link Here
58
		this.valueType = valueType;
52
		this.valueType = valueType;
59
	}
53
	}
60
54
55
	public IObservableMap observeMap(Realm realm, Object source) {
56
		return new SimpleMapPropertyObservableMap(realm, source, this);
57
	}
58
59
	public IObservableMap observeDetailMap(IObservableValue master) {
60
		final Realm realm = master.getRealm();
61
		IObservableFactory factory = new IObservableFactory() {
62
			public IObservable createObservable(Object target) {
63
				return SimpleMapProperty.this.observeMap(realm, target);
64
			}
65
		};
66
		return MasterDetailObservables.detailMap(master, factory);
67
	}
68
61
	/**
69
	/**
62
	 * Returns the element type of the map's key set or <code>null</code> if the
70
	 * Returns the element type of the map's key set or <code>null</code> if the
63
	 * key set is untyped.
71
	 * key set is untyped.
Lines 82-87 Link Here
82
		return valueType;
90
		return valueType;
83
	}
91
	}
84
92
93
	// Accessors
94
85
	/**
95
	/**
86
	 * Returns an unmodifiable Map with the current contents of the source's map
96
	 * Returns an unmodifiable Map with the current contents of the source's map
87
	 * property.
97
	 * property.
Lines 105-110 Link Here
105
	 */
115
	 */
106
	protected abstract Map doGetMap(Object source);
116
	protected abstract Map doGetMap(Object source);
107
117
118
	// Mutators
119
120
	/**
121
	 * Updates the property on the source with the specified change.
122
	 * 
123
	 * @param source
124
	 *            the property source
125
	 * @param map
126
	 *            the new map
127
	 * @param diff
128
	 *            a diff describing the change
129
	 * @return true if the property was modified on the source object, false
130
	 *         otherwise
131
	 * @noreference This method is not intended to be referenced by clients.
132
	 */
133
	protected abstract boolean setMap(Object source, Map map, MapDiff diff);
134
135
	// Listeners
136
108
	/**
137
	/**
109
	 * Returns a listener which implements the correct listener interface for
138
	 * Returns a listener which implements the correct listener interface for
110
	 * the expected source object, and which parlays property change events from
139
	 * the expected source object, and which parlays property change events from
Lines 155-383 Link Here
155
	 */
184
	 */
156
	protected abstract void removeListener(Object source,
185
	protected abstract void removeListener(Object source,
157
			INativePropertyListener listener);
186
			INativePropertyListener listener);
158
159
	/**
160
	 * Returns whether the specified key is contained in the key set of the
161
	 * source's map property
162
	 * 
163
	 * @param source
164
	 *            the property source
165
	 * @param key
166
	 *            the key
167
	 * @return whether the specified key is contained in the key set of the
168
	 *         source's map property
169
	 * @noreference This method is not intended to be referenced by clients.
170
	 */
171
	protected boolean containsKey(Object source, Object key) {
172
		return getMap(source).containsKey(key);
173
	}
174
175
	/**
176
	 * Returns whether the specified value is contains in the values collection
177
	 * of the source's map property
178
	 * 
179
	 * @param source
180
	 *            the property source
181
	 * @param value
182
	 *            the value
183
	 * @return whether the specified value is contains in the values collection
184
	 *         of the source's map property
185
	 * @noreference This method is not intended to be referenced by clients.
186
	 */
187
	protected boolean containsValue(Object source, Object value) {
188
		return getMap(source).containsValue(value);
189
	}
190
191
	/**
192
	 * Returns whether the source's map property is equal to the argument
193
	 * 
194
	 * @param source
195
	 *            the property source
196
	 * @param o
197
	 *            the object to test for equality
198
	 * @return whether the source's map property is equal to the argument
199
	 * @noreference This method is not intended to be referenced by clients.
200
	 */
201
	protected boolean equals(Object source, Object o) {
202
		return getMap(source).equals(o);
203
	}
204
205
	/**
206
	 * Returns the value associated with the specified key in the source's map
207
	 * property
208
	 * 
209
	 * @param source
210
	 *            the property source
211
	 * @param key
212
	 *            the key
213
	 * @return the value associated with the specified key in the source's map
214
	 *         property
215
	 * @noreference This method is not intended to be referenced by clients.
216
	 */
217
	protected Object get(Object source, Object key) {
218
		return getMap(source).get(key);
219
	}
220
221
	/**
222
	 * Returns the hash code of the source's map property
223
	 * 
224
	 * @param source
225
	 *            the property source
226
	 * @return the hash code of the source's map property
227
	 * @noreference This method is not intended to be referenced by clients.
228
	 */
229
	protected int hashCode(Object source) {
230
		return getMap(source).hashCode();
231
	}
232
233
	/**
234
	 * Returns whether the source's map property is empty
235
	 * 
236
	 * @param source
237
	 *            the property source
238
	 * @return whether the source's map property is empty
239
	 * @noreference This method is not intended to be referenced by clients.
240
	 */
241
	protected boolean isEmpty(Object source) {
242
		return getMap(source).isEmpty();
243
	}
244
245
	/**
246
	 * Returns the size of the source's map property
247
	 * 
248
	 * @param source
249
	 *            the property source
250
	 * @return the size of the source's map property
251
	 * @noreference This method is not intended to be referenced by clients.
252
	 */
253
	protected int size(Object source) {
254
		return getMap(source).size();
255
	}
256
257
	/**
258
	 * Updates the property on the source with the specified change.
259
	 * 
260
	 * @param source
261
	 *            the property source
262
	 * @param map
263
	 *            the new map
264
	 * @param diff
265
	 *            a diff describing the change
266
	 * @noreference This method is not intended to be referenced by clients.
267
	 */
268
	protected abstract void setMap(Object source, Map map, MapDiff diff);
269
270
	/**
271
	 * Removes all mapping from the source's map property
272
	 * 
273
	 * @param source
274
	 *            the property source
275
	 * @noreference This method is not intended to be referenced by clients.
276
	 */
277
	protected void clear(Object source) {
278
		if (!isEmpty(source)) {
279
			setMap(source, new HashMap(), Diffs
280
					.createMapDiffRemoveAll(new HashMap(getMap(source))));
281
		}
282
	}
283
284
	/**
285
	 * Associates the specified value with the specified key in the source's map
286
	 * property
287
	 * 
288
	 * @param source
289
	 *            the property source
290
	 * @param key
291
	 *            the key
292
	 * @param value
293
	 *            the value
294
	 * @return the value that was previously associated with the given key in
295
	 *         the source's map property
296
	 * @noreference This method is not intended to be referenced by clients.
297
	 */
298
	protected Object put(Object source, Object key, Object value) {
299
		Map map = new HashMap(getMap(source));
300
		boolean addition = !map.containsKey(key);
301
		Object result = map.put(key, value);
302
		MapDiff diff;
303
		if (addition) {
304
			diff = Diffs.createMapDiffSingleAdd(key, value);
305
		} else {
306
			diff = Diffs.createMapDiffSingleChange(key, result, value);
307
		}
308
		setMap(source, map, diff);
309
		return result;
310
	}
311
312
	/**
313
	 * Adds all mappings in the specified map to the source's map property.
314
	 * 
315
	 * @param source
316
	 *            the property source
317
	 * @param t
318
	 *            the map
319
	 * @noreference This method is not intended to be referenced by clients.
320
	 */
321
	protected void putAll(Object source, Map t) {
322
		if (t.isEmpty())
323
			return;
324
325
		Map map = new HashMap(getMap(source));
326
		Set addedKeys = new HashSet();
327
		Set changedKeys = new HashSet();
328
		Map oldValues = new HashMap();
329
		Map newValues = new HashMap();
330
		for (Iterator it = t.entrySet().iterator(); it.hasNext();) {
331
			Map.Entry entry = (Map.Entry) it.next();
332
			Object key = entry.getKey();
333
			Object newValue = entry.getValue();
334
			boolean addition = !map.containsKey(key);
335
			Object oldValue = map.put(key, newValue);
336
			if (addition) {
337
				addedKeys.add(key);
338
			} else if (!Util.equals(oldValue, newValue)) {
339
				changedKeys.add(key);
340
				oldValues.put(key, oldValue);
341
			}
342
			newValues.put(key, newValue);
343
		}
344
		setMap(source, map, Diffs.createMapDiff(addedKeys,
345
				Collections.EMPTY_SET, changedKeys, oldValues, newValues));
346
	}
347
348
	/**
349
	 * Removes the mapping for the specified key from the source's map property
350
	 * 
351
	 * @param source
352
	 *            the property source
353
	 * @param key
354
	 *            the key
355
	 * @return the value that was previously associated with the specified key
356
	 *         in the source's map property, or null if no such mapping exists
357
	 * @noreference This method is not intended to be referenced by clients.
358
	 */
359
	protected Object remove(Object source, Object key) {
360
		Map map = getMap(source);
361
		if (map.containsKey(key)) {
362
			map = new HashMap(map);
363
			Object result = map.remove(key);
364
			setMap(source, map, Diffs.createMapDiffSingleRemove(key, result));
365
			return result;
366
		}
367
		return null;
368
	}
369
370
	public IObservableMap observeMap(Realm realm, Object source) {
371
		return new SimpleMapPropertyObservableMap(realm, source, this);
372
	}
373
374
	public IObservableMap observeDetailMap(IObservableValue master) {
375
		final Realm realm = master.getRealm();
376
		IObservableFactory factory = new IObservableFactory() {
377
			public IObservable createObservable(Object target) {
378
				return SimpleMapProperty.this.observeMap(realm, target);
379
			}
380
		};
381
		return MasterDetailObservables.detailMap(master, factory);
382
	}
383
}
187
}
(-)src/org/eclipse/core/databinding/property/map/SimpleMapPropertyObservableMap.java (-76 / +113 lines)
Lines 11-18 Link Here
11
11
12
package org.eclipse.core.databinding.property.map;
12
package org.eclipse.core.databinding.property.map;
13
13
14
import java.util.AbstractSet;
14
import java.util.Collection;
15
import java.util.Collection;
15
import java.util.Collections;
16
import java.util.Collections;
17
import java.util.ConcurrentModificationException;
18
import java.util.HashMap;
16
import java.util.HashSet;
19
import java.util.HashSet;
17
import java.util.Iterator;
20
import java.util.Iterator;
18
import java.util.Map;
21
import java.util.Map;
Lines 23-30 Link Here
23
import org.eclipse.core.databinding.observable.Realm;
26
import org.eclipse.core.databinding.observable.Realm;
24
import org.eclipse.core.databinding.observable.map.AbstractObservableMap;
27
import org.eclipse.core.databinding.observable.map.AbstractObservableMap;
25
import org.eclipse.core.databinding.observable.map.MapDiff;
28
import org.eclipse.core.databinding.observable.map.MapDiff;
26
import org.eclipse.core.databinding.property.IProperty;
27
import org.eclipse.core.databinding.property.INativePropertyListener;
29
import org.eclipse.core.databinding.property.INativePropertyListener;
30
import org.eclipse.core.databinding.property.IProperty;
28
import org.eclipse.core.databinding.property.IPropertyObservable;
31
import org.eclipse.core.databinding.property.IPropertyObservable;
29
32
30
/**
33
/**
Lines 99-239 Link Here
99
		cachedMap = null;
102
		cachedMap = null;
100
	}
103
	}
101
104
102
	public boolean containsKey(Object key) {
105
	// Queries
103
		getterCalled();
104
		return property.containsKey(source, key);
105
	}
106
106
107
	public boolean containsValue(Object value) {
107
	private Map getMap() {
108
		getterCalled();
108
		return property.getMap(source);
109
		return property.containsValue(source, value);
110
	}
109
	}
111
110
111
	// Single change operations
112
113
	private EntrySet es = new EntrySet();
114
112
	public Set entrySet() {
115
	public Set entrySet() {
113
		getterCalled();
116
		getterCalled();
114
		// unmodifiable for now
117
		return es;
115
		return Collections.unmodifiableSet(property.getMap(source).entrySet());
116
	}
118
	}
117
119
118
	public Object get(Object key) {
120
	private class EntrySet extends AbstractSet {
119
		getterCalled();
121
		public Iterator iterator() {
120
		return property.get(source, key);
122
			return new EntrySetIterator();
123
		}
124
125
		public int size() {
126
			return getMap().size();
127
		}
121
	}
128
	}
122
129
123
	public boolean isEmpty() {
130
	private class EntrySetIterator implements Iterator {
124
		getterCalled();
131
		private volatile int expectedModCount = modCount;
125
		return property.isEmpty(source);
132
		Map map = new HashMap(getMap());
133
		Iterator iterator = map.entrySet().iterator();
134
		Map.Entry last = null;
135
136
		public boolean hasNext() {
137
			getterCalled();
138
			checkForComodification();
139
			return iterator.hasNext();
140
		}
141
142
		public Object next() {
143
			getterCalled();
144
			checkForComodification();
145
			last = (Map.Entry) iterator.next();
146
			return last;
147
		}
148
149
		public void remove() {
150
			getterCalled();
151
			checkForComodification();
152
153
			iterator.remove(); // stay in sync
154
			MapDiff diff = Diffs.createMapDiffSingleRemove(last.getKey(), last
155
					.getValue());
156
157
			boolean wasUpdating = updating;
158
			boolean changed;
159
			updating = true;
160
			try {
161
				changed = property.setMap(source, map, diff);
162
			} finally {
163
				updating = wasUpdating;
164
			}
165
166
			if (changed) {
167
				cachedMap = getMap();
168
				fireMapChange(diff);
169
170
				last = null;
171
				expectedModCount = modCount;
172
			}
173
		}
174
175
		private void checkForComodification() {
176
			if (expectedModCount != modCount)
177
				throw new ConcurrentModificationException();
178
		}
126
	}
179
	}
127
180
128
	public Set keySet() {
181
	public Set keySet() {
129
		getterCalled();
182
		getterCalled();
130
		return Collections.unmodifiableSet(property.getMap(source).keySet());
183
		// AbstractMap depends on entrySet() to fulfil keySet() API, so all
184
		// getterCalled() and comodification checks will still be handled
185
		return super.keySet();
131
	}
186
	}
132
187
133
	public Object put(Object key, Object value) {
188
	public Object put(Object key, Object value) {
134
		checkRealm();
189
		checkRealm();
135
190
136
		boolean add;
191
		Map map = new HashMap(getMap());
137
		Object oldValue;
192
193
		boolean add = !map.containsKey(key);
194
195
		Object oldValue = map.put(key, value);
196
197
		MapDiff diff;
198
		if (add)
199
			diff = Diffs.createMapDiffSingleAdd(key, value);
200
		else
201
			diff = Diffs.createMapDiffSingleChange(key, oldValue, value);
138
202
139
		boolean wasUpdating = updating;
203
		boolean wasUpdating = updating;
204
		boolean changed;
140
		updating = true;
205
		updating = true;
141
		try {
206
		try {
142
			add = !property.containsKey(source, key);
207
			changed = property.setMap(source, map, diff);
143
			oldValue = property.put(source, key, value);
144
			modCount++;
208
			modCount++;
145
		} finally {
209
		} finally {
146
			updating = wasUpdating;
210
			updating = wasUpdating;
147
		}
211
		}
148
212
149
		cachedMap = property.getMap(source);
213
		if (changed) {
150
		MapDiff diff;
214
			cachedMap = property.getMap(source);
151
		if (add)
215
			fireMapChange(diff);
152
			diff = Diffs.createMapDiffSingleAdd(key, value);
216
		}
153
		else
154
			diff = Diffs.createMapDiffSingleChange(key, oldValue, value);
155
		fireMapChange(diff);
156
217
157
		return property.put(source, key, value);
218
		return oldValue;
158
	}
219
	}
159
220
160
	public void putAll(Map m) {
221
	public void putAll(Map m) {
161
		checkRealm();
222
		checkRealm();
162
223
163
		Map oldValues = cachedMap;
224
		Map map = new HashMap(getMap());
225
226
		Map oldValues = new HashMap();
227
		Map newValues = new HashMap();
164
		Set changedKeys = new HashSet();
228
		Set changedKeys = new HashSet();
165
		Set addedKeys = new HashSet();
229
		Set addedKeys = new HashSet();
166
		for (Iterator it = m.entrySet().iterator(); it.hasNext();) {
230
		for (Iterator it = m.entrySet().iterator(); it.hasNext();) {
167
			Map.Entry entry = (Entry) it.next();
231
			Map.Entry entry = (Entry) it.next();
168
			Object key = entry.getKey();
232
			Object key = entry.getKey();
169
			if (property.containsKey(source, key)) {
233
			Object newValue = entry.getValue();
234
			if (map.containsKey(key)) {
170
				changedKeys.add(key);
235
				changedKeys.add(key);
236
				oldValues.put(key, map.get(key));
171
			} else {
237
			} else {
172
				addedKeys.add(key);
238
				addedKeys.add(key);
173
			}
239
			}
174
		}
240
			map.put(key, newValue);
175
241
176
		boolean wasUpdating = updating;
242
			newValues.put(key, newValue);
177
		updating = true;
178
		try {
179
			property.putAll(source, m);
180
			modCount++;
181
		} finally {
182
			updating = wasUpdating;
183
		}
243
		}
184
244
185
		Map newValues = cachedMap = property.getMap(source);
245
		MapDiff diff = Diffs.createMapDiff(addedKeys, Collections.EMPTY_SET,
186
		fireMapChange(Diffs.createMapDiff(addedKeys, Collections.EMPTY_SET,
246
				changedKeys, oldValues, newValues);
187
				changedKeys, oldValues, newValues));
188
	}
189
190
	public Object remove(Object key) {
191
		checkRealm();
192
193
		if (!property.containsKey(source, key))
194
			return null;
195
196
		Object oldValue;
197
247
198
		boolean wasUpdating = updating;
248
		boolean wasUpdating = updating;
249
		boolean changed;
199
		updating = true;
250
		updating = true;
200
		try {
251
		try {
201
			oldValue = property.remove(source, key);
252
			changed = property.setMap(source, map, diff);
202
			modCount++;
253
			modCount++;
203
		} finally {
254
		} finally {
204
			updating = wasUpdating;
255
			updating = wasUpdating;
205
		}
256
		}
206
257
207
		cachedMap = property.getMap(source);
258
		if (changed) {
208
		fireMapChange(Diffs.createMapDiffSingleRemove(key, oldValue));
259
			cachedMap = getMap();
209
260
			fireMapChange(diff);
210
		return oldValue;
261
		}
211
	}
262
	}
212
263
213
	public int size() {
264
	public Object remove(Object key) {
214
		getterCalled();
265
		checkRealm();
215
		return property.size(source);
266
		return super.remove(key);
216
	}
267
	}
217
268
218
	public Collection values() {
269
	public Collection values() {
219
		getterCalled();
270
		getterCalled();
220
		return Collections.unmodifiableCollection(property.getMap(source)
271
		// AbstractMap depends on entrySet() to fulfil keySet() API, so all
221
				.values());
272
		// getterCalled() and comodification checks will still be handled
222
	}
273
		return super.values();
223
224
	public void clear() {
225
		getterCalled();
226
		property.clear(source);
227
	}
228
229
	public boolean equals(Object o) {
230
		getterCalled();
231
		return property.equals(source, o);
232
	}
233
234
	public int hashCode() {
235
		getterCalled();
236
		return property.hashCode(source);
237
	}
274
	}
238
275
239
	public Object getObserved() {
276
	public Object getObserved() {
(-)src/org/eclipse/core/databinding/property/value/ObservableListSimpleValuePropertyObservableList.java (-9 / +29 lines)
Lines 374-391 Link Here
374
				if (!haveIterated)
374
				if (!haveIterated)
375
					throw new IllegalStateException();
375
					throw new IllegalStateException();
376
376
377
				Object oldValue = cachedValues.get(new IdentityWrapper(
378
						lastMasterElement));
379
377
				boolean wasUpdating = updating;
380
				boolean wasUpdating = updating;
381
				boolean changed;
378
				updating = true;
382
				updating = true;
379
				try {
383
				try {
380
					detailProperty.setValue(lastElement, o);
384
					changed = detailProperty.setValue(lastElement, o);
381
				} finally {
385
				} finally {
382
					updating = wasUpdating;
386
					updating = wasUpdating;
383
				}
387
				}
384
388
385
				cachedValues.put(new IdentityWrapper(lastMasterElement), o);
389
				if (changed) {
386
				fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
390
					Object newValue = detailProperty.getValue(lastElement);
387
						lastIndex, false, lastElement), Diffs
391
388
						.createListDiffEntry(lastIndex, true, o)));
392
					if (!Util.equals(oldValue, newValue)) {
393
						cachedValues.put(
394
								new IdentityWrapper(lastMasterElement), o);
395
						fireListChange(Diffs.createListDiff(Diffs
396
								.createListDiffEntry(lastIndex, false,
397
										lastElement), Diffs
398
								.createListDiffEntry(lastIndex, true, o)));
399
					}
400
				}
389
401
390
				lastElement = o;
402
				lastElement = o;
391
			}
403
			}
Lines 402-417 Link Here
402
		Object oldValue = detailProperty.getValue(masterElement);
414
		Object oldValue = detailProperty.getValue(masterElement);
403
415
404
		boolean wasUpdating = updating;
416
		boolean wasUpdating = updating;
417
		boolean changed;
405
		updating = true;
418
		updating = true;
406
		try {
419
		try {
407
			detailProperty.setValue(masterElement, o);
420
			changed = detailProperty.setValue(masterElement, o);
408
		} finally {
421
		} finally {
409
			updating = wasUpdating;
422
			updating = wasUpdating;
410
		}
423
		}
411
424
412
		cachedValues.put(new IdentityWrapper(masterElement), o);
425
		if (changed) {
413
		fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(index,
426
			Object newValue = detailProperty.getValue(masterElement);
414
				false, oldValue), Diffs.createListDiffEntry(index, true, o)));
427
428
			if (!Util.equals(oldValue, newValue)) {
429
				cachedValues.put(new IdentityWrapper(masterElement), o);
430
				fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
431
						index, false, oldValue), Diffs.createListDiffEntry(
432
						index, true, o)));
433
			}
434
		}
415
435
416
		return oldValue;
436
		return oldValue;
417
	}
437
	}
(-)src/org/eclipse/core/databinding/property/value/ObservableSetSimpleValuePropertyObservableMap.java (-7 / +12 lines)
Lines 106-124 Link Here
106
	protected Object doPut(Object key, Object value) {
106
	protected Object doPut(Object key, Object value) {
107
		Object oldValue = detailProperty.getValue(key);
107
		Object oldValue = detailProperty.getValue(key);
108
108
109
		boolean changed;
109
		updating = true;
110
		updating = true;
110
		try {
111
		try {
111
			detailProperty.setValue(key, value);
112
			changed = detailProperty.setValue(key, value);
112
		} finally {
113
		} finally {
113
			updating = false;
114
			updating = false;
114
		}
115
		}
115
		Object newValue = detailProperty.getValue(key);
116
		
116
		cachedValues.put(key, newValue);
117
		if (changed) {
117
118
			Object newValue = detailProperty.getValue(key);
118
		if (oldValue != newValue) {
119
			cachedValues.put(key, newValue);
119
			fireMapChange(Diffs.createMapDiffSingleChange(key, oldValue,
120
			
120
					newValue));
121
			if (oldValue != newValue) {
122
				fireMapChange(Diffs.createMapDiffSingleChange(key, oldValue,
123
						newValue));
124
			}
121
		}
125
		}
126
122
		return oldValue;
127
		return oldValue;
123
	}
128
	}
124
129
(-)src/org/eclipse/core/databinding/property/value/SimpleValueProperty.java (-1 / +3 lines)
Lines 74-82 Link Here
74
	 *            the property source
74
	 *            the property source
75
	 * @param value
75
	 * @param value
76
	 *            the new value
76
	 *            the new value
77
	 * @return true if the property was modified on the source object, false
78
	 *         otherwise
77
	 * @noreference This method is not intended to be referenced by clients.
79
	 * @noreference This method is not intended to be referenced by clients.
78
	 */
80
	 */
79
	protected abstract void setValue(Object source, Object value);
81
	protected abstract boolean setValue(Object source, Object value);
80
82
81
	/**
83
	/**
82
	 * Returns a listener which implements the correct listener interface for
84
	 * Returns a listener which implements the correct listener interface for
(-)src/org/eclipse/core/databinding/property/value/ObservableMapSimpleValuePropertyObservableMap.java (-6 / +9 lines)
Lines 283-300 Link Here
283
283
284
			Object oldValue = detailProperty.getValue(source);
284
			Object oldValue = detailProperty.getValue(source);
285
285
286
			boolean changed;
286
			updating = true;
287
			updating = true;
287
			try {
288
			try {
288
				detailProperty.setValue(source, value);
289
				changed = detailProperty.setValue(source, value);
289
			} finally {
290
			} finally {
290
				updating = false;
291
				updating = false;
291
			}
292
			}
292
293
293
			Object newValue = detailProperty.getValue(source);
294
			if (changed) {
294
295
				Object newValue = detailProperty.getValue(source);
295
			if (!Util.equals(oldValue, newValue)) {
296
				
296
				fireMapChange(Diffs.createMapDiffSingleChange(key, oldValue,
297
				if (!Util.equals(oldValue, newValue)) {
297
						newValue));
298
					fireMapChange(Diffs.createMapDiffSingleChange(key, oldValue,
299
							newValue));
300
				}
298
			}
301
			}
299
302
300
			return oldValue;
303
			return oldValue;
(-)src/org/eclipse/core/databinding/property/value/SimpleValuePropertyObservableValue.java (-4 / +7 lines)
Lines 105-120 Link Here
105
		if (hasListeners()) {
105
		if (hasListeners()) {
106
			Object oldValue = cachedValue;
106
			Object oldValue = cachedValue;
107
107
108
			boolean changed;
108
			updating = true;
109
			updating = true;
109
			try {
110
			try {
110
				property.setValue(source, value);
111
				changed = property.setValue(source, value);
111
			} finally {
112
			} finally {
112
				updating = false;
113
				updating = false;
113
			}
114
			}
114
115
115
			Object newValue = cachedValue = property.getValue(source);
116
			if (changed) {
116
			if (hasListeners() && !Util.equals(oldValue, newValue)) {
117
				Object newValue = cachedValue = property.getValue(source);
117
				fireValueChange(Diffs.createValueDiff(oldValue, newValue));
118
				if (hasListeners() && !Util.equals(oldValue, newValue)) {
119
					fireValueChange(Diffs.createValueDiff(oldValue, newValue));
120
				}
118
			}
121
			}
119
		} else {
122
		} else {
120
			property.setValue(source, value);
123
			property.setValue(source, value);
(-)src/org/eclipse/core/databinding/property/list/SimpleListProperty.java (-459 / +35 lines)
Lines 11-29 Link Here
11
11
12
package org.eclipse.core.databinding.property.list;
12
package org.eclipse.core.databinding.property.list;
13
13
14
import java.util.ArrayList;
15
import java.util.Collection;
16
import java.util.Collections;
14
import java.util.Collections;
17
import java.util.Iterator;
18
import java.util.List;
15
import java.util.List;
19
import java.util.ListIterator;
20
16
21
import org.eclipse.core.databinding.observable.Diffs;
22
import org.eclipse.core.databinding.observable.IObservable;
17
import org.eclipse.core.databinding.observable.IObservable;
23
import org.eclipse.core.databinding.observable.Realm;
18
import org.eclipse.core.databinding.observable.Realm;
24
import org.eclipse.core.databinding.observable.list.IObservableList;
19
import org.eclipse.core.databinding.observable.list.IObservableList;
25
import org.eclipse.core.databinding.observable.list.ListDiff;
20
import org.eclipse.core.databinding.observable.list.ListDiff;
26
import org.eclipse.core.databinding.observable.list.ListDiffEntry;
27
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
21
import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory;
28
import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables;
22
import org.eclipse.core.databinding.observable.masterdetail.MasterDetailObservables;
29
import org.eclipse.core.databinding.observable.value.IObservableValue;
23
import org.eclipse.core.databinding.observable.value.IObservableValue;
Lines 55-60 Link Here
55
		this.elementType = elementType;
49
		this.elementType = elementType;
56
	}
50
	}
57
51
52
	public IObservableList observeList(Realm realm, Object source) {
53
		return new SimpleListPropertyObservableList(realm, source, this);
54
	}
55
56
	public IObservableList observeDetailList(IObservableValue master) {
57
		final Realm realm = master.getRealm();
58
		IObservableFactory factory = new IObservableFactory() {
59
			public IObservable createObservable(Object target) {
60
				return SimpleListProperty.this.observeList(realm, target);
61
			}
62
		};
63
		return MasterDetailObservables.detailList(master, factory,
64
				getElementType());
65
	}
66
58
	/**
67
	/**
59
	 * Returns the type of the elements in the collection or <code>null</code>
68
	 * Returns the type of the elements in the collection or <code>null</code>
60
	 * if untyped
69
	 * if untyped
Lines 67-183 Link Here
67
		return elementType;
76
		return elementType;
68
	}
77
	}
69
78
70
	/**
79
	// Accessors
71
	 * Returns whether the source's collection property contains all elements in
72
	 * the given collection
73
	 * 
74
	 * @param source
75
	 *            the property source
76
	 * @param c
77
	 *            the collection of elements to test for
78
	 * @return whether the source's collection property contains all elements in
79
	 *         the given collection
80
	 * @noreference This method is not intended to be referenced by clients.
81
	 */
82
	protected boolean containsAll(Object source, Collection c) {
83
		return getList(source).containsAll(c);
84
	}
85
86
	/**
87
	 * Returns whether the source's collection property contains the given
88
	 * element.
89
	 * 
90
	 * @param source
91
	 *            the property source
92
	 * @param o
93
	 *            the element
94
	 * @return whether the source's collection property contains the given
95
	 *         element.
96
	 * @noreference This method is not intended to be referenced by clients.
97
	 */
98
	protected boolean contains(Object source, Object o) {
99
		return getList(source).contains(o);
100
	}
101
80
102
	/**
81
	/**
103
	 * Returns whether the source's collection property is equal to the
82
	 * Returns an unmodifiable List with the current contents of the source's
104
	 * argument.
83
	 * list property
105
	 * 
106
	 * @param source
107
	 *            the property source
108
	 * @param o
109
	 *            the object to test for equality to the source's collection
110
	 *            property
111
	 * @return whether the source's collection property is equal to the argument
112
	 * @noreference This method is not intended to be referenced by clients.
113
	 */
114
	protected boolean equals(Object source, Object o) {
115
		return getList(source).equals(o);
116
	}
117
118
	/**
119
	 * Returns the hash code of the source's collection property.
120
	 * 
84
	 * 
121
	 * @param source
85
	 * @param source
122
	 *            the property source
86
	 *            the property source
123
	 * @return the hash code of the source's collection property
87
	 * @return an unmodifiable List with the current contents of the source's
88
	 *         list property
124
	 * @noreference This method is not intended to be referenced by clients.
89
	 * @noreference This method is not intended to be referenced by clients.
125
	 */
90
	 */
126
	protected int hashCode(Object source) {
91
	protected final List getList(Object source) {
127
		return getList(source).hashCode();
92
		return Collections.unmodifiableList(doGetList(source));
128
	}
93
	}
129
94
130
	/**
95
	/**
131
	 * Returns whether the source's collection property is empty
96
	 * Returns a List with the current contents of the source's list property
132
	 * 
97
	 * 
133
	 * @param source
98
	 * @param source
134
	 *            the property source
99
	 *            the property source
135
	 * @return whether the source's collection property is empty
100
	 * @return a List with the current contents of the source's list property
136
	 * @noreference This method is not intended to be referenced by clients.
101
	 * @noreference This method is not intended to be referenced by clients.
137
	 */
102
	 */
138
	protected boolean isEmpty(Object source) {
103
	protected abstract List doGetList(Object source);
139
		return getList(source).isEmpty();
140
	}
141
104
142
	/**
105
	// Mutators
143
	 * Returns the size of the source's collection property
144
	 * 
145
	 * @param source
146
	 *            the property source
147
	 * @return the size of the source's collection property
148
	 * @noreference This method is not intended to be referenced by clients.
149
	 */
150
	protected int size(Object source) {
151
		return getList(source).size();
152
	}
153
106
154
	/**
107
	/**
155
	 * Returns an array of all elements in the source's collection property
108
	 * Updates the property on the source with the specified change.
156
	 * 
109
	 * 
157
	 * @param source
110
	 * @param source
158
	 *            the property source
111
	 *            the property source
159
	 * @param array
112
	 * @param list
160
	 *            the array into which the elements will be copied. If the array
113
	 *            the new list
161
	 *            is not large enough to hold all elements, the elements will be
114
	 * @param diff
162
	 *            returned in a new array of the same runtime type.
115
	 *            a diff describing the change
163
	 * @return an array of all elements in the source's collection property
116
	 * @return true if the property was modified on the source object, false
117
	 *         otherwise
164
	 * @noreference This method is not intended to be referenced by clients.
118
	 * @noreference This method is not intended to be referenced by clients.
165
	 */
119
	 */
166
	protected Object[] toArray(Object source, Object[] array) {
120
	protected abstract boolean setList(Object source, List list, ListDiff diff);
167
		return getList(source).toArray(array);
168
	}
169
121
170
	/**
122
	// Listeners
171
	 * Returns an array of all elements in the source's collection property
172
	 * 
173
	 * @param source
174
	 *            the property source
175
	 * @return an array of all elements in the source's collection property
176
	 * @noreference This method is not intended to be referenced by clients.
177
	 */
178
	protected Object[] toArray(Object source) {
179
		return getList(source).toArray();
180
	}
181
123
182
	/**
124
	/**
183
	 * Returns a listener which implements the correct listener interface for
125
	 * Returns a listener which implements the correct listener interface for
Lines 200-292 Link Here
200
			IListPropertyChangeListener listener);
142
			IListPropertyChangeListener listener);
201
143
202
	/**
144
	/**
203
	 * Inserts the element into the source's list property at the specified
204
	 * position
205
	 * 
206
	 * @param source
207
	 *            the property source
208
	 * @param index
209
	 *            the insertion index
210
	 * @param element
211
	 *            the element to insert
212
	 * @noreference This method is not intended to be referenced by clients.
213
	 */
214
	protected void add(Object source, int index, Object element) {
215
		List list = new ArrayList(getList(source));
216
		list.add(index, element);
217
		setList(source, list, Diffs.createListDiff(Diffs.createListDiffEntry(
218
				index, true, element)));
219
	}
220
221
	/**
222
	 * Adds the element to the source's collection property
223
	 * 
224
	 * @param source
225
	 *            the property source
226
	 * @param o
227
	 *            the element to add
228
	 * @return whether the element was added to the source's collection property
229
	 * @noreference This method is not intended to be referenced by clients.
230
	 */
231
	protected boolean add(Object source, Object o) {
232
		add(source, size(source), o);
233
		return true;
234
	}
235
236
	/**
237
	 * Adds all elements in the specified collection to the source's collection
238
	 * property.
239
	 * 
240
	 * @param source
241
	 *            the property source
242
	 * @param c
243
	 *            the collection of elements to add.
244
	 * @return whether the source's collection property was changed
245
	 * @noreference This method is not intended to be referenced by clients.
246
	 */
247
	protected boolean addAll(Object source, Collection c) {
248
		if (c.isEmpty())
249
			return false;
250
		addAll(source, size(source), c);
251
		return true;
252
	}
253
254
	/**
255
	 * Inserts all elements in the specified collection into the source's list
256
	 * property at the specified index.
257
	 * 
258
	 * @param source
259
	 *            the property source
260
	 * @param index
261
	 *            the insertion index
262
	 * @param c
263
	 *            the collection of elements to add
264
	 * @return whether the source's list property was changed
265
	 * @noreference This method is not intended to be referenced by clients.
266
	 */
267
	protected boolean addAll(Object source, int index, Collection c) {
268
		if (c.isEmpty()) {
269
			return false;
270
		}
271
272
		List list = new ArrayList(getList(source));
273
		List entries = new ArrayList();
274
		int i = index;
275
		for (Iterator it = c.iterator(); it.hasNext(); i++) {
276
			Object o = it.next();
277
			list.add(i, o);
278
			entries.add(Diffs.createListDiffEntry(i, true, o));
279
		}
280
		boolean changed = !entries.isEmpty();
281
		if (changed) {
282
			ListDiffEntry[] ea = (ListDiffEntry[]) entries
283
					.toArray(new ListDiffEntry[entries.size()]);
284
			setList(source, list, Diffs.createListDiff(ea));
285
		}
286
		return changed;
287
	}
288
289
	/**
290
	 * Adds the specified listener as a listener for this property on the
145
	 * Adds the specified listener as a listener for this property on the
291
	 * specified property source. If the source object has no listener API for
146
	 * specified property source. If the source object has no listener API for
292
	 * this property (i.e. {@link #adaptListener(IListPropertyChangeListener)}
147
	 * this property (i.e. {@link #adaptListener(IListPropertyChangeListener)}
Lines 303-514 Link Here
303
			INativePropertyListener listener);
158
			INativePropertyListener listener);
304
159
305
	/**
160
	/**
306
	 * Removes all elements from the source's collection property.
307
	 * 
308
	 * @param source
309
	 *            the property source
310
	 * @noreference This method is not intended to be referenced by clients.
311
	 */
312
	protected void clear(Object source) {
313
		if (!isEmpty(source)) {
314
			List list = getList(source);
315
			ListDiffEntry[] entries = new ListDiffEntry[list.size()];
316
			int i = 0;
317
			for (Iterator it = getList(source).iterator(); it.hasNext(); i++) {
318
				entries[i] = Diffs.createListDiffEntry(0, false, it.next());
319
			}
320
			setList(source, new ArrayList(), Diffs.createListDiff(entries));
321
		}
322
	}
323
324
	/**
325
	 * Returns the element at the specified position in the source's list
326
	 * property
327
	 * 
328
	 * @param source
329
	 *            the property source
330
	 * @param index
331
	 *            the element position
332
	 * @return the element at the given position in the source's list property
333
	 * @noreference This method is not intended to be referenced by clients.
334
	 */
335
	protected Object get(Object source, int index) {
336
		return getList(source).get(index);
337
	}
338
339
	/**
340
	 * Returns an unmodifiable List with the current contents of the source's
341
	 * list property
342
	 * 
343
	 * @param source
344
	 *            the property source
345
	 * @return an unmodifiable List with the current contents of the source's
346
	 *         list property
347
	 * @noreference This method is not intended to be referenced by clients.
348
	 */
349
	protected final List getList(Object source) {
350
		return Collections.unmodifiableList(doGetList(source));
351
	}
352
353
	/**
354
	 * Returns a List with the current contents of the source's list property
355
	 * 
356
	 * @param source
357
	 *            the property source
358
	 * @return a List with the current contents of the source's list property
359
	 * @noreference This method is not intended to be referenced by clients.
360
	 */
361
	protected abstract List doGetList(Object source);
362
363
	/**
364
	 * Returns the index of the first location of the given element in the
365
	 * source's list property, or -1 if the list does not contain the element.
366
	 * 
367
	 * @param source
368
	 *            the property source
369
	 * @param o
370
	 *            the element
371
	 * @return the index of the first location of the given element in the
372
	 *         source's list property, or -1 if the list does not contain the
373
	 *         element
374
	 * @noreference This method is not intended to be referenced by clients.
375
	 */
376
	protected int indexOf(Object source, Object o) {
377
		return getList(source).indexOf(o);
378
	}
379
380
	/**
381
	 * Returns the index of the last location of the given element in the
382
	 * source's list property, or -1 if the list does not contain the given
383
	 * element.
384
	 * 
385
	 * @param source
386
	 * @param o
387
	 * @return the index of the last location of the given element in the
388
	 *         source's list property, or -1 if the list does not contain the
389
	 *         element
390
	 * @noreference This method is not intended to be referenced by clients.
391
	 */
392
	protected int lastIndexOf(Object source, Object o) {
393
		return getList(source).lastIndexOf(o);
394
	}
395
396
	/**
397
	 * Moves the element at the specified old position in the source's list
398
	 * property to the specified new position
399
	 * 
400
	 * @param source
401
	 *            the property source
402
	 * @param oldIndex
403
	 *            the old element position
404
	 * @param newIndex
405
	 *            the new element position
406
	 * @return the element that was moved
407
	 * @noreference This method is not intended to be referenced by clients.
408
	 */
409
	protected Object move(Object source, int oldIndex, int newIndex) {
410
		if (oldIndex == newIndex)
411
			return get(source, oldIndex);
412
		List list = new ArrayList(getList(source));
413
		Object result = list.remove(oldIndex);
414
		list.add(newIndex, result);
415
		setList(source, list, Diffs.createListDiff(Diffs.createListDiffEntry(
416
				oldIndex, false, result), Diffs.createListDiffEntry(newIndex,
417
				true, result)));
418
		return result;
419
	}
420
421
	public IObservableList observeList(Realm realm, Object source) {
422
		return new SimpleListPropertyObservableList(realm, source, this);
423
	}
424
425
	public IObservableList observeDetailList(IObservableValue master) {
426
		final Realm realm = master.getRealm();
427
		IObservableFactory factory = new IObservableFactory() {
428
			public IObservable createObservable(Object target) {
429
				return SimpleListProperty.this.observeList(realm, target);
430
			}
431
		};
432
		return MasterDetailObservables.detailList(master, factory,
433
				getElementType());
434
	}
435
436
	/**
437
	 * Removes the element from the source's list property which is located at
438
	 * the specified position
439
	 * 
440
	 * @param source
441
	 *            the property source
442
	 * @param index
443
	 *            the index of the element to remove
444
	 * @return the element that was removed from the source's list property
445
	 * @noreference This method is not intended to be referenced by clients.
446
	 */
447
	protected Object remove(Object source, int index) {
448
		List list = new ArrayList(getList(source));
449
		Object result = list.remove(index);
450
		setList(source, list, Diffs.createListDiff(Diffs.createListDiffEntry(
451
				index, false, result)));
452
		return result;
453
	}
454
455
	/**
456
	 * Removes the element from the source's collection property
457
	 * 
458
	 * @param source
459
	 *            the property source
460
	 * @param o
461
	 *            the element to remove
462
	 * @return whether the element was removed from the source's collection
463
	 *         property
464
	 * @noreference This method is not intended to be referenced by clients.
465
	 */
466
	protected boolean remove(Object source, Object o) {
467
		int i = indexOf(source, o);
468
		if (i == -1)
469
			return false;
470
		remove(source, i);
471
		return true;
472
	}
473
474
	/**
475
	 * Removes all elements from the source's collection property which are
476
	 * contained in the specified collection.
477
	 * 
478
	 * @param source
479
	 *            the property source
480
	 * @param c
481
	 *            the collection of elements to be removed
482
	 * @return whether the source's collection property was changed
483
	 * @noreference This method is not intended to be referenced by clients.
484
	 */
485
	protected boolean removeAll(Object source, Collection c) {
486
		if (isEmpty(source)) {
487
			return false;
488
		}
489
		if (c.isEmpty()) {
490
			return false;
491
		}
492
		List list = new ArrayList(getList(source));
493
		List entries = new ArrayList();
494
		for (ListIterator it = list.listIterator(); it.hasNext();) {
495
			Object o = it.next();
496
			if (c.contains(o)) {
497
				entries.add(Diffs.createListDiffEntry(it.previousIndex(),
498
						false, o));
499
				it.remove();
500
			}
501
		}
502
		boolean changed = !entries.isEmpty();
503
		if (changed) {
504
			ListDiffEntry[] ea = (ListDiffEntry[]) entries
505
					.toArray(new ListDiffEntry[entries.size()]);
506
			setList(source, list, Diffs.createListDiff(ea));
507
		}
508
		return changed;
509
	}
510
511
	/**
512
	 * Removes the specified listener as a listener for this property on the
161
	 * Removes the specified listener as a listener for this property on the
513
	 * specified property source. If the source object has no listener API for
162
	 * specified property source. If the source object has no listener API for
514
	 * this property (i.e. {@link #adaptListener(IListPropertyChangeListener)}
163
	 * this property (i.e. {@link #adaptListener(IListPropertyChangeListener)}
Lines 524-600 Link Here
524
	protected abstract void removeListener(Object source,
173
	protected abstract void removeListener(Object source,
525
			INativePropertyListener listener);
174
			INativePropertyListener listener);
526
175
527
	/**
528
	 * Removes all elements from the source's collection property which are not
529
	 * contained in the specified collection.
530
	 * 
531
	 * @param source
532
	 *            the property source
533
	 * @param c
534
	 *            the collection of elements to retain
535
	 * @return whether the source's collection property was changed
536
	 * @noreference This method is not intended to be referenced by clients.
537
	 */
538
	protected boolean retainAll(Object source, Collection c) {
539
		if (isEmpty(source)) {
540
			return false;
541
		}
542
		if (c.isEmpty()) {
543
			clear(source);
544
			return true;
545
		}
546
		List list = new ArrayList(getList(source));
547
		List entries = new ArrayList();
548
		for (ListIterator it = list.listIterator(); it.hasNext();) {
549
			Object o = it.next();
550
			if (!c.contains(o)) {
551
				entries.add(Diffs.createListDiffEntry(it.previousIndex(),
552
						false, o));
553
				it.remove();
554
			}
555
		}
556
		boolean changed = !entries.isEmpty();
557
		if (changed) {
558
			ListDiffEntry[] ea = (ListDiffEntry[]) entries
559
					.toArray(new ListDiffEntry[entries.size()]);
560
			setList(source, list, Diffs.createListDiff(ea));
561
		}
562
		return changed;
563
	}
564
565
	/**
566
	 * Replaces the element at the specified position in the source's list
567
	 * property with the given element.
568
	 * 
569
	 * @param source
570
	 *            the property source
571
	 * @param index
572
	 *            the element position
573
	 * @param element
574
	 *            the replacement element
575
	 * @return the element previously at the specified position in the source's
576
	 *         list property
577
	 * @noreference This method is not intended to be referenced by clients.
578
	 */
579
	protected Object set(Object source, int index, Object element) {
580
		List list = new ArrayList(getList(source));
581
		Object result = list.set(index, element);
582
		setList(source, list, Diffs.createListDiff(Diffs.createListDiffEntry(
583
				index, false, result), Diffs.createListDiffEntry(index, true,
584
				element)));
585
		return result;
586
	}
587
588
	/**
589
	 * Updates the property on the source with the specified change.
590
	 * 
591
	 * @param source
592
	 *            the property source
593
	 * @param list
594
	 *            the new list
595
	 * @param diff
596
	 *            a diff describing the change
597
	 * @noreference This method is not intended to be referenced by clients.
598
	 */
599
	protected abstract void setList(Object source, List list, ListDiff diff);
600
}
176
}
(-)src/org/eclipse/core/databinding/property/list/SimpleListPropertyObservableList.java (-120 / +190 lines)
Lines 60-66 Link Here
60
60
61
	protected void firstListenerAdded() {
61
	protected void firstListenerAdded() {
62
		if (!isDisposed()) {
62
		if (!isDisposed()) {
63
			cachedList = property.getList(source);
63
			cachedList = getList();
64
64
65
			if (listener == null) {
65
			if (listener == null) {
66
				listener = property
66
				listener = property
Lines 72-79 Link Here
72
									getRealm().exec(new Runnable() {
72
									getRealm().exec(new Runnable() {
73
										public void run() {
73
										public void run() {
74
											List oldList = cachedList;
74
											List oldList = cachedList;
75
											List newList = cachedList = property
75
											List newList = cachedList = getList();
76
													.getList(source);
77
											ListDiff diff = event.diff;
76
											ListDiff diff = event.diff;
78
											if (diff == null) {
77
											if (diff == null) {
79
												diff = Diffs.computeListDiff(
78
												diff = Diffs.computeListDiff(
Lines 108-187 Link Here
108
107
109
	// Queries
108
	// Queries
110
109
110
	private List getList() {
111
		return property.getList(source);
112
	}
113
111
	protected int doGetSize() {
114
	protected int doGetSize() {
112
		return property.size(source);
115
		return getList().size();
113
	}
116
	}
114
117
115
	public boolean contains(Object o) {
118
	public boolean contains(Object o) {
116
		getterCalled();
119
		getterCalled();
117
		return property.contains(source, o);
120
		return getList().contains(o);
118
	}
121
	}
119
122
120
	public boolean containsAll(Collection c) {
123
	public boolean containsAll(Collection c) {
121
		getterCalled();
124
		getterCalled();
122
		return property.containsAll(source, c);
125
		return getList().containsAll(c);
123
	}
126
	}
124
127
125
	public Object get(int index) {
128
	public Object get(int index) {
126
		getterCalled();
129
		getterCalled();
127
		return property.get(source, index);
130
		return getList().get(index);
128
	}
131
	}
129
132
130
	public int indexOf(Object o) {
133
	public int indexOf(Object o) {
131
		getterCalled();
134
		getterCalled();
132
		return property.indexOf(source, o);
135
		return getList().indexOf(o);
133
	}
136
	}
134
137
135
	public boolean isEmpty() {
138
	public boolean isEmpty() {
136
		getterCalled();
139
		getterCalled();
137
		return property.isEmpty(source);
140
		return getList().isEmpty();
138
	}
141
	}
139
142
140
	public int lastIndexOf(Object o) {
143
	public int lastIndexOf(Object o) {
141
		getterCalled();
144
		getterCalled();
142
		return property.lastIndexOf(source, o);
145
		return getList().lastIndexOf(o);
143
	}
146
	}
144
147
145
	public Object[] toArray() {
148
	public Object[] toArray() {
146
		getterCalled();
149
		getterCalled();
147
		return property.toArray(source);
150
		return getList().toArray();
148
	}
151
	}
149
152
150
	public Object[] toArray(Object[] a) {
153
	public Object[] toArray(Object[] a) {
151
		getterCalled();
154
		getterCalled();
152
		return property.toArray(source, a);
155
		return getList().toArray(a);
153
	}
156
	}
154
157
155
	// Single change operations
158
	// Single change operations
156
159
157
	public boolean add(Object o) {
160
	public boolean add(Object o) {
158
		checkRealm();
161
		checkRealm();
159
		add(property.size(source), o);
162
		add(getList().size(), o);
160
		return true;
163
		return true;
161
	}
164
	}
162
165
163
	public void add(int index, Object o) {
166
	public void add(int index, Object o) {
164
		checkRealm();
167
		checkRealm();
165
		boolean wasUpdating = updating;
168
		boolean wasUpdating = updating;
169
		boolean changed;
166
		updating = true;
170
		updating = true;
171
		List list = new ArrayList(getList());
172
		list.add(index, o);
173
		ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index,
174
				true, o));
167
		try {
175
		try {
168
			property.add(source, index, o);
176
			changed = property.setList(source, list, diff);
169
			modCount++;
177
			modCount++;
170
		} finally {
178
		} finally {
171
			updating = wasUpdating;
179
			updating = wasUpdating;
172
		}
180
		}
173
181
174
		cachedList = property.getList(source);
182
		if (changed) {
175
		fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(index,
183
			cachedList = getList();
176
				true, o)));
184
			fireListChange(diff);
185
		}
177
	}
186
	}
178
187
179
	public Iterator iterator() {
188
	public Iterator iterator() {
180
		getterCalled();
189
		getterCalled();
181
		return new Iterator() {
190
		return new Iterator() {
182
			int expectedModCount = modCount;
191
			int expectedModCount = modCount;
183
			ListIterator delegate = new ArrayList(property.getList(source))
192
			List list = new ArrayList(getList());
184
					.listIterator();
193
			ListIterator iterator = list.listIterator();
185
194
186
			Object lastElement = null;
195
			Object lastElement = null;
187
			int lastIndex = -1;
196
			int lastIndex = -1;
Lines 189-202 Link Here
189
			public boolean hasNext() {
198
			public boolean hasNext() {
190
				getterCalled();
199
				getterCalled();
191
				checkForComodification();
200
				checkForComodification();
192
				return delegate.hasNext();
201
				return iterator.hasNext();
193
			}
202
			}
194
203
195
			public Object next() {
204
			public Object next() {
196
				getterCalled();
205
				getterCalled();
197
				checkForComodification();
206
				checkForComodification();
198
				Object next = lastElement = delegate.next();
207
				Object next = lastElement = iterator.next();
199
				lastIndex = delegate.previousIndex();
208
				lastIndex = iterator.previousIndex();
200
				return next;
209
				return next;
201
			}
210
			}
202
211
Lines 206-230 Link Here
206
				if (lastIndex == -1)
215
				if (lastIndex == -1)
207
					throw new IllegalStateException();
216
					throw new IllegalStateException();
208
217
209
				delegate.remove(); // stay in sync
218
				iterator.remove(); // stay in sync
219
				ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(
220
						lastIndex, false, lastElement));
210
221
211
				boolean wasUpdating = updating;
222
				boolean wasUpdating = updating;
223
				boolean changed;
212
				updating = true;
224
				updating = true;
213
				try {
225
				try {
214
					property.remove(source, lastIndex);
226
					changed = property.setList(source, list, diff);
215
					modCount++;
227
					modCount++;
216
				} finally {
228
				} finally {
217
					updating = wasUpdating;
229
					updating = wasUpdating;
218
				}
230
				}
219
231
220
				cachedList = property.getList(source);
232
				if (changed) {
221
				fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
233
					cachedList = getList();
222
						lastIndex, false, lastElement)));
234
					fireListChange(diff);
223
235
224
				lastElement = null;
236
					lastElement = null;
225
				lastIndex = -1;
237
					lastIndex = -1;
226
238
227
				expectedModCount = modCount;
239
					expectedModCount = modCount;
240
				}
228
			}
241
			}
229
242
230
			private void checkForComodification() {
243
			private void checkForComodification() {
Lines 237-264 Link Here
237
	public Object move(int oldIndex, int newIndex) {
250
	public Object move(int oldIndex, int newIndex) {
238
		checkRealm();
251
		checkRealm();
239
252
240
		int size = property.size(source);
253
		List list = getList();
254
		int size = list.size();
241
		if (oldIndex < 0 || oldIndex >= size || newIndex < 0
255
		if (oldIndex < 0 || oldIndex >= size || newIndex < 0
242
				|| newIndex >= size)
256
				|| newIndex >= size)
243
			throw new IndexOutOfBoundsException();
257
			throw new IndexOutOfBoundsException();
258
244
		if (oldIndex == newIndex)
259
		if (oldIndex == newIndex)
245
			return property.get(source, oldIndex);
260
			return list.get(oldIndex);
246
261
247
		Object element;
262
		list = new ArrayList(list);
263
		Object element = list.remove(oldIndex);
264
		list.add(newIndex, element);
265
266
		ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(
267
				oldIndex, false, element), Diffs.createListDiffEntry(newIndex,
268
				true, element));
248
269
249
		boolean wasUpdating = updating;
270
		boolean wasUpdating = updating;
271
		boolean changed;
250
		updating = true;
272
		updating = true;
251
		try {
273
		try {
252
			element = property.move(source, oldIndex, newIndex);
274
			changed = property.setList(source, list, diff);
253
			modCount++;
275
			modCount++;
254
		} finally {
276
		} finally {
255
			updating = wasUpdating;
277
			updating = wasUpdating;
256
		}
278
		}
257
279
258
		cachedList = property.getList(source);
280
		if (changed) {
259
		fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(oldIndex,
281
			cachedList = getList();
260
				false, element), Diffs.createListDiffEntry(newIndex, true,
282
			fireListChange(diff);
261
				element)));
283
		}
262
284
263
		return element;
285
		return element;
264
	}
286
	}
Lines 266-272 Link Here
266
	public boolean remove(Object o) {
288
	public boolean remove(Object o) {
267
		checkRealm();
289
		checkRealm();
268
290
269
		int index = property.indexOf(source, o);
291
		int index = getList().indexOf(o);
270
		if (index == -1)
292
		if (index == -1)
271
			return false;
293
			return false;
272
294
Lines 283-290 Link Here
283
		getterCalled();
305
		getterCalled();
284
		return new ListIterator() {
306
		return new ListIterator() {
285
			int expectedModCount = modCount;
307
			int expectedModCount = modCount;
286
			ListIterator delegate = new ArrayList(property.getList(source))
308
			List list = new ArrayList(getList());
287
					.listIterator(index);
309
			ListIterator iterator = list.listIterator(index);
288
310
289
			Object lastElement = null;
311
			Object lastElement = null;
290
			int lastIndex = -1;
312
			int lastIndex = -1;
Lines 292-382 Link Here
292
			public boolean hasNext() {
314
			public boolean hasNext() {
293
				getterCalled();
315
				getterCalled();
294
				checkForComodification();
316
				checkForComodification();
295
				return delegate.hasNext();
317
				return iterator.hasNext();
296
			}
318
			}
297
319
298
			public int nextIndex() {
320
			public int nextIndex() {
299
				getterCalled();
321
				getterCalled();
300
				checkForComodification();
322
				checkForComodification();
301
				return delegate.nextIndex();
323
				return iterator.nextIndex();
302
			}
324
			}
303
325
304
			public Object next() {
326
			public Object next() {
305
				getterCalled();
327
				getterCalled();
306
				checkForComodification();
328
				checkForComodification();
307
				lastElement = delegate.next();
329
				lastElement = iterator.next();
308
				lastIndex = delegate.previousIndex();
330
				lastIndex = iterator.previousIndex();
309
				return lastElement;
331
				return lastElement;
310
			}
332
			}
311
333
312
			public boolean hasPrevious() {
334
			public boolean hasPrevious() {
313
				getterCalled();
335
				getterCalled();
314
				checkForComodification();
336
				checkForComodification();
315
				return delegate.hasPrevious();
337
				return iterator.hasPrevious();
316
			}
338
			}
317
339
318
			public int previousIndex() {
340
			public int previousIndex() {
319
				getterCalled();
341
				getterCalled();
320
				checkForComodification();
342
				checkForComodification();
321
				return delegate.previousIndex();
343
				return iterator.previousIndex();
322
			}
344
			}
323
345
324
			public Object previous() {
346
			public Object previous() {
325
				getterCalled();
347
				getterCalled();
326
				checkForComodification();
348
				checkForComodification();
327
				lastElement = delegate.previous();
349
				lastElement = iterator.previous();
328
				lastIndex = delegate.nextIndex();
350
				lastIndex = iterator.nextIndex();
329
				return lastElement;
351
				return lastElement;
330
			}
352
			}
331
353
332
			public void add(Object o) {
354
			public void add(Object o) {
333
				checkRealm();
355
				checkRealm();
334
				checkForComodification();
356
				checkForComodification();
335
				int index = delegate.nextIndex();
357
				int index = iterator.nextIndex();
336
358
337
				delegate.add(o); // keep in sync
359
				iterator.add(o); // keep in sync
338
360
361
				List list = getList();
362
				list.add(index, o);
363
				ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(
364
						index, true, o));
339
				boolean wasUpdating = updating;
365
				boolean wasUpdating = updating;
366
				boolean changed;
340
				updating = true;
367
				updating = true;
341
				try {
368
				try {
342
					property.add(source, index, o);
369
					changed = property.setList(source, list, diff);
343
					modCount++;
370
					modCount++;
344
				} finally {
371
				} finally {
345
					updating = wasUpdating;
372
					updating = wasUpdating;
346
				}
373
				}
347
374
348
				cachedList = property.getList(source);
375
				if (changed) {
349
				fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
376
					cachedList = getList();
350
						index, true, o)));
377
					fireListChange(diff);
351
378
352
				lastElement = null;
379
					lastElement = null;
353
				lastIndex = -1;
380
					lastIndex = -1;
354
				expectedModCount = modCount;
381
					expectedModCount = modCount;
382
				}
355
			}
383
			}
356
384
357
			public void set(Object o) {
385
			public void set(Object o) {
358
				checkRealm();
386
				checkRealm();
359
				checkForComodification();
387
				checkForComodification();
360
388
361
				delegate.set(o);
389
				iterator.set(o);
390
				ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(
391
						lastIndex, false, lastElement), Diffs
392
						.createListDiffEntry(lastIndex, true, o));
362
393
363
				boolean wasUpdating = updating;
394
				boolean wasUpdating = updating;
395
				boolean changed;
364
				updating = true;
396
				updating = true;
365
				try {
397
				try {
366
					property.set(source, lastIndex, o);
398
					changed = property.setList(source, list, diff);
367
					modCount++;
399
					modCount++;
368
				} finally {
400
				} finally {
369
					updating = wasUpdating;
401
					updating = wasUpdating;
370
				}
402
				}
371
403
372
				cachedList = property.getList(source);
404
				if (changed) {
373
				fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
405
					cachedList = getList();
374
						lastIndex, false, lastElement), Diffs
406
					fireListChange(diff);
375
						.createListDiffEntry(lastIndex, true, o)));
376
407
377
				lastElement = o;
408
					lastElement = o;
378
409
379
				expectedModCount = modCount;
410
					expectedModCount = modCount;
411
				}
380
			}
412
			}
381
413
382
			public void remove() {
414
			public void remove() {
Lines 385-408 Link Here
385
				if (lastIndex == -1)
417
				if (lastIndex == -1)
386
					throw new IllegalStateException();
418
					throw new IllegalStateException();
387
419
388
				delegate.remove(); // keep in sync
420
				iterator.remove(); // keep in sync
421
				ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(
422
						lastIndex, false, lastElement));
389
423
390
				boolean wasUpdating = updating;
424
				boolean wasUpdating = updating;
425
				boolean changed;
391
				updating = true;
426
				updating = true;
392
				try {
427
				try {
393
					property.remove(source, lastIndex);
428
					changed = property.setList(source, list, diff);
394
					modCount++;
429
					modCount++;
395
				} finally {
430
				} finally {
396
					updating = wasUpdating;
431
					updating = wasUpdating;
397
				}
432
				}
398
433
399
				cachedList = property.getList(source);
434
				if (changed) {
400
				fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(
435
					cachedList = getList();
401
						lastIndex, false, lastElement)));
436
					fireListChange(diff);
402
437
403
				lastElement = null;
438
					lastElement = null;
404
				lastIndex = -1;
439
					lastIndex = -1;
405
				expectedModCount = modCount;
440
					expectedModCount = modCount;
441
				}
406
			}
442
			}
407
443
408
			private void checkForComodification() {
444
			private void checkForComodification() {
Lines 415-434 Link Here
415
	public Object remove(int index) {
451
	public Object remove(int index) {
416
		checkRealm();
452
		checkRealm();
417
453
418
		Object element;
454
		List list = new ArrayList(getList());
455
		Object element = list.remove(index);
456
		ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index,
457
				false, element));
419
458
420
		boolean wasUpdating = updating;
459
		boolean wasUpdating = updating;
460
		boolean changed;
421
		updating = true;
461
		updating = true;
422
		try {
462
		try {
423
			element = property.remove(source, index);
463
			changed = property.setList(source, list, diff);
424
			modCount++;
464
			modCount++;
425
		} finally {
465
		} finally {
426
			updating = wasUpdating;
466
			updating = wasUpdating;
427
		}
467
		}
428
468
429
		cachedList = property.getList(source);
469
		if (changed) {
430
		fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(index,
470
			cachedList = getList();
431
				false, element)));
471
			fireListChange(diff);
472
		}
432
473
433
		return element;
474
		return element;
434
	}
475
	}
Lines 436-463 Link Here
436
	public Object set(int index, Object o) {
477
	public Object set(int index, Object o) {
437
		checkRealm();
478
		checkRealm();
438
479
439
		Object oldElement;
480
		List list = new ArrayList(getList());
481
		Object oldElement = list.set(index, o);
482
483
		ListDiff diff = Diffs.createListDiff(Diffs.createListDiffEntry(index,
484
				false, oldElement), Diffs.createListDiffEntry(index, true, o));
440
485
441
		boolean wasUpdating = updating;
486
		boolean wasUpdating = updating;
487
		boolean changed;
442
		updating = true;
488
		updating = true;
443
		try {
489
		try {
444
			oldElement = property.set(source, index, o);
490
			changed = property.setList(source, list, diff);
445
			modCount++;
491
			modCount++;
446
		} finally {
492
		} finally {
447
			updating = wasUpdating;
493
			updating = wasUpdating;
448
		}
494
		}
449
495
450
		cachedList = property.getList(source);
496
		if (changed) {
451
		fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry(index,
497
			cachedList = getList();
452
				false, oldElement), Diffs.createListDiffEntry(index, true, o)));
498
			fireListChange(diff);
499
		}
453
500
454
		return oldElement;
501
		return oldElement;
455
	}
502
	}
456
503
457
	public List subList(int fromIndex, int toIndex) {
504
	public List subList(int fromIndex, int toIndex) {
458
		getterCalled();
505
		getterCalled();
459
		return Collections.unmodifiableList(property.getList(source).subList(
506
		return Collections.unmodifiableList(getList().subList(fromIndex,
460
				fromIndex, toIndex));
507
				toIndex));
461
	}
508
	}
462
509
463
	// Bulk change operations
510
	// Bulk change operations
Lines 465-471 Link Here
465
	public boolean addAll(Collection c) {
512
	public boolean addAll(Collection c) {
466
		checkRealm();
513
		checkRealm();
467
514
468
		return addAll(property.size(source), c);
515
		return addAll(getList().size(), c);
469
	}
516
	}
470
517
471
	public boolean addAll(int index, Collection c) {
518
	public boolean addAll(int index, Collection c) {
Lines 474-479 Link Here
474
		if (c.isEmpty())
521
		if (c.isEmpty())
475
			return false;
522
			return false;
476
523
524
		List list = new ArrayList(getList());
525
		list.addAll(index, c);
526
477
		ListDiffEntry[] entries = new ListDiffEntry[c.size()];
527
		ListDiffEntry[] entries = new ListDiffEntry[c.size()];
478
		int offsetIndex = 0;
528
		int offsetIndex = 0;
479
		for (Iterator it = c.iterator(); it.hasNext();) {
529
		for (Iterator it = c.iterator(); it.hasNext();) {
Lines 482-502 Link Here
482
					+ offsetIndex, true, element);
532
					+ offsetIndex, true, element);
483
			offsetIndex++;
533
			offsetIndex++;
484
		}
534
		}
535
		ListDiff diff = Diffs.createListDiff(entries);
485
536
486
		boolean changed;
537
		boolean changed;
487
538
488
		boolean wasUpdating = updating;
539
		boolean wasUpdating = updating;
489
		updating = true;
540
		updating = true;
490
		try {
541
		try {
491
			changed = property.addAll(source, index, c);
542
			changed = property.setList(source, list, diff);
492
			modCount++;
543
			modCount++;
493
		} finally {
544
		} finally {
494
			updating = wasUpdating;
545
			updating = wasUpdating;
495
		}
546
		}
496
547
497
		cachedList = property.getList(source);
548
		if (changed) {
498
		if (changed)
549
			cachedList = getList();
499
			fireListChange(Diffs.createListDiff(entries));
550
			fireListChange(diff);
551
		}
500
552
501
		return changed;
553
		return changed;
502
	}
554
	}
Lines 504-520 Link Here
504
	public boolean removeAll(Collection c) {
556
	public boolean removeAll(Collection c) {
505
		checkRealm();
557
		checkRealm();
506
558
507
		if (property.isEmpty(source) || c.isEmpty())
559
		if (c.isEmpty())
508
			return false;
560
			return false;
509
561
510
		boolean changed;
562
		List list = getList();
563
		if (list.isEmpty())
564
			return false;
511
565
566
		list = new ArrayList(list);
512
		List entries = new ArrayList();
567
		List entries = new ArrayList();
568
		ListDiff diff;
513
569
514
		boolean wasUpdating = updating;
570
		boolean wasUpdating = updating;
571
		boolean changed;
515
		updating = true;
572
		updating = true;
516
		try {
573
		try {
517
			List list = new ArrayList(property.getList(source));
518
			for (ListIterator it = list.listIterator(); it.hasNext();) {
574
			for (ListIterator it = list.listIterator(); it.hasNext();) {
519
				Object element = it.next();
575
				Object element = it.next();
520
				int index = it.previousIndex();
576
				int index = it.previousIndex();
Lines 524-540 Link Here
524
							.createListDiffEntry(index, false, element));
580
							.createListDiffEntry(index, false, element));
525
				}
581
				}
526
			}
582
			}
527
			changed = property.removeAll(source, c);
583
			if (entries.isEmpty())
584
				return false;
585
586
			diff = Diffs.createListDiff((ListDiffEntry[]) entries
587
					.toArray(new ListDiffEntry[entries.size()]));
588
			changed = property.setList(source, list, diff);
528
			modCount++;
589
			modCount++;
529
		} finally {
590
		} finally {
530
			updating = wasUpdating;
591
			updating = wasUpdating;
531
		}
592
		}
532
593
533
		cachedList = property.getList(source);
594
		if (changed) {
534
595
			cachedList = getList();
535
		if (changed)
596
			fireListChange(diff);
536
			fireListChange(Diffs.createListDiff((ListDiffEntry[]) entries
597
		}
537
					.toArray(new ListDiffEntry[entries.size()])));
538
598
539
		return changed;
599
		return changed;
540
	}
600
	}
Lines 542-548 Link Here
542
	public boolean retainAll(Collection c) {
602
	public boolean retainAll(Collection c) {
543
		checkRealm();
603
		checkRealm();
544
604
545
		if (property.isEmpty(source))
605
		List list = getList();
606
		if (list.isEmpty())
546
			return false;
607
			return false;
547
608
548
		if (c.isEmpty()) {
609
		if (c.isEmpty()) {
Lines 550-563 Link Here
550
			return true;
611
			return true;
551
		}
612
		}
552
613
553
		boolean changed;
614
		list = new ArrayList(list);
554
555
		List entries = new ArrayList();
615
		List entries = new ArrayList();
616
		ListDiff diff;
556
617
557
		boolean wasUpdating = updating;
618
		boolean wasUpdating = updating;
619
		boolean changed;
558
		updating = true;
620
		updating = true;
559
		try {
621
		try {
560
			List list = new ArrayList(property.getList(source));
561
			for (ListIterator it = list.listIterator(); it.hasNext();) {
622
			for (ListIterator it = list.listIterator(); it.hasNext();) {
562
				Object element = it.next();
623
				Object element = it.next();
563
				int index = it.previousIndex();
624
				int index = it.previousIndex();
Lines 567-583 Link Here
567
							.createListDiffEntry(index, false, element));
628
							.createListDiffEntry(index, false, element));
568
				}
629
				}
569
			}
630
			}
570
			changed = property.retainAll(source, c);
631
			if (entries.isEmpty())
632
				return false;
633
634
			diff = Diffs.createListDiff((ListDiffEntry[]) entries
635
					.toArray(new ListDiffEntry[entries.size()]));
636
			changed = property.setList(source, list, diff);
571
			modCount++;
637
			modCount++;
572
		} finally {
638
		} finally {
573
			updating = wasUpdating;
639
			updating = wasUpdating;
574
		}
640
		}
575
641
576
		cachedList = property.getList(source);
642
		if (changed) {
577
643
			cachedList = getList();
578
		if (changed)
644
			fireListChange(diff);
579
			fireListChange(Diffs.createListDiff((ListDiffEntry[]) entries
645
		}
580
					.toArray(new ListDiffEntry[entries.size()])));
581
646
582
		return changed;
647
		return changed;
583
	}
648
	}
Lines 585-621 Link Here
585
	public void clear() {
650
	public void clear() {
586
		checkRealm();
651
		checkRealm();
587
652
588
		if (property.isEmpty(source))
653
		List list = getList();
654
		if (list.isEmpty())
589
			return;
655
			return;
590
656
591
		List entries = new ArrayList();
657
		List entries = new ArrayList();
592
		for (Iterator it = property.getList(source).iterator(); it.hasNext();) {
658
		for (Iterator it = list.iterator(); it.hasNext();) {
593
			// always report 0 as the remove index
659
			// always report 0 as the remove index
594
			entries.add(Diffs.createListDiffEntry(0, false, it.next()));
660
			entries.add(Diffs.createListDiffEntry(0, false, it.next()));
595
		}
661
		}
596
662
663
		ListDiff diff = Diffs.createListDiff((ListDiffEntry[]) entries
664
				.toArray(new ListDiffEntry[entries.size()]));
597
		boolean wasUpdating = updating;
665
		boolean wasUpdating = updating;
666
		boolean changed;
598
		updating = true;
667
		updating = true;
599
		try {
668
		try {
600
			property.clear(source);
669
			changed = property.setList(source, Collections.EMPTY_LIST, diff);
601
			modCount++;
670
			modCount++;
602
		} finally {
671
		} finally {
603
			updating = wasUpdating;
672
			updating = wasUpdating;
604
		}
673
		}
605
674
606
		cachedList = property.getList(source);
675
		if (changed) {
607
		fireListChange(Diffs.createListDiff((ListDiffEntry[]) entries
676
			cachedList = getList();
608
				.toArray(new ListDiffEntry[entries.size()])));
677
			fireListChange(diff);
678
		}
609
	}
679
	}
610
680
611
	public boolean equals(Object o) {
681
	public boolean equals(Object o) {
612
		getterCalled();
682
		getterCalled();
613
		return property.equals(source, o);
683
		return getList().equals(o);
614
	}
684
	}
615
685
616
	public int hashCode() {
686
	public int hashCode() {
617
		getterCalled();
687
		getterCalled();
618
		return property.hashCode(source);
688
		return getList().hashCode();
619
	}
689
	}
620
690
621
	public Object getObserved() {
691
	public Object getObserved() {
(-)src/org/eclipse/core/internal/databinding/beans/BeanSetProperty.java (-5 / +6 lines)
Lines 63-73 Link Here
63
		return (Set) propertyValue;
63
		return (Set) propertyValue;
64
	}
64
	}
65
65
66
	protected void setSet(Object source, Set set, SetDiff diff) {
66
	protected boolean setSet(Object source, Set set, SetDiff diff) {
67
		if (source != null) {
67
		if (source == null)
68
			BeanPropertyHelper.writeProperty(source, propertyDescriptor,
68
			return false;
69
					convertSetToBeanPropertyType(set));
69
		BeanPropertyHelper.writeProperty(source, propertyDescriptor,
70
		}
70
				convertSetToBeanPropertyType(set));
71
		return true;
71
	}
72
	}
72
73
73
	private Object convertSetToBeanPropertyType(Set set) {
74
	private Object convertSetToBeanPropertyType(Set set) {
(-)src/org/eclipse/core/internal/databinding/beans/PojoValueProperty.java (-4 / +5 lines)
Lines 43-52 Link Here
43
		return BeanPropertyHelper.readProperty(source, propertyDescriptor);
43
		return BeanPropertyHelper.readProperty(source, propertyDescriptor);
44
	}
44
	}
45
45
46
	public void setValue(Object source, Object value) {
46
	public boolean setValue(Object source, Object value) {
47
		if (source != null) {
47
		if (source == null)
48
			BeanPropertyHelper.writeProperty(source, propertyDescriptor, value);
48
			return false;
49
		}
49
		BeanPropertyHelper.writeProperty(source, propertyDescriptor, value);
50
		return true;
50
	}
51
	}
51
52
52
	public PropertyDescriptor getPropertyDescriptor() {
53
	public PropertyDescriptor getPropertyDescriptor() {
(-)src/org/eclipse/core/internal/databinding/beans/PojoSetProperty.java (-5 / +6 lines)
Lines 59-69 Link Here
59
		return (Set) propertyValue;
59
		return (Set) propertyValue;
60
	}
60
	}
61
61
62
	protected void setSet(Object source, Set set, SetDiff diff) {
62
	protected boolean setSet(Object source, Set set, SetDiff diff) {
63
		if (source != null) {
63
		if (source == null)
64
			BeanPropertyHelper.writeProperty(source, propertyDescriptor,
64
			return false;
65
					convertSetToBeanPropertyType(set));
65
		BeanPropertyHelper.writeProperty(source, propertyDescriptor,
66
		}
66
				convertSetToBeanPropertyType(set));
67
		return true;
67
	}
68
	}
68
69
69
	private Object convertSetToBeanPropertyType(Set set) {
70
	private Object convertSetToBeanPropertyType(Set set) {
(-)src/org/eclipse/core/internal/databinding/beans/BeanListProperty.java (-5 / +6 lines)
Lines 64-74 Link Here
64
		return (List) propertyValue;
64
		return (List) propertyValue;
65
	}
65
	}
66
66
67
	protected void setList(Object source, List list, ListDiff diff) {
67
	protected boolean setList(Object source, List list, ListDiff diff) {
68
		if (source != null) {
68
		if (source == null)
69
			BeanPropertyHelper.writeProperty(source, propertyDescriptor,
69
			return false;
70
					convertListToBeanPropertyType(list));
70
		BeanPropertyHelper.writeProperty(source, propertyDescriptor,
71
		}
71
				convertListToBeanPropertyType(list));
72
		return true;
72
	}
73
	}
73
74
74
	private Object convertListToBeanPropertyType(List list) {
75
	private Object convertListToBeanPropertyType(List list) {
(-)src/org/eclipse/core/internal/databinding/beans/PojoMapProperty.java (-4 / +5 lines)
Lines 54-63 Link Here
54
		return (Map) propertyValue;
54
		return (Map) propertyValue;
55
	}
55
	}
56
56
57
	protected void setMap(Object source, Map map, MapDiff diff) {
57
	protected boolean setMap(Object source, Map map, MapDiff diff) {
58
		if (source != null) {
58
		if (source == null)
59
			BeanPropertyHelper.writeProperty(source, propertyDescriptor, map);
59
			return false;
60
		}
60
		BeanPropertyHelper.writeProperty(source, propertyDescriptor, map);
61
		return true;
61
	}
62
	}
62
63
63
	public PropertyDescriptor getPropertyDescriptor() {
64
	public PropertyDescriptor getPropertyDescriptor() {
(-)src/org/eclipse/core/internal/databinding/beans/BeanMapProperty.java (-4 / +5 lines)
Lines 58-67 Link Here
58
		return (Map) propertyValue;
58
		return (Map) propertyValue;
59
	}
59
	}
60
60
61
	protected void setMap(Object source, Map map, MapDiff diff) {
61
	protected boolean setMap(Object source, Map map, MapDiff diff) {
62
		if (source != null) {
62
		if (source == null)
63
			BeanPropertyHelper.writeProperty(source, propertyDescriptor, map);
63
			return false;
64
		}
64
		BeanPropertyHelper.writeProperty(source, propertyDescriptor, map);
65
		return true;
65
	}
66
	}
66
67
67
	public PropertyDescriptor getPropertyDescriptor() {
68
	public PropertyDescriptor getPropertyDescriptor() {
(-)src/org/eclipse/core/internal/databinding/beans/PojoListProperty.java (-5 / +6 lines)
Lines 60-70 Link Here
60
		return (List) propertyValue;
60
		return (List) propertyValue;
61
	}
61
	}
62
62
63
	protected void setList(Object source, List list, ListDiff diff) {
63
	protected boolean setList(Object source, List list, ListDiff diff) {
64
		if (source != null) {
64
		if (source == null)
65
			BeanPropertyHelper.writeProperty(source, propertyDescriptor,
65
			return false;
66
					convertListToBeanPropertyType(list));
66
		BeanPropertyHelper.writeProperty(source, propertyDescriptor,
67
		}
67
				convertListToBeanPropertyType(list));
68
		return true;
68
	}
69
	}
69
70
70
	private Object convertListToBeanPropertyType(List list) {
71
	private Object convertListToBeanPropertyType(List list) {
(-)src/org/eclipse/core/internal/databinding/beans/BeanValueProperty.java (-4 / +5 lines)
Lines 48-57 Link Here
48
		return BeanPropertyHelper.readProperty(source, propertyDescriptor);
48
		return BeanPropertyHelper.readProperty(source, propertyDescriptor);
49
	}
49
	}
50
50
51
	public void setValue(Object source, Object value) {
51
	public boolean setValue(Object source, Object value) {
52
		if (source != null) {
52
		if (source == null)
53
			BeanPropertyHelper.writeProperty(source, propertyDescriptor, value);
53
			return false;
54
		}
54
		BeanPropertyHelper.writeProperty(source, propertyDescriptor, value);
55
		return true;
55
	}
56
	}
56
57
57
	public PropertyDescriptor getPropertyDescriptor() {
58
	public PropertyDescriptor getPropertyDescriptor() {
(-)src/org/eclipse/jface/internal/databinding/viewers/SelectionProviderSingleSelectionProperty.java (-1 / +4 lines)
Lines 42-51 Link Here
42
		return null;
42
		return null;
43
	}
43
	}
44
44
45
	public void setValue(Object source, Object value) {
45
	public boolean setValue(Object source, Object value) {
46
		if (source == null)
47
			return false;
46
		((ISelectionProvider) source)
48
		((ISelectionProvider) source)
47
				.setSelection(value == null ? StructuredSelection.EMPTY
49
				.setSelection(value == null ? StructuredSelection.EMPTY
48
						: new StructuredSelection(value));
50
						: new StructuredSelection(value));
51
		return true;
49
	}
52
	}
50
53
51
	public INativePropertyListener adaptListener(
54
	public INativePropertyListener adaptListener(
(-)src/org/eclipse/jface/internal/databinding/viewers/ViewerInputProperty.java (-1 / +4 lines)
Lines 31-38 Link Here
31
		return ((Viewer) source).getInput();
31
		return ((Viewer) source).getInput();
32
	}
32
	}
33
33
34
	public void setValue(Object source, Object value) {
34
	public boolean setValue(Object source, Object value) {
35
		if (source == null)
36
			return false;
35
		((Viewer) source).setInput(value);
37
		((Viewer) source).setInput(value);
38
		return true;
36
	}
39
	}
37
40
38
	public INativePropertyListener adaptListener(
41
	public INativePropertyListener adaptListener(
(-)src/org/eclipse/jface/internal/databinding/viewers/StructuredViewerFiltersProperty.java (-1 / +4 lines)
Lines 38-44 Link Here
38
				.getFilters()));
38
				.getFilters()));
39
	}
39
	}
40
40
41
	public void setSet(Object source, Set set, SetDiff diff) {
41
	public boolean setSet(Object source, Set set, SetDiff diff) {
42
		if (source == null)
43
			return false;
42
		StructuredViewer viewer = (StructuredViewer) source;
44
		StructuredViewer viewer = (StructuredViewer) source;
43
		viewer.getControl().setRedraw(false);
45
		viewer.getControl().setRedraw(false);
44
		try {
46
		try {
Lines 47-52 Link Here
47
		} finally {
49
		} finally {
48
			viewer.getControl().setRedraw(true);
50
			viewer.getControl().setRedraw(true);
49
		}
51
		}
52
		return true;
50
	}
53
	}
51
54
52
	public INativePropertyListener adaptListener(
55
	public INativePropertyListener adaptListener(
(-)src/org/eclipse/jface/internal/databinding/viewers/CheckableCheckedElementsProperty.java (-1 / +4 lines)
Lines 56-62 Link Here
56
		return new HashSet();
56
		return new HashSet();
57
	}
57
	}
58
58
59
	protected void setSet(Object source, Set set, SetDiff diff) {
59
	protected boolean setSet(Object source, Set set, SetDiff diff) {
60
		if (source == null)
61
			return false;
60
		ICheckable checkable = (ICheckable) source;
62
		ICheckable checkable = (ICheckable) source;
61
		for (Iterator it = diff.getAdditions().iterator(); it.hasNext();) {
63
		for (Iterator it = diff.getAdditions().iterator(); it.hasNext();) {
62
			checkable.setChecked(it.next(), true);
64
			checkable.setChecked(it.next(), true);
Lines 64-69 Link Here
64
		for (Iterator it = diff.getRemovals().iterator(); it.hasNext();) {
66
		for (Iterator it = diff.getRemovals().iterator(); it.hasNext();) {
65
			checkable.setChecked(it.next(), false);
67
			checkable.setChecked(it.next(), false);
66
		}
68
		}
69
		return true;
67
	}
70
	}
68
71
69
	public INativePropertyListener adaptListener(
72
	public INativePropertyListener adaptListener(
(-)src/org/eclipse/jface/internal/databinding/viewers/SelectionProviderMultipleSelectionProperty.java (-1 / +4 lines)
Lines 45-53 Link Here
45
		return Collections.EMPTY_LIST;
45
		return Collections.EMPTY_LIST;
46
	}
46
	}
47
47
48
	protected void setList(Object source, List list, ListDiff diff) {
48
	protected boolean setList(Object source, List list, ListDiff diff) {
49
		if (source == null)
50
			return false;
49
		((ISelectionProvider) source)
51
		((ISelectionProvider) source)
50
				.setSelection(new StructuredSelection(list));
52
				.setSelection(new StructuredSelection(list));
53
		return true;
51
	}
54
	}
52
55
53
	public INativePropertyListener adaptListener(
56
	public INativePropertyListener adaptListener(
(-)src/org/eclipse/jface/internal/databinding/swt/ControlStringListProperty.java (-1 / +4 lines)
Lines 28-36 Link Here
28
		super(String.class);
28
		super(String.class);
29
	}
29
	}
30
30
31
	protected void setList(Object source, List list, ListDiff diff) {
31
	protected boolean setList(Object source, List list, ListDiff diff) {
32
		if (source == null)
33
			return false;
32
		String[] strings = (String[]) list.toArray(new String[list.size()]);
34
		String[] strings = (String[]) list.toArray(new String[list.size()]);
33
		doSetStringList((Control) source, strings);
35
		doSetStringList((Control) source, strings);
36
		return true;
34
	}
37
	}
35
38
36
	abstract void doSetStringList(Control control, String[] list);
39
	abstract void doSetStringList(Control control, String[] list);
(-)src/org/eclipse/jface/internal/databinding/swt/WidgetBooleanValueProperty.java (-1 / +4 lines)
Lines 32-41 Link Here
32
		return doGetBooleanValue(source) ? Boolean.TRUE : Boolean.FALSE;
32
		return doGetBooleanValue(source) ? Boolean.TRUE : Boolean.FALSE;
33
	}
33
	}
34
34
35
	public void setValue(Object source, Object value) {
35
	public boolean setValue(Object source, Object value) {
36
		if (source == null)
37
			return false;
36
		if (value == null)
38
		if (value == null)
37
			value = Boolean.FALSE;
39
			value = Boolean.FALSE;
38
		doSetBooleanValue(source, ((Boolean) value).booleanValue());
40
		doSetBooleanValue(source, ((Boolean) value).booleanValue());
41
		return true;
39
	}
42
	}
40
43
41
	abstract boolean doGetBooleanValue(Object source);
44
	abstract boolean doGetBooleanValue(Object source);
(-)src/org/eclipse/jface/internal/databinding/swt/ControlBackgroundProperty.java (-1 / +4 lines)
Lines 30-37 Link Here
30
		return ((Control) source).getBackground();
30
		return ((Control) source).getBackground();
31
	}
31
	}
32
32
33
	public void setValue(Object source, Object value) {
33
	public boolean setValue(Object source, Object value) {
34
		if (source == null)
35
			return false;
34
		((Control) source).setBackground((Color) value);
36
		((Control) source).setBackground((Color) value);
37
		return true;
35
	}
38
	}
36
39
37
	public String toString() {
40
	public String toString() {
(-)src/org/eclipse/jface/internal/databinding/swt/ControlSizeProperty.java (-1 / +4 lines)
Lines 32-39 Link Here
32
		return ((Control) source).getSize();
32
		return ((Control) source).getSize();
33
	}
33
	}
34
34
35
	public void setValue(Object source, Object value) {
35
	public boolean setValue(Object source, Object value) {
36
		if (source == null)
37
			return false;
36
		((Control) source).setSize((Point) value);
38
		((Control) source).setSize((Point) value);
39
		return true;
37
	}
40
	}
38
41
39
	public String toString() {
42
	public String toString() {
(-)src/org/eclipse/jface/internal/databinding/swt/WidgetStringValueProperty.java (-1 / +4 lines)
Lines 28-35 Link Here
28
		return doGetStringValue(source);
28
		return doGetStringValue(source);
29
	}
29
	}
30
30
31
	public void setValue(Object source, Object value) {
31
	public boolean setValue(Object source, Object value) {
32
		if (source == null)
33
			return false;
32
		doSetStringValue(source, (String) value);
34
		doSetStringValue(source, (String) value);
35
		return true;
33
	}
36
	}
34
37
35
	abstract String doGetStringValue(Object source);
38
	abstract String doGetStringValue(Object source);
(-)src/org/eclipse/jface/internal/databinding/swt/ControlFontProperty.java (-1 / +4 lines)
Lines 30-37 Link Here
30
		return ((Control) source).getFont();
30
		return ((Control) source).getFont();
31
	}
31
	}
32
32
33
	public void setValue(Object source, Object value) {
33
	public boolean setValue(Object source, Object value) {
34
		if (source == null)
35
			return false;
34
		((Control) source).setFont((Font) value);
36
		((Control) source).setFont((Font) value);
37
		return true;
35
	}
38
	}
36
39
37
	public String toString() {
40
	public String toString() {
(-)src/org/eclipse/jface/internal/databinding/swt/ControlBoundsProperty.java (-1 / +4 lines)
Lines 32-39 Link Here
32
		return ((Control) source).getBounds();
32
		return ((Control) source).getBounds();
33
	}
33
	}
34
34
35
	public void setValue(Object source, Object value) {
35
	public boolean setValue(Object source, Object value) {
36
		if (source == null)
37
			return false;
36
		((Control) source).setBounds((Rectangle) value);
38
		((Control) source).setBounds((Rectangle) value);
39
		return true;
37
	}
40
	}
38
41
39
	public String toString() {
42
	public String toString() {
(-)src/org/eclipse/jface/internal/databinding/swt/ControlForegroundProperty.java (-1 / +4 lines)
Lines 30-37 Link Here
30
		return ((Control) source).getForeground();
30
		return ((Control) source).getForeground();
31
	}
31
	}
32
32
33
	public void setValue(Object source, Object value) {
33
	public boolean setValue(Object source, Object value) {
34
		if (source == null)
35
			return false;
34
		((Control) source).setForeground((Color) value);
36
		((Control) source).setForeground((Color) value);
37
		return true;
35
	}
38
	}
36
39
37
	public String toString() {
40
	public String toString() {
(-)src/org/eclipse/jface/internal/databinding/swt/ControlLocationProperty.java (-1 / +4 lines)
Lines 32-39 Link Here
32
		return ((Control) source).getLocation();
32
		return ((Control) source).getLocation();
33
	}
33
	}
34
34
35
	public void setValue(Object source, Object value) {
35
	public boolean setValue(Object source, Object value) {
36
		if (source == null)
37
			return false;
36
		((Control) source).setLocation((Point) value);
38
		((Control) source).setLocation((Point) value);
39
		return true;
37
	}
40
	}
38
41
39
	public String toString() {
42
	public String toString() {
(-)src/org/eclipse/jface/internal/databinding/swt/WidgetIntValueProperty.java (-1 / +4 lines)
Lines 32-39 Link Here
32
		return new Integer(doGetIntValue(source));
32
		return new Integer(doGetIntValue(source));
33
	}
33
	}
34
34
35
	public void setValue(Object source, Object value) {
35
	public boolean setValue(Object source, Object value) {
36
		if (source == null)
37
			return false;
36
		doSetIntValue(source, ((Integer) value).intValue());
38
		doSetIntValue(source, ((Integer) value).intValue());
39
		return true;
37
	}
40
	}
38
41
39
	abstract int doGetIntValue(Object source);
42
	abstract int doGetIntValue(Object source);

Return to bug 194734