Mercurial > projects > dwt2
comparison org.eclipse.core.databinding.beans/src/org/eclipse/core/internal/databinding/beans/JavaBeanObservableList.d @ 95:6208d4f6a277
Added trees for databinding.beans and observable
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 21 Apr 2009 10:55:51 +0200 |
parents | |
children | b74ac5dfcc06 |
comparison
equal
deleted
inserted
replaced
94:1d37a7813832 | 95:6208d4f6a277 |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2006-2008 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM Corporation - initial API and implementation | |
10 * Brad Reynolds - bug 171616 | |
11 * Matthew Hall - bugs 208858, 221351, 213145, 223164, 244098 | |
12 * Mike Evans - bug 217558 | |
13 *******************************************************************************/ | |
14 | |
15 package org.eclipse.core.internal.databinding.beans; | |
16 | |
17 import java.beans.PropertyChangeListener; | |
18 import java.beans.PropertyDescriptor; | |
19 import java.lang.reflect.Array; | |
20 import java.lang.reflect.InvocationTargetException; | |
21 import java.lang.reflect.Method; | |
22 import java.util.ArrayList; | |
23 import java.util.Arrays; | |
24 import java.util.Collection; | |
25 import java.util.Iterator; | |
26 import java.util.List; | |
27 | |
28 import org.eclipse.core.databinding.BindingException; | |
29 import org.eclipse.core.databinding.beans.IBeanObservable; | |
30 import org.eclipse.core.databinding.observable.Diffs; | |
31 import org.eclipse.core.databinding.observable.Realm; | |
32 import org.eclipse.core.databinding.observable.list.ListDiffEntry; | |
33 import org.eclipse.core.databinding.observable.list.ObservableList; | |
34 | |
35 /** | |
36 * @since 1.0 | |
37 * | |
38 */ | |
39 public class JavaBeanObservableList : ObservableList , | |
40 IBeanObservable { | |
41 | |
42 private final Object object; | |
43 | |
44 private bool updating = false; | |
45 | |
46 private PropertyDescriptor descriptor; | |
47 | |
48 private ListenerSupport listenerSupport; | |
49 | |
50 /** | |
51 * @param realm | |
52 * @param object | |
53 * @param descriptor | |
54 * @param elementType | |
55 */ | |
56 public this(Realm realm, Object object, | |
57 PropertyDescriptor descriptor, Class elementType) { | |
58 this(realm, object, descriptor, elementType, true); | |
59 } | |
60 | |
61 /** | |
62 * @param realm | |
63 * @param object | |
64 * @param descriptor | |
65 * @param elementType | |
66 * @param attachListeners | |
67 */ | |
68 public this(Realm realm, Object object, | |
69 PropertyDescriptor descriptor, Class elementType, | |
70 bool attachListeners) { | |
71 | |
72 super(realm, new ArrayList(), elementType); | |
73 this.object = object; | |
74 this.descriptor = descriptor; | |
75 | |
76 if (attachListeners) { | |
77 PropertyChangeListener listener = new class() PropertyChangeListener { | |
78 public void propertyChange(java.beans.PropertyChangeEvent event) { | |
79 if (!updating) { | |
80 getRealm().exec(new class() Runnable { | |
81 public void run() { | |
82 updateWrappedList(new ArrayList(Arrays | |
83 .asList(getValues()))); | |
84 } | |
85 }); | |
86 } | |
87 } | |
88 }; | |
89 this.listenerSupport = new ListenerSupport(listener, | |
90 descriptor.getName()); | |
91 listenerSupport.hookListener(this.object); | |
92 } | |
93 | |
94 // initialize list without firing events | |
95 wrappedList.addAll(Arrays.asList(getValues())); | |
96 } | |
97 | |
98 public void dispose() { | |
99 if (listenerSupport !is null) { | |
100 listenerSupport.dispose(); | |
101 listenerSupport = null; | |
102 } | |
103 super.dispose(); | |
104 } | |
105 | |
106 private Object primGetValues() { | |
107 Exception ex = null; | |
108 try { | |
109 Method readMethod = descriptor.getReadMethod(); | |
110 if (!readMethod.isAccessible()) { | |
111 readMethod.setAccessible(true); | |
112 } | |
113 return readMethod.invoke(object, new Object[0]); | |
114 } catch (IllegalArgumentException e) { | |
115 ex = e; | |
116 } catch (IllegalAccessException e) { | |
117 ex = e; | |
118 } catch (InvocationTargetException e) { | |
119 ex = e; | |
120 } | |
121 throw new BindingException("Could not read collection values", ex); //$NON-NLS-1$ | |
122 } | |
123 | |
124 private Object[] getValues() { | |
125 Object[] values = null; | |
126 | |
127 Object result = primGetValues(); | |
128 if (descriptor.getPropertyType().isArray()) | |
129 values = cast(Object[]) result; | |
130 else { | |
131 // TODO add jUnit for POJO (var. SettableValue) collections | |
132 Collection list = cast(Collection) result; | |
133 if (list !is null) { | |
134 values = list.toArray(); | |
135 } | |
136 } | |
137 if (values is null) | |
138 values = new Object[0]; | |
139 return values; | |
140 } | |
141 | |
142 public Object getObserved() { | |
143 return object; | |
144 } | |
145 | |
146 public PropertyDescriptor getPropertyDescriptor() { | |
147 return descriptor; | |
148 } | |
149 | |
150 private void setValues() { | |
151 if (descriptor.getPropertyType().isArray()) { | |
152 Class componentType = descriptor.getPropertyType() | |
153 .getComponentType(); | |
154 Object[] newArray = cast(Object[]) Array.newInstance(componentType, | |
155 wrappedList.size()); | |
156 wrappedList.toArray(newArray); | |
157 primSetValues(newArray); | |
158 } else { | |
159 // assume that it is a java.util.List | |
160 primSetValues(new ArrayList(wrappedList)); | |
161 } | |
162 } | |
163 | |
164 private void primSetValues(Object newValue) { | |
165 Exception ex = null; | |
166 try { | |
167 Method writeMethod = descriptor.getWriteMethod(); | |
168 if (!writeMethod.isAccessible()) { | |
169 writeMethod.setAccessible(true); | |
170 } | |
171 writeMethod.invoke(object, new Object[] { newValue }); | |
172 return; | |
173 } catch (IllegalArgumentException e) { | |
174 ex = e; | |
175 } catch (IllegalAccessException e) { | |
176 ex = e; | |
177 } catch (InvocationTargetException e) { | |
178 ex = e; | |
179 } | |
180 throw new BindingException("Could not write collection values", ex); //$NON-NLS-1$ | |
181 } | |
182 | |
183 public Object set(int index, Object element) { | |
184 getterCalled(); | |
185 updating = true; | |
186 try { | |
187 Object oldElement = wrappedList.set(index, element); | |
188 setValues(); | |
189 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry( | |
190 index, false, oldElement), Diffs.createListDiffEntry(index, | |
191 true, element))); | |
192 return oldElement; | |
193 } finally { | |
194 updating = false; | |
195 } | |
196 } | |
197 | |
198 public Object move(int oldIndex, int newIndex) { | |
199 getterCalled(); | |
200 updating = true; | |
201 try { | |
202 int size = wrappedList.size(); | |
203 if (oldIndex < 0 || oldIndex >= size) | |
204 throw new IndexOutOfBoundsException( | |
205 "oldIndex: " + oldIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$ | |
206 if (newIndex < 0 || newIndex >= size) | |
207 throw new IndexOutOfBoundsException( | |
208 "newIndex: " + newIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$ | |
209 if (oldIndex is newIndex) | |
210 return wrappedList.get(oldIndex); | |
211 Object element = wrappedList.remove(oldIndex); | |
212 wrappedList.add(newIndex, element); | |
213 setValues(); | |
214 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry( | |
215 oldIndex, false, element), Diffs.createListDiffEntry( | |
216 newIndex, true, element))); | |
217 return element; | |
218 } finally { | |
219 updating = false; | |
220 } | |
221 } | |
222 | |
223 public Object remove(int index) { | |
224 getterCalled(); | |
225 updating = true; | |
226 try { | |
227 Object oldElement = wrappedList.remove(index); | |
228 setValues(); | |
229 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry( | |
230 index, false, oldElement))); | |
231 return oldElement; | |
232 } finally { | |
233 updating = false; | |
234 } | |
235 } | |
236 | |
237 public bool add(Object element) { | |
238 updating = true; | |
239 try { | |
240 int index = wrappedList.size(); | |
241 bool result = wrappedList.add(element); | |
242 setValues(); | |
243 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry( | |
244 index, true, element))); | |
245 return result; | |
246 } finally { | |
247 updating = false; | |
248 } | |
249 } | |
250 | |
251 public void add(int index, Object element) { | |
252 updating = true; | |
253 try { | |
254 wrappedList.add(index, element); | |
255 setValues(); | |
256 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry( | |
257 index, true, element))); | |
258 } finally { | |
259 updating = false; | |
260 } | |
261 } | |
262 | |
263 public bool addAll(Collection c) { | |
264 if (c.isEmpty()) { | |
265 return false; | |
266 } | |
267 updating = true; | |
268 try { | |
269 int index = wrappedList.size(); | |
270 bool result = wrappedList.addAll(c); | |
271 setValues(); | |
272 ListDiffEntry[] entries = new ListDiffEntry[c.size()]; | |
273 int i = 0; | |
274 for (Iterator it = c.iterator(); it.hasNext();) { | |
275 Object o = it.next(); | |
276 entries[i++] = Diffs.createListDiffEntry(index++, true, o); | |
277 } | |
278 fireListChange(Diffs.createListDiff(entries)); | |
279 return result; | |
280 } finally { | |
281 updating = false; | |
282 } | |
283 } | |
284 | |
285 public bool addAll(int index, Collection c) { | |
286 if (c.isEmpty()) { | |
287 return false; | |
288 } | |
289 updating = true; | |
290 try { | |
291 bool result = wrappedList.addAll(index, c); | |
292 setValues(); | |
293 ListDiffEntry[] entries = new ListDiffEntry[c.size()]; | |
294 int i = 0; | |
295 for (Iterator it = c.iterator(); it.hasNext();) { | |
296 Object o = it.next(); | |
297 entries[i++] = Diffs.createListDiffEntry(index++, true, o); | |
298 } | |
299 fireListChange(Diffs.createListDiff(entries)); | |
300 return result; | |
301 } finally { | |
302 updating = false; | |
303 } | |
304 } | |
305 | |
306 public bool remove(Object o) { | |
307 getterCalled(); | |
308 int index = wrappedList.indexOf(o); | |
309 if (index is -1) { | |
310 return false; | |
311 } | |
312 updating = true; | |
313 try { | |
314 Object oldElement = wrappedList.remove(index); | |
315 setValues(); | |
316 fireListChange(Diffs.createListDiff(Diffs.createListDiffEntry( | |
317 index, false, oldElement))); | |
318 return true; | |
319 } finally { | |
320 updating = false; | |
321 } | |
322 } | |
323 | |
324 public bool removeAll(Collection c) { | |
325 getterCalled(); | |
326 bool changed = false; | |
327 updating = true; | |
328 try { | |
329 List diffEntries = new ArrayList(); | |
330 for (Iterator it = c.iterator(); it.hasNext();) { | |
331 Object o = it.next(); | |
332 int index = wrappedList.indexOf(o); | |
333 if (index !is -1) { | |
334 changed = true; | |
335 Object oldElement = wrappedList.remove(index); | |
336 diffEntries.add(Diffs.createListDiffEntry(index, false, | |
337 oldElement)); | |
338 } | |
339 } | |
340 if (changed) { | |
341 setValues(); | |
342 fireListChange(Diffs | |
343 .createListDiff(cast(ListDiffEntry[]) diffEntries | |
344 .toArray(new ListDiffEntry[diffEntries.size()]))); | |
345 } | |
346 return changed; | |
347 } finally { | |
348 updating = false; | |
349 } | |
350 } | |
351 | |
352 public bool retainAll(Collection c) { | |
353 getterCalled(); | |
354 bool changed = false; | |
355 updating = true; | |
356 try { | |
357 List diffEntries = new ArrayList(); | |
358 int index = 0; | |
359 for (Iterator it = wrappedList.iterator(); it.hasNext();) { | |
360 Object o = it.next(); | |
361 bool retain = c.contains(o); | |
362 if (retain) { | |
363 index++; | |
364 } else { | |
365 changed = true; | |
366 it.remove(); | |
367 diffEntries.add(Diffs.createListDiffEntry(index, false, o)); | |
368 } | |
369 } | |
370 if (changed) { | |
371 setValues(); | |
372 fireListChange(Diffs | |
373 .createListDiff(cast(ListDiffEntry[]) diffEntries | |
374 .toArray(new ListDiffEntry[diffEntries.size()]))); | |
375 } | |
376 return changed; | |
377 } finally { | |
378 updating = false; | |
379 } | |
380 } | |
381 | |
382 public void clear() { | |
383 updating = true; | |
384 try { | |
385 List diffEntries = new ArrayList(); | |
386 for (Iterator it = wrappedList.iterator(); it.hasNext();) { | |
387 Object o = it.next(); | |
388 diffEntries.add(Diffs.createListDiffEntry(0, false, o)); | |
389 } | |
390 wrappedList.clear(); | |
391 setValues(); | |
392 fireListChange(Diffs.createListDiff(cast(ListDiffEntry[]) diffEntries | |
393 .toArray(new ListDiffEntry[diffEntries.size()]))); | |
394 } finally { | |
395 updating = false; | |
396 } | |
397 } | |
398 | |
399 } |