001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.event;
017:
018: /**
019: * A List to hold objects being tracked by the GTEvent system, note this list
020: * is event aware, and will fire off events to a getParent.
021: *
022: * <p>
023: * Special attention is paid to children that are GTComponents (they will have
024: * setParent called). This list is not limited to GTComponent children, a
025: * native Java type like Color will do just fine.
026: * </p>
027: *
028: * <p>
029: * This list is used to maintain list or array properties in implementations
030: * such as FeatureTypeStyle.
031: * </p>
032: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/event/GTList.java $
033: */
034: import java.util.ArrayList;
035: import java.util.Collection;
036: import java.util.Iterator;
037: import java.util.List;
038:
039: public class GTList extends ArrayList implements List {
040: private static final long serialVersionUID = -4849245752797538846L;
041: // private List delegate; // TODO use a list delegate
042: private GTComponent host;
043: private String notificationName;
044:
045: /**
046: * Package visiable constructor for test purposes
047: */
048: GTList() {
049: this (GTRoot.NO_PARENT, "");
050: }
051:
052: /**
053: * Client code must construct with a GTComponent parent (in order to fire
054: * events).
055: *
056: * @param host Host for this list
057: * @param listName DOCUMENT ME!
058: */
059: public GTList(GTComponent host, String listName) {
060: this .host = host;
061: this .notificationName = listName;
062: }
063:
064: /**
065: * Indicate that the range has been added.
066: *
067: * <p>
068: * Performs all the book keeping but does not actually add, or fire
069: * notifications.
070: * </p>
071: *
072: * @param fromIndex DOCUMENT ME!
073: * @param toIndex DOCUMENT ME!
074: *
075: * @return DOCUMENT ME!
076: */
077: private List deltaAdded(int fromIndex, int toIndex) {
078: int position = fromIndex;
079: List range = subList(fromIndex, toIndex);
080: List added = new ArrayList(range.size());
081:
082: for (Iterator i = range.iterator(); i.hasNext(); position++) {
083: Object item = i.next();
084: added.add(deltaAdded(position, item));
085: }
086:
087: return added;
088: }
089:
090: private GTDelta deltaAdded(int position, Object item) {
091: if (item instanceof GTComponent) {
092: GTComponent myChild = (GTComponent) item;
093: myChild.setNote(note(position));
094: }
095:
096: GTDelta delta = new GTDeltaImpl(new GTNoteImpl(
097: notificationName, position), GTDelta.Kind.ADDED, item,
098: null);
099:
100: return delta;
101: }
102:
103: protected GTNote note(int position) {
104: return new GTNoteImpl(host, notificationName, position);
105: }
106:
107: /**
108: * Indicate that the range has been moved
109: *
110: * <p>
111: * Performs all the book keeping but does not actually move, or fire
112: * notifications.
113: * </p>
114: *
115: * @param fromIndex DOCUMENT ME!
116: * @param toIndex DOCUMENT ME!
117: *
118: * @return DOCUMENT ME!
119: */
120: private List deltaMove(int fromIndex, int toIndex) {
121: int position = fromIndex;
122: List rest = subList(fromIndex, toIndex);
123: List moved = new ArrayList(rest.size());
124:
125: for (Iterator i = rest.iterator(); i.hasNext(); position++) {
126: Object item = i.next();
127: moved.add(deltaSync(position, item));
128: }
129:
130: return moved;
131: }
132:
133: private GTDelta deltaSync(int position, Object item) {
134: if (item instanceof GTComponent) {
135: GTComponent myChild = (GTComponent) item;
136: myChild.setNote(GTNote.EMPTY);
137: myChild.setNote(note(position));
138: }
139: GTDelta delta = new GTDeltaImpl(new GTNoteImpl(
140: notificationName, position), GTDelta.Kind.NO_CHANGE,
141: item, null);
142:
143: return delta;
144: }
145:
146: /**
147: * Indicate that the range has been removed.
148: *
149: * <p>
150: * Performs all the book keeping but does not actually remove, or fire
151: * notifications.
152: * </p>
153: *
154: * @param fromIndex DOCUMENT ME!
155: * @param toIndex DOCUMENT ME!
156: *
157: * @return DOCUMENT ME!
158: */
159: private List deltaRemoved(int fromIndex, int toIndex) {
160: int position = fromIndex;
161: List rest = subList(fromIndex, toIndex);
162: List removed = new ArrayList(rest.size());
163:
164: for (Iterator i = rest.iterator(); i.hasNext(); position++) {
165: Object item = i.next();
166: removed.add(deltaRemoved(position, item));
167: }
168:
169: return removed;
170: }
171:
172: private List deltaRemoved(Collection collection) {
173: List removed = new ArrayList(collection.size());
174:
175: for (Iterator i = collection.iterator(); i.hasNext();) {
176: Object item = i.next();
177: int position = indexOf(item);
178: removed.add(deltaRemoved(position, item));
179: }
180:
181: return removed;
182: }
183:
184: private GTDelta deltaRemoved(int position, Object item) {
185: if (item instanceof GTComponent) {
186: GTComponent myChild = (GTComponent) item;
187: myChild.setNote(GTNote.EMPTY);
188: }
189: GTDelta delta = new GTDeltaImpl(new GTNoteImpl(
190: notificationName, position), GTDelta.Kind.REMOVED,
191: null, item);
192:
193: return delta;
194: }
195:
196: public boolean add(Object item) {
197: boolean added = super .add(item);
198:
199: GTDelta delta;
200: delta = deltaAdded(size() - 1, item);
201: delta = new GTDeltaImpl(new GTNoteImpl(notificationName,
202: GTDelta.NO_INDEX), GTDelta.Kind.CHANGED, host, delta);
203: host.getNote().getParent().changed(delta);
204:
205: return added;
206: }
207:
208: /**
209: * Fire even when added
210: *
211: * @param index
212: * @param item
213: */
214: public void add(int index, Object item) {
215: super .add(index, item);
216:
217: GTDelta delta;
218: delta = deltaAdded(index, item);
219: delta = new GTDeltaImpl(new GTNoteImpl(notificationName,
220: GTDelta.NO_INDEX), GTDelta.Kind.CHANGED, host, delta);
221: host.getNote().getParent().changed(delta);
222: }
223:
224: public boolean addAll(Collection list) {
225: int position = isEmpty() ? 0 : (size() - 1);
226: boolean added = super .addAll(list);
227:
228: List changed = deltaAdded(position, size());
229: GTDelta delta;
230: delta = new GTDeltaImpl(new GTNoteImpl(notificationName,
231: GTDelta.NO_INDEX), GTDelta.Kind.CHANGED, host, changed);
232: host.getNote().getParent().changed(delta);
233:
234: return added;
235: }
236:
237: public boolean addAll(int index, Collection list) {
238: int start = index;
239: int end = start + list.size();
240:
241: boolean added = super .addAll(index, list);
242: List changed = deltaAdded(start, end);
243: changed.addAll(deltaMove(end, size()));
244:
245: GTDelta delta;
246: delta = new GTDeltaImpl(new GTNoteImpl(notificationName,
247: GTDelta.NO_INDEX), GTDelta.Kind.CHANGED, host, changed);
248: host.getNote().getParent().changed(delta);
249:
250: return added;
251: }
252:
253: public void clear() {
254: super .clear();
255:
256: GTDelta delta;
257: delta = new GTDeltaImpl(new GTNoteImpl(notificationName,
258: GTDelta.NO_INDEX), GTDelta.Kind.CHANGED, host);
259: host.getNote().getParent().changed(delta);
260: }
261:
262: public Object remove(int index) {
263: List changed = deltaRemoved(index, index + 1);
264: Object item = super .remove(index);
265:
266: changed.addAll(deltaMove(index, size()));
267:
268: GTDelta delta = new GTDeltaImpl(new GTNoteImpl(
269: notificationName, GTDelta.NO_INDEX),
270: GTDelta.Kind.CHANGED, host, changed);
271: host.getNote().getParent().changed(delta);
272:
273: return item;
274: }
275:
276: public boolean remove(Object item) {
277: int index = indexOf(item);
278:
279: if (index == -1) {
280: return false;
281: }
282:
283: remove(index);
284:
285: return true;
286: }
287:
288: public boolean removeAll(Collection collection) {
289: List changed = deltaRemoved(collection);
290: boolean removed = super .removeAll(collection);
291: changed.addAll(deltaMove(0, size()));
292:
293: GTDelta delta = new GTDeltaImpl(new GTNoteImpl(
294: notificationName, GTDelta.NO_INDEX),
295: GTDelta.Kind.CHANGED, host, changed);
296: host.getNote().getParent().changed(delta);
297:
298: return removed;
299: }
300:
301: protected void removeRange(int fromIndex, int toIndex) {
302: List changed = deltaRemoved(fromIndex, toIndex);
303:
304: super .removeRange(fromIndex, toIndex);
305:
306: changed.addAll(deltaMove(0, size()));
307:
308: GTDelta delta = new GTDeltaImpl(new GTNoteImpl(
309: notificationName, GTDelta.NO_INDEX),
310: GTDelta.Kind.CHANGED, host, changed);
311: host.getNote().getParent().changed(delta);
312: }
313: }
|