001: /* ListModelList.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Thu Nov 23 17:43:13 2006, Created by Henri Chen
010: }}IS_NOTE
011:
012: Copyright (C) 2006 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: }}IS_RIGHT
016: */
017: package org.zkoss.zul;
018:
019: import org.zkoss.zul.event.ListDataEvent;
020: import org.zkoss.zk.ui.UiException;
021:
022: import java.util.List;
023: import java.util.Iterator;
024: import java.util.ArrayList;
025: import java.util.Comparator;
026: import java.util.Collection;
027: import java.util.Collections;
028: import java.util.ListIterator;
029:
030: /**
031: * <p>This is the {@link ListModel} as a {@link java.util.List} to be used with {@link Listbox}.
032: * Add or remove the contents of this model as a List would cause the associated Listbox to change accordingly.</p>
033: *
034: * @author Henri Chen
035: * @see ListModel
036: * @see ListModelList
037: * @see ListModelMap
038: */
039: public class ListModelList extends AbstractListModel implements
040: ListModelExt, List, java.io.Serializable {
041: protected List _list;
042:
043: /**
044: * Creates an instance which accepts a "live" List as its inner List.
045: * @param list the inner List storage
046: * @deprecated As of release 2.4.0, replaced by {@link #ListModelList(List,boolean)}
047: */
048: public static ListModelList instance(List list) {
049: return new ListModelList(list, true);
050: }
051:
052: /**
053: * Constructor
054: *
055: * @param list the list to represent
056: * @param live whether to have a 'live' {@link ListModel} on top of
057: * the specified list.
058: * If false, the content of the specified list is copied.
059: * If true, this object is a 'facade' of the specified list,
060: * i.e., when you add or remove items from this ListModelList,
061: * the inner "live" list would be changed accordingly.
062: *
063: * However, it is not a good idea to modify <code>list</code>
064: * if it is passed to this method with live is true,
065: * since {@link Listbox} is not smart enough to hanle it.
066: * Instead, modify it thru this object.
067: * @since 2.4.0
068: */
069: public ListModelList(List list, boolean live) {
070: _list = live ? list : new ArrayList(list);
071: }
072:
073: /**
074: * Constructor.
075: */
076: public ListModelList() {
077: _list = new ArrayList();
078: }
079:
080: /**
081: * Constructor.
082: * It mades a copy of the specified collection (i.e., not live).
083: */
084: public ListModelList(Collection c) {
085: _list = new ArrayList(c);
086: }
087:
088: /**
089: * Constructor.
090: * It mades a copy of the specified array (i.e., not live).
091: * @since 2.4.1
092: */
093: public ListModelList(Object[] array) {
094: _list = new ArrayList(array.length);
095: for (int j = 0; j < array.length; ++j)
096: _list.add(array[j]);
097: }
098:
099: /**
100: * Constructor.
101: * @param initialCapacity the initial capacity for this ListModelList.
102: */
103: public ListModelList(int initialCapacity) {
104: _list = new ArrayList(initialCapacity);
105: }
106:
107: /**
108: * Remove from fromIndex(inclusive) to toIndex(exclusive). If fromIndex equals toIndex,
109: * this methods do nothing.
110: * @param fromIndex the begin index (inclusive) to be removed.
111: * @param toIndex the end index (exclusive) to be removed.
112: */
113: public void removeRange(int fromIndex, int toIndex) {
114: if (fromIndex > toIndex) {
115: throw new UiException(
116: "fromIndex must less than toIndex: fromIndex: "
117: + fromIndex + ", toIndex: " + toIndex);
118: }
119: if (fromIndex == toIndex) {
120: return;
121: }
122: int sz = _list.size();
123: if (sz == fromIndex) {
124: return;
125: }
126: int index = fromIndex;
127: for (final Iterator it = _list.listIterator(fromIndex); it
128: .hasNext()
129: && index < toIndex; ++index) {
130: it.next();
131: it.remove();
132: }
133: fireEvent(ListDataEvent.INTERVAL_REMOVED, fromIndex, index - 1);
134: }
135:
136: /**
137: * Get the inner real List.
138: */
139: public List getInnerList() {
140: return _list;
141: }
142:
143: //-- ListModel --//
144: public int getSize() {
145: return _list.size();
146: }
147:
148: public Object getElementAt(int j) {
149: return _list.get(j);
150: }
151:
152: //-- List --//
153: public void add(int index, Object element) {
154: _list.add(index, element);
155: fireEvent(ListDataEvent.INTERVAL_ADDED, index, index);
156: }
157:
158: public boolean add(Object o) {
159: int i1 = _list.size();
160: boolean ret = _list.add(o);
161: fireEvent(ListDataEvent.INTERVAL_ADDED, i1, i1);
162: return ret;
163: }
164:
165: public boolean addAll(Collection c) {
166: int sz = c.size();
167: if (sz <= 0) {
168: return false;
169: }
170: int i1 = _list.size();
171: int i2 = i1 + sz - 1;
172: boolean ret = _list.addAll(c);
173: fireEvent(ListDataEvent.INTERVAL_ADDED, i1, i2);
174: return ret;
175: }
176:
177: public boolean addAll(int index, Collection c) {
178: int sz = c.size();
179: if (sz <= 0) {
180: return false;
181: }
182: int i2 = index + sz - 1;
183: boolean ret = _list.addAll(index, c);
184: fireEvent(ListDataEvent.INTERVAL_ADDED, index, i2);
185: return ret;
186: }
187:
188: public void clear() {
189: int i2 = _list.size() - 1;
190: if (i2 < 0) {
191: return;
192: }
193: _list.clear();
194: fireEvent(ListDataEvent.INTERVAL_REMOVED, 0, i2);
195: }
196:
197: public boolean contains(Object elem) {
198: boolean ret = _list.contains(elem);
199: return ret;
200: }
201:
202: public boolean containsAll(Collection c) {
203: return _list.containsAll(c);
204: }
205:
206: public boolean equals(Object o) {
207: return _list
208: .equals(o instanceof ListModelList ? ((ListModelList) o)._list
209: : o);
210: }
211:
212: public Object get(int index) {
213: return _list.get(index);
214: }
215:
216: public int hashCode() {
217: return _list.hashCode();
218: }
219:
220: public String toString() {
221: return _list.toString();
222: }
223:
224: public int indexOf(Object elem) {
225: return _list.indexOf(elem);
226: }
227:
228: public boolean isEmpty() {
229: return _list.isEmpty();
230: }
231:
232: public Iterator iterator() {
233: return _list.iterator();
234: }
235:
236: public int lastIndexOf(Object elem) {
237: return _list.lastIndexOf(elem);
238: }
239:
240: public ListIterator listIterator() {
241: return _list.listIterator();
242: }
243:
244: public ListIterator listIterator(int index) {
245: return _list.listIterator(index);
246: }
247:
248: public Object remove(int index) {
249: Object ret = _list.remove(index);
250: fireEvent(ListDataEvent.INTERVAL_REMOVED, index, index);
251: return ret;
252: }
253:
254: public boolean remove(Object o) {
255: int index = indexOf(o);
256: if (index >= 0) {
257: remove(index);
258: }
259: return false;
260: }
261:
262: public boolean removeAll(Collection c) {
263: if (_list == c || this == c) { //special case
264: clear();
265: return true;
266: }
267: return removePartial(c, true);
268: }
269:
270: public boolean retainAll(Collection c) {
271: if (_list == c || this == c) { //special case
272: return false;
273: }
274: return removePartial(c, false);
275: }
276:
277: private boolean removePartial(Collection c, boolean exclude) {
278: boolean removed = false;
279: int index = 0;
280: int begin = -1;
281: for (final Iterator it = _list.iterator(); it.hasNext(); ++index) {
282: Object item = it.next();
283: if (c.contains(item) == exclude) {
284: if (begin < 0) {
285: begin = index;
286: }
287: removed = true;
288: it.remove();
289: } else {
290: if (begin >= 0) {
291: fireEvent(ListDataEvent.INTERVAL_REMOVED, begin,
292: index - 1);
293: index = begin; //this range removed, the index is reset to begin
294: begin = -1;
295: }
296: }
297: }
298: if (begin >= 0) {
299: fireEvent(ListDataEvent.INTERVAL_REMOVED, begin, index - 1);
300: }
301:
302: return removed;
303: }
304:
305: public Object set(int index, Object element) {
306: Object ret = _list.set(index, element);
307: fireEvent(ListDataEvent.CONTENTS_CHANGED, index, index);
308: return ret;
309: }
310:
311: public int size() {
312: return _list.size();
313: }
314:
315: public List subList(int fromIndex, int toIndex) {
316: List list = _list.subList(fromIndex, toIndex);
317: return new ListModelList(list);
318: }
319:
320: public Object[] toArray() {
321: return _list.toArray();
322: }
323:
324: public Object[] toArray(Object[] a) {
325: return _list.toArray(a);
326: }
327:
328: //-- ListModelExt --//
329: /** Sorts the data.
330: *
331: * @param cmpr the comparator.
332: * @param ascending whether to sort in the ascending order.
333: * It is ignored since this implementation uses cmprt to compare.
334: */
335: public void sort(Comparator cmpr, final boolean ascending) {
336: Collections.sort(_list, cmpr);
337: fireEvent(ListDataEvent.CONTENTS_CHANGED, -1, -1);
338: }
339: }
|