View Javadoc
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: STextArea.java,v 1.13 2002/09/13 17:04:42 ludovicc Exp $ 37 */ 38 package org.scopemvc.view.swing; 39 40 41 import java.awt.event.FocusEvent; 42 import java.awt.event.FocusListener; 43 import java.beans.Beans; 44 import javax.swing.JTextArea; 45 import javax.swing.JToolTip; 46 import org.apache.commons.logging.Log; 47 import org.apache.commons.logging.LogFactory; 48 import org.scopemvc.core.Control; 49 import org.scopemvc.core.Controller; 50 import org.scopemvc.core.PropertyView; 51 import org.scopemvc.core.Selector; 52 import org.scopemvc.util.Debug; 53 import org.scopemvc.util.convertor.StringConvertor; 54 import org.scopemvc.util.convertor.StringConvertors; 55 import org.scopemvc.view.util.ModelBindable; 56 57 /*** 58 * <P> 59 * 60 * A JTextArea linked to a property of a bound model object. The property must 61 * have a StringConvertor to handle conversion to and from a String 62 * representation that will be edited in the textarea. Updates to the textarea 63 * result in changes to the model property when focus is lost. </P> <P> 64 * 65 * STextArea responds to the bound model object or the particular bound property 66 * becoming read-only by disabling itself. An STextArea is also disabled if it 67 * has no bound model or property. </P> <P> 68 * 69 * Null properties are handled in one of two ways: 70 * <OL> 71 * <LI> The textarea is disabled to prevent editing. </LI> 72 * <LI> The textarea is populated with an empty String. In this case, the 73 * bound property will contain an empty String not a null, if the textarea is 74 * populated with an empty string. </LI> 75 * </OL> 76 * The second option is the default but that can be changed by calling {@link 77 * #setDisableOnNull}. </P> 78 * 79 * @author <A HREF="mailto:smeyfroi@users.sourceforge.net">Steve Meyfroidt</A> 80 * @created 05 September 2002 81 * @version $Revision: 1.13 $ $Date: 2002/09/13 17:04:42 $ 82 * @see SwingView 83 */ 84 public class STextArea extends JTextArea implements PropertyView, FocusListener, ModelBindable, Refreshable { 85 86 private static final Log LOG = LogFactory.getLog(STextArea.class); 87 88 /*** 89 * Helper to manage model to view binding. 90 */ 91 private SwingBoundModel boundModel = new SwingBoundModel(this); 92 93 /*** 94 * Helper to manage validation state. 95 */ 96 private ValidationHelper validationHelper = new ValidationHelper(this); 97 98 /*** 99 * STextArea can "hold" a null when bound to a property that happens to be 100 * null. 101 */ 102 private boolean valueIsNull = false; 103 104 /*** 105 * Does this textarea disable itself if the model property it is bound to 106 * becomes null? 107 */ 108 private boolean disableOnNull = false; 109 110 /*** 111 * The StringConvertor used to convert the model property to and from the 112 * String representation that the user edits in the textarea. 113 */ 114 private StringConvertor stringConvertor; 115 116 117 /*** 118 * Constructor for the STextArea object 119 */ 120 public STextArea() { 121 this(0, 0); 122 } 123 124 125 /*** 126 * Constructor for the STextArea object 127 * 128 * @param rows TODO: Describe the Parameter 129 * @param columns TODO: Describe the Parameter 130 */ 131 public STextArea(int rows, int columns) { 132 super(rows, columns); 133 setEnabled(Beans.isDesignTime()); 134 addFocusListener(this); 135 } 136 137 138 /*** 139 * @return true if the textarea should be disabled when it edits a null 140 * property value. Otherwise, a null property is treated as an empty 141 * String. 142 */ 143 public final boolean isDisableOnNull() { 144 return disableOnNull; 145 } 146 147 148 // ------------------- Delegate to BoundModel ------------------- 149 150 /*** 151 * Gets the bound model 152 * 153 * @return The boundModel value 154 */ 155 public final Object getBoundModel() { 156 return boundModel.getBoundModel(); 157 } 158 159 160 /*** 161 * Gets the selector 162 * 163 * @return The selector value 164 */ 165 public final Selector getSelector() { 166 return boundModel.getSelector(); 167 } 168 169 170 /*** 171 * Get the current value (what would be set as a property of the bound model 172 * object) being presented on the View. 173 * 174 * @return property value from parsing the textarea's current String 175 * representation. 176 * @exception IllegalArgumentException if the conversion from String fails. 177 */ 178 public Object getViewValue() throws IllegalArgumentException { 179 String text = getText(); 180 181 if (stringConvertor == null 182 || valueIsNull 183 || (isDisableOnNull() && text.length() < 1)) { 184 return null; 185 } 186 187 return stringConvertor.stringAsValue(text); 188 } 189 190 191 /*** 192 * Don't assign a Controller to STextArea. 193 * 194 * @return The controller value 195 */ 196 public Controller getController() { 197 return null; 198 } 199 200 201 /*** 202 * STextArea can't issue Controls. 203 * 204 * @param inControl TODO: Describe the Parameter 205 */ 206 public void issueControl(Control inControl) { 207 throw new UnsupportedOperationException("STextArea can't issue Controls."); 208 } 209 210 211 /*** 212 * Set this to true if the textarea should be disabled when it edits a null 213 * String. Otherwise, a null property is treated as an empty String. 214 * 215 * @param inDisable The new disableOnNull value 216 */ 217 public final void setDisableOnNull(boolean inDisable) { 218 disableOnNull = inDisable; 219 } 220 221 222 /*** 223 * Sets the bound model 224 * 225 * @param inModel The new boundModel value 226 */ 227 public final void setBoundModel(Object inModel) { 228 boundModel.setBoundModel(inModel); 229 setupStringConvertor(); 230 } 231 232 233 /*** 234 * Sets the selector 235 * 236 * @param inSelector The new selector value 237 */ 238 public final void setSelector(Selector inSelector) { 239 boundModel.setSelector(inSelector); 240 setupStringConvertor(); 241 } 242 243 244 /*** 245 * Sets the selector string 246 * 247 * @param inSelectorString The new selectorString value 248 */ 249 public final void setSelectorString(String inSelectorString) { 250 boundModel.setSelectorString(inSelectorString); 251 setupStringConvertor(); 252 } 253 254 255 /*** 256 * Override to call super.setText() only if new value not equals() old 257 * value. 258 * 259 * @param t new text. 260 */ 261 public void setText(String t) { 262 if (Debug.ON) { 263 Debug.assertTrue(getText() != null, "null getText()"); 264 } 265 if (!getText().equals(t)) { 266 super.setText(t); 267 } 268 } 269 270 271 // ------------------------ Implement View ----------------------- 272 273 /*** 274 * Don't assign a Controller to this component, instead delegate to the 275 * containing SwingView that has a parent Controller. 276 * 277 * @param inController The new controller value 278 */ 279 public void setController(Controller inController) { 280 throw new UnsupportedOperationException("Can't assign a Controller to a " + getClass()); 281 } 282 283 // --------------------- Implement ModelBindable ---------------------- 284 285 /*** 286 * Converts the incoming value to a String via appropriate {@link 287 * org.scopemvc.util.convertor.StringConvertor}. For incoming null either 288 * disable field or set text to empty String. 289 * 290 * @param inValue TODO: Describe the Parameter 291 * @param inReadOnly TODO: Describe the Parameter 292 */ 293 public void updateFromProperty(Object inValue, boolean inReadOnly) { 294 if (LOG.isDebugEnabled()) { 295 LOG.debug("updateFromProperty: " + inValue + ", " + inReadOnly); 296 } 297 298 // ***** Hack. Need to revisit PropertyManager to traverse nulls and use metadata etc 299 setupStringConvertor(); 300 301 if (stringConvertor == null) { 302 valueIsNull = true; 303 // ? 304 setEnabled(false); 305 // setText(""); 306 return; 307 } 308 309 if (inValue == null && isDisableOnNull()) { 310 valueIsNull = true; 311 setEnabled(false); 312 // setText(""); 313 return; 314 } 315 316 valueIsNull = false; 317 //(inValue == null); 318 setEnabled(!inReadOnly); 319 try { 320 if (LOG.isDebugEnabled()) { 321 LOG.debug("updateFromProperty: inValue: " + inValue); 322 } 323 String text = stringConvertor.valueAsString(inValue); 324 if (LOG.isDebugEnabled()) { 325 LOG.debug("updateFromProperty: text: " + text); 326 } 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 336 337 /*** 338 * TODO: document the method 339 * 340 * @param inException TODO: Describe the Parameter 341 */ 342 public void validationFailed(Exception inException) { 343 validationHelper.validationFailed(inException); 344 } 345 346 347 /*** 348 * TODO: document the method 349 */ 350 public void validationSuccess() { 351 validationHelper.validationSuccess(); 352 } 353 354 355 /*** 356 * TODO: document the method 357 * 358 * @return TODO: Describe the Return Value 359 */ 360 public JToolTip createToolTip() { 361 return validationHelper.createToolTip(super.createToolTip()); 362 } 363 364 365 // ---------------------- View to model ---------------------- 366 367 /*** 368 * TODO: document the method 369 * 370 * @param inEvent TODO: Describe the Parameter 371 */ 372 public void focusLost(FocusEvent inEvent) { 373 if (LOG.isDebugEnabled()) { 374 LOG.debug("focusLost"); 375 } 376 377 // if (! inEvent.isTemporary()) { 378 boundModel.updateModel(); 379 // } 380 } 381 382 383 /*** 384 * TODO: document the method 385 * 386 * @param inEvent TODO: Describe the Parameter 387 */ 388 public void focusGained(FocusEvent inEvent) { } 389 390 391 // ------------------ Refreshable ------------------------- 392 393 /*** 394 * TODO: document the method 395 */ 396 public void refresh() { 397 Object propertyValue = boundModel.getPropertyValue(); 398 boolean propertyReadOnly = boundModel.getPropertyReadOnly(); 399 updateFromProperty(propertyValue, propertyReadOnly); 400 } 401 402 403 /*** 404 * TODO: document the method 405 */ 406 protected void setupStringConvertor() { 407 try { 408 Object m = getBoundModel(); 409 Selector s = getSelector(); 410 if (m != null) { 411 Class clazz = boundModel.getPropertyManager().getPropertyClass(m, s); 412 stringConvertor = StringConvertors.forClass(clazz); 413 } 414 } catch (Exception e) { 415 stringConvertor = null; 416 } 417 } 418 } 419

This page was automatically generated by Maven