Mercurial > projects > dwt2
comparison org.eclipse.core.databinding.observable/src/org/eclipse/core/databinding/observable/list/ObservableList.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 - bugs 164653, 167204 | |
11 * Matthew Hall - bugs 208858, 208332, 245183 | |
12 * Tom Schindl - bug 245183 | |
13 *******************************************************************************/ | |
14 | |
15 package org.eclipse.core.databinding.observable.list; | |
16 | |
17 import java.util.Collection; | |
18 import java.util.Iterator; | |
19 import java.util.List; | |
20 import java.util.ListIterator; | |
21 | |
22 import org.eclipse.core.databinding.observable.AbstractObservable; | |
23 import org.eclipse.core.databinding.observable.Diffs; | |
24 import org.eclipse.core.databinding.observable.ObservableTracker; | |
25 import org.eclipse.core.databinding.observable.Realm; | |
26 | |
27 /** | |
28 * | |
29 * Abstract implementation of {@link IObservableList}, based on an underlying regular list. | |
30 * <p> | |
31 * This class is thread safe. All state accessing methods must be invoked from | |
32 * the {@link Realm#isCurrent() current realm}. Methods for adding and removing | |
33 * listeners may be invoked from any thread. | |
34 * </p> | |
35 * @since 1.0 | |
36 * | |
37 */ | |
38 public abstract class ObservableList : AbstractObservable , | |
39 IObservableList { | |
40 | |
41 protected List wrappedList; | |
42 | |
43 /** | |
44 * Stale state of the list. Access must occur in the current realm. | |
45 */ | |
46 private bool stale = false; | |
47 | |
48 private Object elementType; | |
49 | |
50 protected this(List wrappedList, Object elementType) { | |
51 this(Realm.getDefault(), wrappedList, elementType); | |
52 } | |
53 | |
54 protected this(Realm realm, List wrappedList, Object elementType) { | |
55 super(realm); | |
56 this.wrappedList = wrappedList; | |
57 this.elementType = elementType; | |
58 } | |
59 | |
60 public synchronized void addListChangeListener(IListChangeListener listener) { | |
61 addListener(ListChangeEvent.TYPE, listener); | |
62 } | |
63 | |
64 public synchronized void removeListChangeListener(IListChangeListener listener) { | |
65 removeListener(ListChangeEvent.TYPE, listener); | |
66 } | |
67 | |
68 protected void fireListChange(ListDiff diff) { | |
69 // fire general change event first | |
70 super.fireChange(); | |
71 fireEvent(new ListChangeEvent(this, diff)); | |
72 } | |
73 | |
74 public bool contains(Object o) { | |
75 getterCalled(); | |
76 return wrappedList.contains(o); | |
77 } | |
78 | |
79 public bool containsAll(Collection c) { | |
80 getterCalled(); | |
81 return wrappedList.containsAll(c); | |
82 } | |
83 | |
84 public override equals_t opEquals(Object o) { | |
85 getterCalled(); | |
86 | |
87 if (o is this) | |
88 return true; | |
89 if (o is null) | |
90 return false; | |
91 if (getClass() is o.getClass()) { | |
92 return wrappedList.equals((cast(ObservableList) o).wrappedList); | |
93 } | |
94 | |
95 return wrappedList.equals(o); | |
96 } | |
97 | |
98 public override hash_t toHash() { | |
99 getterCalled(); | |
100 return wrappedList.hashCode(); | |
101 } | |
102 | |
103 public bool isEmpty() { | |
104 getterCalled(); | |
105 return wrappedList.isEmpty(); | |
106 } | |
107 | |
108 public Iterator iterator() { | |
109 getterCalled(); | |
110 final Iterator wrappedIterator = wrappedList.iterator(); | |
111 return new class() Iterator { | |
112 | |
113 public void remove() { | |
114 throw new UnsupportedOperationException(); | |
115 } | |
116 | |
117 public bool hasNext() { | |
118 return wrappedIterator.hasNext(); | |
119 } | |
120 | |
121 public Object next() { | |
122 return wrappedIterator.next(); | |
123 } | |
124 }; | |
125 } | |
126 | |
127 public int size() { | |
128 getterCalled(); | |
129 return wrappedList.size(); | |
130 } | |
131 | |
132 public Object[] toArray() { | |
133 getterCalled(); | |
134 return wrappedList.toArray(); | |
135 } | |
136 | |
137 public Object[] toArray(Object[] a) { | |
138 getterCalled(); | |
139 return wrappedList.toArray(a); | |
140 } | |
141 | |
142 public String toString() { | |
143 getterCalled(); | |
144 return wrappedList.toString(); | |
145 } | |
146 | |
147 /** | |
148 * @TrackedGetter | |
149 */ | |
150 public Object get(int index) { | |
151 getterCalled(); | |
152 return wrappedList.get(index); | |
153 } | |
154 | |
155 /** | |
156 * @TrackedGetter | |
157 */ | |
158 public int indexOf(Object o) { | |
159 getterCalled(); | |
160 return wrappedList.indexOf(o); | |
161 } | |
162 | |
163 /** | |
164 * @TrackedGetter | |
165 */ | |
166 public int lastIndexOf(Object o) { | |
167 getterCalled(); | |
168 return wrappedList.lastIndexOf(o); | |
169 } | |
170 | |
171 // List Iterators | |
172 | |
173 /** | |
174 * @TrackedGetter | |
175 */ | |
176 public ListIterator listIterator() { | |
177 return listIterator(0); | |
178 } | |
179 | |
180 /** | |
181 * @TrackedGetter | |
182 */ | |
183 public ListIterator listIterator(int index) { | |
184 getterCalled(); | |
185 final ListIterator wrappedIterator = wrappedList.listIterator(index); | |
186 return new class() ListIterator { | |
187 | |
188 public int nextIndex() { | |
189 return wrappedIterator.nextIndex(); | |
190 } | |
191 | |
192 public int previousIndex() { | |
193 return wrappedIterator.previousIndex(); | |
194 } | |
195 | |
196 public void remove() { | |
197 throw new UnsupportedOperationException(); | |
198 } | |
199 | |
200 public bool hasNext() { | |
201 return wrappedIterator.hasNext(); | |
202 } | |
203 | |
204 public bool hasPrevious() { | |
205 return wrappedIterator.hasPrevious(); | |
206 } | |
207 | |
208 public Object next() { | |
209 return wrappedIterator.next(); | |
210 } | |
211 | |
212 public Object previous() { | |
213 return wrappedIterator.previous(); | |
214 } | |
215 | |
216 public void add(Object o) { | |
217 throw new UnsupportedOperationException(); | |
218 } | |
219 | |
220 public void set(Object o) { | |
221 throw new UnsupportedOperationException(); | |
222 } | |
223 }; | |
224 } | |
225 | |
226 | |
227 public List subList(final int fromIndex, final int toIndex) { | |
228 getterCalled(); | |
229 if (fromIndex < 0 || fromIndex > toIndex || toIndex > size()) { | |
230 throw new IndexOutOfBoundsException(); | |
231 } | |
232 return new AbstractObservableList(getRealm()) { | |
233 | |
234 public Object getElementType() { | |
235 return this.outer.getElementType(); | |
236 } | |
237 | |
238 public Object get(int location) { | |
239 return this.outer.get(fromIndex + location); | |
240 } | |
241 | |
242 protected int doGetSize() { | |
243 return toIndex - fromIndex; | |
244 } | |
245 }; | |
246 } | |
247 | |
248 protected void getterCalled() { | |
249 ObservableTracker.getterCalled(this); | |
250 } | |
251 | |
252 public Object set(int index, Object element) { | |
253 throw new UnsupportedOperationException(); | |
254 } | |
255 | |
256 /** | |
257 * Moves the element located at <code>oldIndex</code> to | |
258 * <code>newIndex</code>. This method is equivalent to calling | |
259 * <code>add(newIndex, remove(oldIndex))</code>. | |
260 * <p> | |
261 * Subclasses should override this method to deliver list change | |
262 * notification for the remove and add operations in the same | |
263 * ListChangeEvent, as this allows {@link ListDiff#acceptcast(ListDiffVisitor)} | |
264 * to recognize the operation as a move. | |
265 * | |
266 * @param oldIndex | |
267 * the element's position before the move. Must be within the | |
268 * range <code>0 <= oldIndex < size()</code>. | |
269 * @param newIndex | |
270 * the element's position after the move. Must be within the | |
271 * range <code>0 <= newIndex < size()</code>. | |
272 * @return the element that was moved. | |
273 * @throws IndexOutOfBoundsException | |
274 * if either argument is out of range (<code>0 <= index < size()</code>). | |
275 * @see ListDiffVisitor#handleMove(int, int, Object) | |
276 * @see ListDiff#acceptcast(ListDiffVisitor) | |
277 * @since 1.1 | |
278 */ | |
279 public Object move(int oldIndex, int newIndex) { | |
280 checkRealm(); | |
281 int size = wrappedList.size(); | |
282 if (oldIndex < 0 || oldIndex >= size) | |
283 throw new IndexOutOfBoundsException( | |
284 "oldIndex: " + oldIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$ | |
285 if (newIndex < 0 || newIndex >= size) | |
286 throw new IndexOutOfBoundsException( | |
287 "newIndex: " + newIndex + ", size:" + size); //$NON-NLS-1$ //$NON-NLS-2$ | |
288 Object element = remove(oldIndex); | |
289 add(newIndex, element); | |
290 return element; | |
291 } | |
292 | |
293 public Object remove(int index) { | |
294 throw new UnsupportedOperationException(); | |
295 } | |
296 | |
297 public bool add(Object o) { | |
298 throw new UnsupportedOperationException(); | |
299 } | |
300 | |
301 public void add(int index, Object element) { | |
302 throw new UnsupportedOperationException(); | |
303 } | |
304 | |
305 public bool addAll(Collection c) { | |
306 throw new UnsupportedOperationException(); | |
307 } | |
308 | |
309 public bool addAll(int index, Collection c) { | |
310 throw new UnsupportedOperationException(); | |
311 } | |
312 | |
313 public bool remove(Object o) { | |
314 throw new UnsupportedOperationException(); | |
315 } | |
316 | |
317 public bool removeAll(Collection c) { | |
318 throw new UnsupportedOperationException(); | |
319 } | |
320 | |
321 public bool retainAll(Collection c) { | |
322 throw new UnsupportedOperationException(); | |
323 } | |
324 | |
325 public void clear() { | |
326 throw new UnsupportedOperationException(); | |
327 } | |
328 | |
329 /** | |
330 * Returns the stale state. Must be invoked from the current realm. | |
331 * | |
332 * @return stale state | |
333 */ | |
334 public bool isStale() { | |
335 getterCalled(); | |
336 return stale; | |
337 } | |
338 | |
339 /** | |
340 * Sets the stale state. Must be invoked from the current realm. | |
341 * | |
342 * @param stale | |
343 * The stale state to list. This will fire a stale event if the | |
344 * given bool is true and this observable list was not already | |
345 * stale. | |
346 */ | |
347 public void setStale(bool stale) { | |
348 checkRealm(); | |
349 | |
350 bool wasStale = this.stale; | |
351 this.stale = stale; | |
352 if (!wasStale && stale) { | |
353 fireStale(); | |
354 } | |
355 } | |
356 | |
357 protected void fireChange() { | |
358 throw new RuntimeException("fireChange should not be called, use fireListChange() instead"); //$NON-NLS-1$ | |
359 } | |
360 | |
361 /* (non-Javadoc) | |
362 * @see org.eclipse.jface.provisional.databinding.observable.AbstractObservable#dispose() | |
363 */ | |
364 public synchronized void dispose() { | |
365 super.dispose(); | |
366 } | |
367 | |
368 public Object getElementType() { | |
369 return elementType; | |
370 } | |
371 | |
372 protected void updateWrappedList(List newList) { | |
373 List oldList = wrappedList; | |
374 ListDiff listDiff = Diffs.computeListDiff(oldList, newList); | |
375 wrappedList = newList; | |
376 fireListChange(listDiff); | |
377 } | |
378 | |
379 } |