1 /***
2 * Copyright (C) 2006 Philipp Mpalampanis
3 *
4 * License: MPL 1.1/GPL 2.0/LGPL 2.1
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * Alternatively, the contents of this file may be used under the terms of
17 * either the GNU General Public License Version 2 or later (the "GPL"), or
18 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
19 * in which case the provisions of the GPL or the LGPL are applicable instead
20 * of those above. If you wish to allow use of your version of this file only
21 * under the terms of either the GPL or the LGPL, and not to allow others to
22 * use your version of this file under the terms of the MPL, indicate your
23 * decision by deleting the provisions above and replace them with the notice
24 * and other provisions required by the GPL or the LGPL. If you do not delete
25 * the provisions above, a recipient may use your version of this file under
26 * the terms of any one of the MPL, the GPL or the LGPL.
27 */
28
29 package net.sf.echobinding.controls;
30
31 import java.beans.PropertyChangeEvent;
32 import java.beans.PropertyChangeListener;
33 import java.util.ArrayList;
34 import java.util.Collection;
35
36 import net.sf.echobinding.BoundControl;
37 import net.sf.echobinding.binding.BindingContext;
38 import net.sf.echobinding.decorator.Decorator;
39 import net.sf.echobinding.validation.*;
40 import nextapp.echo2.app.event.*;
41 import nextapp.echo2.app.list.ListModel;
42
43 /***
44 *
45 */
46 public class SelectField extends nextapp.echo2.app.SelectField implements
47 BoundControl, ActionListener, PropertyChangeListener {
48
49 private static final long serialVersionUID = -3593733868533261539L;
50
51 private BindingContext _ctx;
52
53 private String _id;
54
55 private String _itemsAdapterId;
56
57 private ArrayList<Object> _listItems;
58
59 private Collection<Object> _items;
60
61 private ValidationHandler _validationHandler;
62
63 /***
64 * creates a data bound select field
65 *
66 * @param adapterId
67 * @param context
68 */
69 public SelectField(String adapterId, Object[] items, BindingContext context) {
70 super(items);
71 _id = adapterId;
72 setBindingConext(context);
73 setActionCommand( adapterId );
74 }
75
76 /***
77 * Creates a data bound select field
78 *
79 * @param bindingId
80 * @param context
81 */
82 public SelectField(String bindingId, ListModel model, BindingContext context) {
83 super(model);
84 _id = bindingId;
85 _ctx = context;
86 }
87
88 /***
89 * creates a data bound select field
90 *
91 * @param adapterId
92 * @param itemsAdapterId
93 * @param context
94 */
95 public SelectField(String adapterId, String itemsAdapterId,
96 BindingContext context) {
97 super();
98 _id = adapterId;
99 _itemsAdapterId = itemsAdapterId;
100 setActionCommand( adapterId );
101 addActionListener(this);
102 addPropertyChangeListener(this);
103
104 context.addPropertyChangeListener(SELECTION_CHANGED_PROPERTY, this);
105
106 setBindingConext(context);
107 }
108
109
110
111
112 public void setBindingConext(BindingContext context) {
113 if(context == null) return;
114 if( _ctx != null) _ctx.removeControl(this);
115 context.registerControl( _id, this);
116 _ctx = context;
117 update();
118 }
119
120
121
122
123
124
125
126 public void setAdapterId(String adapterId) {
127 _id = adapterId;
128 }
129
130
131
132
133
134
135 @SuppressWarnings("unchecked")
136 public void update() {
137 assert(_ctx != null);
138
139
140 Object value = _ctx.getValue(_id);
141
142
143 _items = (Collection<Object>) _ctx
144 .getValue(_itemsAdapterId);
145
146 if (_items == null) {
147
148 _items = new ArrayList<Object>();
149 }
150
151
152 _listItems = new ArrayList<Object>();
153 _listItems.add("");
154 _listItems.addAll(_items);
155
156
157
158 Object selectedItem = null;
159 for (Object item : _listItems) {
160 if (item.equals(value))
161 selectedItem = item;
162 }
163 if (selectedItem != null) {
164 int index = _listItems.indexOf(selectedItem);
165 if( getSelectedIndex() != index )
166 setSelectedIndex( index );
167 }
168
169 final Decorator decorator = _ctx.getDecorator(_itemsAdapterId);
170
171 ListModel model = new ListModel() {
172
173 private static final long serialVersionUID = -6693815714661801487L;
174
175 public void removeListDataListener(ListDataListener arg0) {
176 }
177
178 public int size() {
179 return _listItems.size();
180 }
181
182 public Object get(int i) {
183 return decorator.decorate(_listItems.get(i));
184 }
185
186 public void addListDataListener(ListDataListener arg0) {
187 }
188
189 };
190
191 setModel(model);
192 }
193
194
195
196
197
198
199 public void save() {
200
201 if(getSelectedIndex() == -1)
202 _ctx.setValue(_id, null);
203 else
204 _ctx.setValue(_id, _listItems.get(getSelectedIndex()));
205 }
206
207
208
209
210
211
212 public boolean isValid() {
213
214 return createValidationReport().isValid();
215 }
216
217
218
219
220
221
222 public void propertyChange(PropertyChangeEvent event) {
223 if (SELECTION_CHANGED_PROPERTY.equals(event.getPropertyName())) {
224 Object value = _ctx.getValue( _itemsAdapterId );
225 if( value != null && ! value.equals( _items ) ) {
226 update();
227 }
228 }
229 }
230
231
232
233
234
235
236 public void actionPerformed(ActionEvent event) {
237 fireSelectionChange();
238 }
239
240 /***
241 *
242 */
243 private void fireSelectionChange() {
244
245 int selectedIndex = getSelectedIndex();
246 int minListIndex = 1;
247 if (selectedIndex >= minListIndex) {
248 PropertyChangeEvent selectionChangeEvent = new PropertyChangeEvent(
249 this, SELECTION_CHANGED_PROPERTY, null, _listItems
250 .get(selectedIndex));
251 _ctx.propertyChange(selectionChangeEvent);
252 }
253 }
254
255 @Override
256 public String toString() {
257 return super.toString()+"#"+_id;
258 }
259
260 @Override
261 public void setSelectedIndex(int index) {
262 super.setSelectedIndex(index);
263
264 fireSelectionChange();
265 }
266
267
268
269
270
271
272
273 public void validateInput() {
274
275 ValidationReport validationReport = createValidationReport();
276
277 setToolTipText(validationReport.getMessage());
278
279 invokeValidationHandler(validationReport);
280
281 }
282
283 /***
284 * @return
285 */
286 private ValidationReport createValidationReport() {
287 ValidationReport validationReport;
288 Object value = getSelectedIndex() == -1 ? null : _listItems.get(getSelectedIndex());
289 validationReport = _ctx.validate(_id, value);
290 return validationReport;
291 }
292
293 /***
294 * @param validationReport
295 */
296 private void invokeValidationHandler(ValidationReport validationReport) {
297 initValidationHandler();
298
299 if(validationReport.isValid())
300 _validationHandler.markValid(this);
301 else
302 _validationHandler.markInvalid(this);
303 }
304
305 /***
306 * Initializes the validation handler
307 *
308 */
309 private void initValidationHandler() {
310 if( _validationHandler == null ) {
311 _validationHandler = _ctx.getValidationHandler(_id);
312 if( _validationHandler == null )
313 _validationHandler = new DefaultValidationHandler(this);
314 }
315 }
316
317
318
319
320 public boolean isDirty() {
321 if(getSelectedIndex() == -1)
322 return _ctx.isDirty(_id, null);
323 else
324 return _ctx.isDirty(_id, _listItems.get(getSelectedIndex()));
325 }
326
327
328
329
330 public Object getValue() {
331 if(getSelectedIndex() < 0)
332 return null;
333 return _listItems.get(getSelectedIndex());
334 }
335
336
337
338
339 public void setValue(Object value) {
340 if( value==null ) {
341 setSelectedIndex( 0 );
342 return;
343 }
344 setSelectedIndex( _listItems.indexOf( value ) );
345 }
346 }