001 /*
002 * This file is part of muCommander, http://www.mucommander.com
003 * Copyright (C) 2002-2008 Maxence Bernard
004 *
005 * muCommander is free software; you can redistribute it and/or modify
006 * it under the terms of the GNU General Public License as published by
007 * the Free Software Foundation; either version 3 of the License, or
008 * (at your option) any later version.
009 *
010 * muCommander is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License
016 * along with this program. If not, see <http://www.gnu.org/licenses/>.
017 */
018
019 package com.mucommander.util;
020
021 import java.util.Collection;
022 import java.util.Iterator;
023 import java.util.Vector;
024 import java.util.WeakHashMap;
025
026 /**
027 * AlteredVector is a Vector that is able to notify registered listeners whenever its contents has changed.
028 * <p>
029 * Events are triggered when:
030 * <ul>
031 * <li>one or more elements has been added
032 * <li>one or more elements has been removed
033 * <li>an element has been changed
034 * </ul>
035 * </p>
036 * <p>It is however not aware of modifications that are made to the contained objects themselves.</p>
037 *
038 * @author Maxence Bernard
039 */
040 public class AlteredVector extends Vector {
041
042 /** Contains all registered listeners, stored as weak references */
043 private WeakHashMap listeners = new WeakHashMap();
044
045
046 public AlteredVector() {
047 super();
048 }
049
050 public AlteredVector(Collection collection) {
051 super(collection);
052 }
053
054 public AlteredVector(int initialCapacity, int capacityIncrement) {
055 super(initialCapacity, capacityIncrement);
056 }
057
058 public AlteredVector(int initialCapacity) {
059 super(initialCapacity);
060 }
061
062
063 /**
064 * Adds the specified VectorChangeListener to the list of registered listeners.
065 *
066 * <p>Listeners are stored as weak references so {@link #removeVectorChangeListener(VectorChangeListener)}
067 * doesn't need to be called for listeners to be garbage collected when they're not used anymore.</p>
068 *
069 * @param listener the VectorChangeListener to add to the list of registered listeners.
070 * @see #removeVectorChangeListener(VectorChangeListener)
071 */
072 public void addVectorChangeListener(VectorChangeListener listener) {
073 listeners.put(listener, null);
074 }
075
076 /**
077 * Removes the specified VectorChangeListener from the list of registered listeners.
078 *
079 * @param listener the VectorChangeListener to remove from the list of registered listeners.
080 * @see #addVectorChangeListener(VectorChangeListener)
081 */
082 public void removeVectorChangeListener(VectorChangeListener listener) {
083 listeners.remove(listener);
084 }
085
086
087 /**
088 * This method is called when one or more elements has been added to this AlteredVector to notify listeners.
089 *
090 * @param startIndex index at which the first element has been added
091 * @param nbAdded number of elements added
092 */
093 private void fireElementsAddedEvent(int startIndex, int nbAdded) {
094 Iterator iterator = listeners.keySet().iterator();
095 while(iterator.hasNext())
096 ((VectorChangeListener)iterator.next()).elementsAdded(startIndex, nbAdded);
097 }
098
099 /**
100 * This method is called when one or more elements has been removed from this AlteredVector to notify listeners.
101 *
102 * @param startIndex index at which the first element has been removed
103 * @param nbRemoved number of elements removed
104 */
105 private void fireElementsRemovedEvent(int startIndex, int nbRemoved) {
106 Iterator iterator = listeners.keySet().iterator();
107 while(iterator.hasNext())
108 ((VectorChangeListener)iterator.next()).elementsRemoved(startIndex, nbRemoved);
109 }
110
111 /**
112 * This method is called when an element has been changed in this AlteredVector to notify listeners.
113 *
114 * @param index index of the element that has been changed
115 */
116 private void fireElementChangedEvent(int index) {
117 Iterator iterator = listeners.keySet().iterator();
118 while(iterator.hasNext())
119 ((VectorChangeListener)iterator.next()).elementChanged(index);
120 }
121
122
123 ////////////////////////
124 // Overridden methods //
125 ////////////////////////
126
127 public void setElementAt(Object o, int i) {
128 super.setElementAt(o, i);
129
130 fireElementChangedEvent(i);
131 }
132
133 public Object set(int i, Object o) {
134 o = super.set(i, o);
135
136 fireElementChangedEvent(i);
137
138 return o;
139 }
140
141 public void insertElementAt(Object o, int i) {
142 super.insertElementAt(o, i);
143
144 fireElementsAddedEvent(i, 1);
145 }
146
147 public void add(int i, Object o) {
148 insertElementAt(o, i);
149
150 fireElementsAddedEvent(i, 1);
151 }
152
153 public void addElement(Object o) {
154 super.addElement(o);
155
156 fireElementsAddedEvent(size()-1, 1);
157 }
158
159 public boolean add(Object o) {
160 addElement(o);
161
162 fireElementsAddedEvent(size()-1, 1);
163
164 return true;
165 }
166
167 public boolean addAll(Collection collection) {
168 int sizeBefore = size();
169
170 boolean b = super.addAll(collection);
171
172 fireElementsAddedEvent(sizeBefore, size()-sizeBefore);
173
174 return b;
175 }
176
177 public boolean addAll(int i, Collection collection) {
178 int sizeBefore = size();
179
180 boolean b = super.addAll(i, collection);
181
182 fireElementsAddedEvent(i, size()-sizeBefore);
183
184 return b;
185 }
186
187 public void removeElementAt(int i) {
188 super.removeElementAt(i);
189
190 fireElementsRemovedEvent(i, 1);
191 }
192
193 public Object remove(int i) {
194 Object o = super.remove(i);
195
196 fireElementsRemovedEvent(i, 1);
197
198 return o;
199 }
200
201 public boolean removeElement(Object o) {
202 int index = indexOf(o);
203
204 if(index==-1)
205 return false;
206
207 removeElementAt(index);
208
209 return true;
210 }
211
212 public boolean remove(Object o) {
213 return removeElement(o);
214 }
215
216 public void removeAllElements() {
217 int sizeBefore = size();
218
219 super.removeAllElements();
220
221 fireElementsRemovedEvent(0, sizeBefore);
222 }
223
224 public void clear() {
225 removeAllElements();
226 }
227 }