Source code: org/scopemvc/model/collection/ListModelAdaptor.java
1 /*
2 * Scope: a generic MVC framework.
3 * Copyright (c) 2000-2002, Steve Meyfroidt
4 * All rights reserved.
5 * Email: smeyfroi@users.sourceforge.net
6 *
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * Neither the name "Scope" nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *
36 *
37 * $Id: ListModelAdaptor.java,v 1.4 2002/01/12 09:35:40 smeyfroi Exp $
38 */
39
40
41 package org.scopemvc.model.collection;
42
43
44 import java.util.ArrayList;
45 import java.util.Collections;
46 import java.util.Comparator;
47 import java.util.List;
48 import org.scopemvc.core.ModelChangeEvent;
49 import org.scopemvc.core.ModelChangeListener;
50 import org.scopemvc.core.ModelChangeTypes;
51 import org.scopemvc.core.Selector;
52 import org.scopemvc.model.basic.BasicModel;
53
54
55 /**
56 * <P>
57 * Used to present a list of {@link ListModelSource}s as
58 * an active BasicModel. Useful when
59 * initialising {@link org.scopemvc.view.swing.SComboBox}
60 * or {@link org.scopemvc.view.swing.SList} with a static
61 * list of data.
62 * </P>
63 * <P>
64 * This will propogate ModelChangeEvents from sublists that
65 * are ModelChangeEventSources. Note that this adaptor registers
66 * as a listener with such sublists: it may be necessary to
67 * manually unregister with {@link #removeModelChangeListeners}
68 * if an adaptor is no longer needed.
69 * </P>
70 * <P>
71 * The adaptor can present its ListModelSources as a sorted list
72 * if a Comparator is passed to {@link #setComparator}
73 * or all list elements implement Comparable and {@link #setSorted}
74 * is called.
75 * </P>
76 *
77 *@author Roytman, Alex
78 * @author <A HREF="mailto:smeyfroi@users.sourceforge.net">Steve Meyfroidt</A>
79 *@version $Revision: 1.4 $ $Date: 2002/01/12 09:35:40 $
80 */
81 public class ListModelAdaptor extends BasicModel
82 implements ModelChangeListener {
83
84
85 public final static Selector LIST_SELECTOR = Selector.fromString("list");
86 public final static Selector LIST_SIZE_SELECTOR = Selector.fromString("size");
87
88
89 private List list;
90 private ListModelSource listSources[];
91
92 private boolean sorted;
93 private Comparator comparator;
94
95
96 public ListModelAdaptor(ListModelSource listSources[]) {
97 this.listSources = listSources;
98 for (int i = 0; i < listSources.length; i++) {
99 if (listSources[i].isModelBased()) {
100 listSources[i].getListSourceModel().addModelChangeListener(this);
101 }
102 }
103 }
104
105
106 public ListModelAdaptor(ListModelSource listSource) {
107 this(new ListModelSource[]{listSource});
108 }
109
110
111 public void removeModelChangeListeners() {
112 if (listSources != null) {
113 for (int i = 0; i < listSources.length; i++) {
114 if (listSources[i].isModelBased()) {
115 listSources[i].getListSourceModel().removeModelChangeListener(this);
116 }
117 }
118 }
119 }
120
121
122 public void modelChanged(ModelChangeEvent inEvent) {
123 if (list != null && isListChangeEvent(inEvent)) {
124 loadList();
125 fireModelChange(ModelChangeTypes.VALUE_CHANGED, LIST_SELECTOR);
126 }
127 }
128
129
130 private boolean isListChangeEvent(ModelChangeEvent inEvent) {
131 for (int i = 0; i < listSources.length; i++) {
132 if (listSources[i].isModelBased() &&
133 inEvent.getModel().equals(listSources[i].getListSourceModel()) &&
134 (inEvent.getSelector() == null || inEvent.getSelector().equals(listSources[i].getListSourceSelector()))) {
135 return true;
136 }
137 }
138 return false;
139 }
140
141
142 public List getList() {
143 if (list == null) {
144 loadList();
145 }
146 return list;
147 }
148
149
150 public int getSize() {
151 if (list == null) {
152 loadList();
153 }
154 return list.size();
155 }
156
157
158 public Object getElementAt(int inIndex) {
159 if (list == null) {
160 loadList();
161 }
162 if (list == null) {
163 return null;
164 } else {
165 return list.get(inIndex);
166 }
167 }
168
169
170 public boolean isSorted() {
171 return sorted;
172 }
173
174
175 public void setSorted(boolean inSorted) {
176 sorted = true;
177 }
178
179
180 public void setComparator(Comparator inComparator) {
181 if (inComparator == null) {
182 setSorted(false);
183 comparator = null;
184 list = null;
185 } else {
186 setSorted(true);
187 comparator = inComparator;
188 list = null;
189 }
190 fireModelChange(ModelChangeTypes.VALUE_CHANGED, LIST_SELECTOR);
191 }
192
193
194 protected void loadList() {
195 if (listSources.length == 1 && listSources[0].isList() && ! isSorted()) {
196 list = (List)listSources[0].getListSource();
197 return;
198 }
199
200 if (list == null) {
201 list = new ArrayList();
202 } else {
203 list.clear();
204 }
205
206 for (int i = 0; i < listSources.length; i++) {
207 listSources[i].addToList(list);
208 }
209
210 if (isSorted() && comparator != null) {
211 Collections.sort(list, comparator);
212 } else if (isSorted()) {
213 Collections.sort(list);
214 }
215 }
216 }