1 /*
2 * Scope: a generic MVC framework.
3 * Copyright (c) 2000-2002, The Scope team
4 * All rights reserved.
5 *
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * Neither the name "Scope" nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 *
36 * $Id: SLabel.java,v 1.9 2002/09/13 17:04:39 ludovicc Exp $
37 */
38 package org.scopemvc.view.swing;
39
40 import java.beans.Beans;
41 import javax.swing.*;
42
43 import org.apache.commons.logging.Log;
44 import org.apache.commons.logging.LogFactory;
45
46 import org.scopemvc.core.Control;
47 import org.scopemvc.core.Controller;
48 import org.scopemvc.core.PropertyView;
49 import org.scopemvc.core.Selector;
50 import org.scopemvc.util.Debug;
51 import org.scopemvc.util.convertor.StringConvertor;
52 import org.scopemvc.util.convertor.StringConvertors;
53 import org.scopemvc.view.util.ModelBindable;
54
55 /***
56 * <P>
57 *
58 * A JLabel linked to a property of a bound model object. The property must have
59 * a StringConvertor to handle conversion to and from a String representation
60 * that will be edited in the textfield. </P> <P>
61 *
62 * SLabel responds to the bound model or the particular bound property becoming
63 * read-only by disabling itself. An SLabel is also disabled if it has no bound
64 * model or property. </P>
65 *
66 * @author <A HREF="mailto:smeyfroi@users.sourceforge.net">Steve Meyfroidt</A>
67 * @author <A HREF="mailto:ludovicc@users.sourceforge.net">Ludovic Claude</A>
68 * @created June 12, 2002
69 * @version $Revision: 1.9 $ $Date: 2002/09/13 17:04:39 $
70 */
71 public class SLabel extends JLabel implements PropertyView, ModelBindable, Refreshable {
72
73 private static final Log LOG = LogFactory.getLog(SLabel.class);
74
75 /***
76 * Helper to manage model to view binding.
77 */
78 private SwingBoundModel boundModel = new SwingBoundModel(this);
79
80 /***
81 * The StringConvertor used to convert the model property to the String
82 * representation that the user see in the label.
83 */
84 private StringConvertor stringConvertor;
85
86 /***
87 * If this is set, use it instead of finding a convertor to match the
88 * datatype being edited.
89 */
90 private StringConvertor forcedStringConvertor;
91
92
93 /***
94 * Creates a <code>SLabel</code> instance with the specified text, image,
95 * and horizontal alignment. The label is centered vertically in its display
96 * area. The text is on the trailing edge of the image.
97 *
98 * @param text The text to be displayed by the label.
99 * @param icon The image to be displayed by the label.
100 * @param horizontalAlignment One of the following constants defined in
101 * <code>SwingConstants</code>: <code>LEFT</code>, <code>CENTER</code>,
102 * <code>RIGHT</code>, <code>LEADING</code> or <code>TRAILING</code>.
103 */
104 public SLabel(String text, Icon icon, int horizontalAlignment) {
105 super(text, icon, horizontalAlignment);
106 setEnabled(Beans.isDesignTime());
107 }
108
109 /***
110 * Creates a <code>SLabel</code> instance with the specified text and
111 * horizontal alignment. The label is centered vertically in its display
112 * area.
113 *
114 * @param text The text to be displayed by the label.
115 * @param horizontalAlignment One of the following constants defined in
116 * <code>SwingConstants</code>: <code>LEFT</code>, <code>CENTER</code>,
117 * <code>RIGHT</code>, <code>LEADING</code> or <code>TRAILING</code>.
118 */
119 public SLabel(String text, int horizontalAlignment) {
120 this(text, null, horizontalAlignment);
121 }
122
123 /***
124 * Creates a <code>SLabel</code> instance with the specified text. The label
125 * is aligned against the leading edge of its display area, and centered
126 * vertically.
127 *
128 * @param text The text to be displayed by the label.
129 */
130 public SLabel(String text) {
131 this(text, null, LEADING);
132 }
133
134 /***
135 * Creates a <code>SLabel</code> instance with the specified image and
136 * horizontal alignment. The label is centered vertically in its display
137 * area.
138 *
139 * @param horizontalAlignment One of the following constants defined in
140 * <code>SwingConstants</code>: <code>LEFT</code>, <code>CENTER</code>,
141 * <code>RIGHT</code>, <code>LEADING</code> or <code>TRAILING</code>.
142 * @param image Description of the Parameter
143 */
144 public SLabel(Icon image, int horizontalAlignment) {
145 this(null, image, horizontalAlignment);
146 }
147
148 /***
149 * Creates a <code>SLabel</code> instance with the specified image. The
150 * label is centered vertically and horizontally in its display area.
151 *
152 * @param image Description of the Parameter
153 */
154 public SLabel(Icon image) {
155 this(null, image, CENTER);
156 }
157
158 /***
159 * Creates a <code>SLabel</code> instance with no image and with an empty
160 * string for the title. The label is centered vertically in its display
161 * area. The label's contents, once set, will be displayed on the leading
162 * edge of the label's display area.
163 */
164 public SLabel() {
165 this("", null, LEADING);
166 }
167
168
169 // ------------------- Delegate to BoundModel -------------------
170
171 /***
172 * Gets the bound model
173 *
174 * @return The boundModel value
175 */
176 public final Object getBoundModel() {
177 return boundModel.getBoundModel();
178 }
179
180
181 /***
182 * Gets the selector
183 *
184 * @return The selector value
185 */
186 public final Selector getSelector() {
187 return boundModel.getSelector();
188 }
189
190
191 /***
192 * Don't assign a Controller to STextField, instead delegate to the
193 * containing SwingView that has a parent Controller.
194 *
195 * @return The controller value
196 */
197 public Controller getController() {
198 return null;
199 }
200
201
202 /***
203 * SLabel don't issue any control
204 *
205 * @param inControl Description of the Parameter
206 */
207 public void issueControl(Control inControl) {
208 throw new UnsupportedOperationException("Can't issue a control from a SLabel");
209 }
210
211 /***
212 * Get the current value (what would be set as a property of the bound model
213 * object) being presented on the View.
214 *
215 * @return property value from parsing the textfield's current String
216 * representation.
217 * @exception IllegalArgumentException if the conversion from String fails.
218 */
219 public Object getViewValue() throws IllegalArgumentException {
220 String text = getText();
221
222 if (stringConvertor == null) {
223 return null;
224 }
225
226 return stringConvertor.stringAsValue(text);
227 }
228
229
230 /***
231 * Sets the bound model
232 *
233 * @param inModel The new boundModel value
234 */
235 public final void setBoundModel(Object inModel) {
236 boundModel.setBoundModel(inModel);
237 setupStringConvertor();
238 }
239
240
241 /***
242 * Sets the selector
243 *
244 * @param inSelector The new selector value
245 */
246 public final void setSelector(Selector inSelector) {
247 boundModel.setSelector(inSelector);
248 setupStringConvertor();
249 }
250
251
252 /***
253 * Sets the selector string
254 *
255 * @param inSelectorString The new selectorString value
256 */
257 public final void setSelectorString(String inSelectorString) {
258 boundModel.setSelectorString(inSelectorString);
259 setupStringConvertor();
260 }
261
262 /***
263 * Don't assign a Controller to this component, instead delegate to the
264 * containing SwingView that has a parent Controller.
265 *
266 * @param inController The new controller value
267 */
268 public void setController(Controller inController) {
269 throw new UnsupportedOperationException("Can't assign a Controller to a " + getClass());
270 }
271
272 /***
273 * Force use of this StringConvertor instead of automatically finding one to
274 * match the datatype being edited.
275 *
276 * @param inConvertor The new stringConvertor value
277 */
278 public void setStringConvertor(StringConvertor inConvertor) {
279 forcedStringConvertor = inConvertor;
280 }
281
282
283 /***
284 * Override to call super.setText() only if new value not equals() old
285 * value.
286 *
287 * @param t new text.
288 */
289 public void setText(String t) {
290 if (Debug.ON) {
291 Debug.assertTrue(getText() != null, "null getText()");
292 }
293 if (!getText().equals(t)) {
294 super.setText(t);
295 }
296 }
297
298 // --------------------- Implement ModelBindable ----------------------
299
300 /***
301 * Converts the incoming value to a String via appropriate {@link
302 * org.scopemvc.util.convertor.StringConvertor}. For incoming null either
303 * disable field or set text to empty String.
304 *
305 * @param inValue Description of the Parameter
306 * @param inReadOnly Description of the Parameter
307 */
308 public void updateFromProperty(Object inValue, boolean inReadOnly) {
309 if (LOG.isDebugEnabled()) {
310 LOG.debug("updateFromProperty: " + inValue + ", " + inReadOnly);
311 }
312
313 // ***** Hack. Need to revisit PropertyManager to traverse nulls and use metadata etc
314 setupStringConvertor();
315
316 if (stringConvertor == null) {
317 setEnabled(false);
318 setText("");
319 } else if (inValue == null) {
320 setEnabled(true);
321 setText("");
322 } else {
323
324 setEnabled(!inReadOnly);
325 try {
326 String text = stringConvertor.valueAsString(inValue);
327 setText(text);
328 } catch (IllegalArgumentException e) {
329 // should never happen normally -- comes from getValue() but the
330 // ... property value must always be convertible to String?
331 LOG.error("updateFromProperty", e);
332 setEnabled(false);
333 }
334 }
335 revalidate();
336 }
337
338 /***
339 * Makes no sense.
340 *
341 * @param inException TODO: Describe the Parameter
342 */
343 public void validationFailed(Exception inException) {
344 // noop
345 }
346
347
348 /***
349 * Makes no sense.
350 */
351 public void validationSuccess() {
352 // noop
353 }
354
355
356 // ------------------ Refreshable -------------------------
357
358 /***
359 * Description of the Method
360 */
361 public void refresh() {
362 Object propertyValue = boundModel.getPropertyValue();
363 boolean propertyReadOnly = boundModel.getPropertyReadOnly();
364 updateFromProperty(propertyValue, propertyReadOnly);
365 }
366
367
368 /***
369 * Description of the Method
370 */
371 protected void setupStringConvertor() {
372 if (forcedStringConvertor != null) {
373 stringConvertor = forcedStringConvertor;
374 return;
375 }
376
377 try {
378 Object m = getBoundModel();
379 Selector s = getSelector();
380 if (m != null) {
381 Class clazz = boundModel.getPropertyManager().getPropertyClass(m, s);
382 stringConvertor = StringConvertors.forClass(clazz);
383 }
384 } catch (Exception e) {
385 stringConvertor = null;
386 }
387 }
388
389 }
390
This page was automatically generated by Maven