View Javadoc

1   /*
2   Wotonomy: OpenStep design patterns for pure Java applications.
3   Copyright (C) 2001 Michael Powers
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  Lesser General Public License for more details.
14  
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, see http://www.gnu.org
17  */
18  
19  package net.wotonomy.ui;
20  
21  import java.util.Collection;
22  import java.util.Iterator;
23  import java.util.List;
24  
25  import net.wotonomy.control.EOObserverCenter;
26  import net.wotonomy.control.EOObserving;
27  import net.wotonomy.foundation.NSMutableArray;
28  import net.wotonomy.foundation.NSRange;
29  
30  /***
31  * A package class that extends NSMutableArray but makes use
32  * of the fact that wotonomy's implementation extends ArrayList
33  * to intercept insertions and deletion and register and 
34  * unregister objects for change notifications as appropriate.
35  * Since we can't be sure of ArrayList's implementation, we're
36  * forced to override each and every add and remove method,
37  * some of which probably call each other.  However, 
38  * EOObserverCenter will only register us once per object.
39  */
40  class ObservableArray extends NSMutableArray
41  {
42      EOObserving observer;
43      
44      ObservableArray( EOObserving anObserver )
45      {
46          observer = anObserver;
47      }
48      
49  	/***
50  	* Removes the last object from the array.
51  	*/
52      public void removeLastObject ()
53      {
54  		remove( count() - 1 );    
55      }
56  
57  	/***
58  	* Removes the object at the specified index.
59  	*/
60      public void removeObjectAtIndex (int index)
61      {
62      	remove( index );
63      }
64  
65  	/***
66  	* Adds all objects in the specified collection.
67  	*/
68      public void addObjectsFromArray (Collection aCollection)
69      {
70      	addAll( aCollection );
71      }
72  
73  	/***
74  	* Removes all objects from the array.
75  	*/
76      public void removeAllObjects ()
77      {
78      	clear();
79      }
80  
81  	/***
82  	* Removes all objects equivalent to the specified object
83  	* within the range of specified indices.
84  	*/
85      public void removeObject (Object anObject, NSRange aRange)
86      {
87      	if ( ( anObject == null ) || ( aRange == null ) ) return;
88  	    
89  	    int loc = aRange.location();
90  	    int max = aRange.maxRange();
91  	    for ( int i = loc; i < max; i++ )
92  	    {
93  	    	if ( anObject.equals( get( i ) ) )
94  		    {
95  		    	remove( i );
96  			    i = i - 1;
97  			    max = max - 1;
98  		    }
99  	    }
100     }
101 
102 	/***
103 	* Removes all instances of the specified object within the 
104 	* range of specified indices, comparing by reference.
105 	*/
106     public void removeIdenticalObject (Object anObject, NSRange aRange)
107     {
108     	if ( ( anObject == null ) || ( aRange == null ) ) return;
109 	    
110 	    int loc = aRange.location();
111 	    int max = aRange.maxRange();
112 	    for ( int i = loc; i < max; i++ )
113 	    {
114 	    	if ( anObject == get( i ) )
115 		    {
116 		    	remove( i );
117 			    i = i - 1;
118 			    max = max - 1;
119 		    }
120 	    }
121     }
122 
123 	/***
124 	* Removes all objects in the specified collection from the array.
125 	*/
126     public void removeObjectsInArray (Collection aCollection)
127     {
128     	removeAll( aCollection );
129     }
130 
131 	/***
132 	* Removes all objects in the indices within the specified range 
133 	* from the array.
134 	*/
135     public void removeObjectsInRange (NSRange aRange)
136     {
137     	if ( aRange == null ) return;
138 	    
139 	    for ( int i = 0; i < aRange.length(); i++ )
140 	    {
141 	    	remove( aRange.location() );
142 	    }
143     }
144 
145 	/***
146 	* Replaces objects in the current range with objects from
147 	* the specified range of the specified array.  If currentRange
148 	* is larger than otherRange, the extra objects are removed.
149 	* If otherRange is larger than currentRange, the extra objects
150 	* are added.
151 	*/
152     public void replaceObjectsInRange (NSRange currentRange, 
153     	List otherArray, NSRange otherRange)
154 	{
155 		if ( ( currentRange == null ) || ( otherArray == null ) ||
156 			( otherRange == null ) ) return;
157 	
158 		// transform otherRange if out of bounds for array
159 		if ( otherRange.maxRange() > otherArray.size() )
160 		{
161 			// TODO: Test this logic.
162 			int loc = Math.min( otherRange.location(), otherArray.size() - 1 );
163 			otherRange = new NSRange( loc, otherArray.size() - loc ); 
164 		}
165 		
166 		Object o;
167 		List subList = subList( 
168 			currentRange.location(), currentRange.maxRange() );
169 		int otherIndex = otherRange.location();
170 		// TODO: Test this logic.
171 		for ( int i = 0; i < subList.size(); i++ )
172 		{
173 			if ( otherIndex < otherRange.maxRange() )
174 			{ // set object
175 				subList.set( i, otherArray.get( otherIndex ) ); 
176 			}
177 			else
178 			{ // remove extra elements from currentRange
179 				subList.remove( i );
180 				i--; 
181 			}
182 			otherIndex++;
183 		}
184 		// TODO: Test this logic.
185 		for ( int i = otherIndex; i < otherRange.maxRange(); i++ )
186 		{
187 			add( otherArray.get( i ) );
188 		}
189 	}
190 
191 	/***
192 	* Clears the current array and then populates it with the
193 	* contents of the specified collection.
194 	*/
195     public void setArray (Collection aCollection)
196     {
197     	clear();
198 	    addAll( aCollection );
199     }
200 
201 	/***
202 	* Removes all objects equivalent to the specified object. 
203 	*/
204     public void removeObject (Object anObject)
205     {
206         remove( anObject );
207     }
208 
209 	/***
210 	* Removes all occurences of the specified object,
211 	* comparing by reference.
212 	*/
213     public void removeIdenticalObject (Object anObject)
214     {
215         EOObserverCenter.removeObserver( observer, anObject );
216         super.removeIdenticalObject( anObject );
217     }
218 
219 	/***
220 	* Inserts the specified object into this array at the
221 	* specified index.
222 	*/
223     public void insertObjectAtIndex (Object anObject, int anIndex)
224     {
225     	add( anIndex, anObject );
226     }
227     
228 	/***
229 	* Replaces the object at the specified index with the 
230 	* specified object.
231 	*/
232     public void replaceObjectAtIndex (int anIndex, Object anObject)
233     {
234     	set( anIndex, anObject );
235     }
236 
237 	/***
238 	* Adds the specified object to the end of this array.
239 	*/
240     public void addObject (Object anObject) 
241     {
242     	add( anObject );
243     }
244     
245     // interface List: mutators
246 
247 	public void add(int index, Object element) 
248     {
249         EOObserverCenter.addObserver( observer, element );
250         super.add( index, element );
251     }
252     
253 	public boolean add(Object o)
254     {
255         EOObserverCenter.addObserver( observer, o );
256         return super.add(o);
257     }
258 
259 	public boolean addAll(Collection coll) 
260     {
261         Iterator it = coll.iterator();
262         while ( it.hasNext() )
263         {
264             EOObserverCenter.addObserver( observer, it.next() );
265         }
266         return super.addAll(coll);
267     }
268 
269 	public boolean addAll(int index, Collection c) 
270     {
271         Iterator it = c.iterator();
272         while ( it.hasNext() )
273         {
274             EOObserverCenter.addObserver( observer, it.next() );
275         }
276         return super.addAll( index, c );
277     }
278     
279 	public void clear() 
280     {
281         Iterator it = iterator();
282         while ( it.hasNext() )
283         {
284             EOObserverCenter.removeObserver( observer, it.next() );
285         }
286         super.clear();
287     }
288 
289 	public Object remove(int index) 
290     {
291         EOObserverCenter.removeObserver( observer, get(index) );
292         return super.remove( index );
293     }
294     
295 	public boolean remove(Object o) 
296     {
297         EOObserverCenter.removeObserver( observer, o );
298         return super.remove(o);
299     }
300 
301 	public boolean removeAll(Collection coll) 
302     {
303         Iterator it = coll.iterator();
304         while ( it.hasNext() )
305         {
306             EOObserverCenter.removeObserver( observer, it.next() );
307         }
308         return super.removeAll(coll);
309     }
310 
311 	public boolean retainAll(Collection coll) 
312     {
313         throw new UnsupportedOperationException();
314     }
315 
316     public Object set(int index, Object element) 
317     {
318         EOObserverCenter.removeObserver( observer, get(index) );
319         EOObserverCenter.addObserver( observer, element );
320         return super.set( index, element );
321     }
322 }
323 
324 /*
325  * $Log$
326  * Revision 1.2  2006/02/18 23:14:35  cgruber
327  * Update imports and maven dependencies.
328  *
329  * Revision 1.1  2006/02/16 13:22:22  cgruber
330  * Check in all sources in eclipse-friendly maven-enabled packages.
331  *
332  * Revision 1.3  2003/08/06 23:07:52  chochos
333  * general code cleanup (mostly, removing unused imports)
334  *
335  * Revision 1.2  2002/10/24 21:15:36  mpowers
336  * New implementations of NSArray and subclasses.
337  *
338  * Revision 1.1  2001/02/20 16:38:55  mpowers
339  * MasterDetailAssociations now observe their controlled display group's
340  * objects for changes to that the parent object will be marked as updated.
341  * Before, only inserts and deletes to an object's items are registered.
342  * Also, moved ObservableArray to package access.
343  *
344  * Revision 1.1  2001/01/24 14:37:24  mpowers
345  * Contributing a delegate useful for debugging.
346  *
347  *
348  */
349