1 /*
2 Copyright 2002-2006 Martin van den Bemt
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16 package org.xulux.guilayer.swing.models;
17
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.StringTokenizer;
21
22 import javax.swing.AbstractListModel;
23 import javax.swing.ComboBoxModel;
24
25 import org.xulux.api.dataprovider.IField;
26 import org.xulux.api.dataprovider.IMapping;
27 import org.xulux.core.XuluxContext;
28 import org.xulux.guilayer.swing.widgets.Combo;
29
30 /**
31 * The default combobox model.
32 *
33 * @author <a href="mailto:martin@mvdb.net">Martin van den Bemt</a>
34 * @version $Id: DefaultComboModel.java,v 1.1 2005/12/18 12:58:21 mvdb Exp $
35 */
36 public class DefaultComboModel extends AbstractListModel implements ComboBoxModel {
37 /**
38 * The original list
39 */
40 private List original;
41 /**
42 * the used list
43 */
44 private ArrayList list;
45 /**
46 * The selected item
47 */
48 private ComboShowable selectedItem;
49 /**
50 * the field to use
51 */
52 private String field;
53 /**
54 * the Mapping
55 */
56 private IMapping mapping;
57 /**
58 * the combo where this model is used for
59 */
60 private Combo combo;
61 /**
62 * If the model has been initialized
63 */
64 private boolean initialized;
65
66 /**
67 * don't do anything, since we don't have any data..
68 * It will create an empty list however
69 */
70 public DefaultComboModel() {
71 this.list = new ArrayList();
72 }
73
74 /**
75 * Constructor for DefaultComboModel.
76 *
77 * @param list the list with data
78 * @param field the field to use
79 * @param combo the combo used
80 */
81 public DefaultComboModel(List list, String field, Combo combo) {
82 this.field = field;
83 this.original = list;
84 this.combo = combo;
85 initialize();
86 }
87
88 /**
89 * When using the arrow keys to select another
90 * item from the combo, we have to fire an event
91 * with the index0 and the index1 with the value -1.
92 * This way you can actually see the selectedItem change
93 * on screen. If you don't fire this event, the selectedItem
94 * (onscreen!) will stay on the selected item on creation
95 * of the combo.
96 *
97 * @see javax.swing.ComboBoxModel#setSelectedItem(Object)
98 */
99 public void setSelectedItem(Object anItem) {
100 if (anItem instanceof ComboShowable) {
101 this.selectedItem = (ComboShowable) anItem;
102 if (initialized && !combo.isRefreshing()) {// && combo.getProvider() == null) {
103 combo.setLazyValue(getRealSelectedValue());
104 }
105 } else {
106 setRealSelectedValue(anItem);
107 }
108 fireContentsChanged(this, -1, -1);
109 }
110
111 /**
112 * Set the selected item to the specified index
113 * @param index the index to select
114 */
115 public void setSelectedItem(int index) {
116 if (list.size() > 0) {
117 if (!(index >= list.size())) {
118 this.selectedItem = (ComboShowable) list.get(index);
119 }
120 }
121 }
122
123 /**
124 * @see javax.swing.ComboBoxModel#getSelectedItem()
125 */
126 public Object getSelectedItem() {
127 return selectedItem;
128 }
129
130 /**
131 * @see javax.swing.ListModel#getSize()
132 */
133 public int getSize() {
134 if (list == null) {
135 return 0;
136 }
137 return list.size();
138 }
139
140 /**
141 * The comboshowable which is requested by the JCombo
142 * object.
143 *
144 * @see javax.swing.ListModel#getElementAt(int)
145 */
146 public Object getElementAt(int index) {
147 return list.get(index);
148 }
149
150 /**
151 * @return the real selected value in the combo, so not a comboshowable
152 */
153 public Object getRealSelectedValue() {
154 Object retValue = null;
155 if (original != null && selectedItem != null) {
156 retValue = original.get(selectedItem.getIndex());
157 } else if (original != null && original.size() > 0) {
158 retValue = original.get(0);
159 }
160 return retValue;
161 }
162
163 /**
164 * @return the selected index in the model
165 * If the selection is null, it will return -1
166 */
167 public int getSelectedIndex() {
168 if (selectedItem == null) {
169 return -1;
170 } else {
171 return selectedItem.getIndex();
172 }
173 }
174
175 /**
176 * Set the real selected item (so not the comboshowable.
177 *
178 * @param selectedItem the real selected item
179 */
180 public void setRealSelectedValue(Object selectedItem) {
181 if (original == null) {
182 return;
183 }
184 int index = -1;
185 try {
186 index = original.indexOf(selectedItem);
187 } catch(Exception e) {
188 // ignore exceptions thrown in an equals method.
189 e.printStackTrace();
190 }
191 if (index != -1) {
192 setSelectedItem(list.get(index));
193 } else if (combo.getProvider() != null) {
194 combo.setValue(getRealSelectedValue());
195 } else {
196 setSelectedItem(0);
197 if (combo.getProvider() == null) {
198 combo.setLazyValue(getRealSelectedValue());
199 }
200 }
201 }
202
203 /**
204 * Initialize the model and the data
205 */
206 protected void initialize() {
207 if (field != null && original.size() > 0) {
208 int startMappingAt = 0;
209 if (original.get(0).equals(combo.getNotSelectedValue())) {
210 startMappingAt = 1;
211 }
212 if ((startMappingAt == 1 && original.size() > 1) || startMappingAt == 0) {
213 Class tmpClazz = original.get(startMappingAt).getClass();
214 mapping = XuluxContext.getDictionary().getDefaultProvider().getMapping(tmpClazz);
215 }
216 }
217 list = new ArrayList();
218 for (int i = 0; i < original.size(); i++) {
219 Object object = original.get(i);
220 if (object != null && (i == 0 && combo.getNotSelectedValue() != null && object.equals(combo.getNotSelectedValue())) || this.field == null) {
221 list.add(new ComboShowable(i, object.toString()));
222 } else {
223 String value = "";
224 StringTokenizer stn = new StringTokenizer(field, ",");
225 while (stn.hasMoreTokens()) {
226 String token = stn.nextToken();
227 String strPart = "";
228 IField iField = mapping.getField(token);
229 if (iField != null) {
230 strPart = iField.getValue(object).toString();
231 } else {
232 //allow seperators in the field list.
233 strPart = token;
234 }
235 value += strPart;
236 }
237 list.add(new ComboShowable(i, value));
238 }
239 }
240 initialized = true;
241 }
242
243 /**
244 * Clean up combomodel (if at all needed)
245 */
246 public void destroy() {
247 this.combo = null;
248 this.list = null;
249 this.mapping = null;
250 this.original = null;
251 this.field = null;
252 this.selectedItem = null;
253 }
254
255 /**
256 * @return the original data
257 */
258 protected List getOriginal() {
259 return this.original;
260 }
261
262 /**
263 * @return the data in the combo
264 */
265 protected List getList() {
266 return this.list;
267 }
268 /**
269 * Holds all items in a list
270 */
271 public class ComboShowable {
272 /**
273 * the index
274 */
275 private int index;
276 /**
277 * the value
278 */
279 private String value;
280
281 /**
282 * The main constructor
283 * @param index the index in the original data
284 * @param value the value that needs to be shown
285 */
286 public ComboShowable(int index, String value) {
287 this.index = index;
288 this.value = value;
289 }
290
291 /**
292 * Since a combo is using the toString value of an object,
293 * this will return the value set in the constructor
294 *
295 * @see java.lang.Object#toString()
296 */
297 public String toString() {
298 return this.value;
299 }
300
301 /**
302 * @return the index in the original data
303 */
304 public int getIndex() {
305 return index;
306 }
307 }
308 }