1 /* 2 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.beans; 27 28 import java.beans.*; 29 30 /** 31 * This is a support class to help build property editors. 32 * <p> 33 * It can be used either as a base class or as a delegate. 34 * 35 * @since 1.1 36 */ 37 38 public class PropertyEditorSupport implements PropertyEditor { 39 40 /** 41 * Constructs a <code>PropertyEditorSupport</code> object. 42 * 43 * @since 1.5 44 */ 45 public PropertyEditorSupport() { 46 setSource(this); 47 } 48 49 /** 50 * Constructs a <code>PropertyEditorSupport</code> object. 51 * 52 * @param source the source used for event firing 53 * @since 1.5 54 */ 55 public PropertyEditorSupport(Object source) { 56 if (source == null) { 57 throw new NullPointerException(); 58 } 59 setSource(source); 60 } 61 62 /** 63 * Returns the bean that is used as the 64 * source of events. If the source has not 65 * been explicitly set then this instance of 66 * <code>PropertyEditorSupport</code> is returned. 67 * 68 * @return the source object or this instance 69 * @since 1.5 70 */ 71 public Object getSource() { 72 return source; 73 } 74 75 /** 76 * Sets the source bean. 77 * <p> 78 * The source bean is used as the source of events 79 * for the property changes. This source should be used for information 80 * purposes only and should not be modified by the PropertyEditor. 81 * 82 * @param source source object to be used for events 83 * @since 1.5 84 */ 85 public void setSource(Object source) { 86 this.source = source; 87 } 88 89 /** 90 * Set (or change) the object that is to be edited. 91 * 92 * @param value The new target object to be edited. Note that this 93 * object should not be modified by the PropertyEditor, rather 94 * the PropertyEditor should create a new object to hold any 95 * modified value. 96 */ 97 public void setValue(Object value) { 98 this.value = value; 99 firePropertyChange(); 100 } 101 102 /** 103 * Gets the value of the property. 104 * 105 * @return The value of the property. 106 */ 107 public Object getValue() { 108 return value; 109 } 110 111 //---------------------------------------------------------------------- 112 113 /** 114 * Determines whether the class will honor the paintValue method. 115 * 116 * @return True if the class will honor the paintValue method. 117 */ 118 119 public boolean isPaintable() { 120 return false; 121 } 122 123 /** 124 * Paint a representation of the value into a given area of screen 125 * real estate. Note that the propertyEditor is responsible for doing 126 * its own clipping so that it fits into the given rectangle. 127 * <p> 128 * If the PropertyEditor doesn't honor paint requests (see isPaintable) 129 * this method should be a silent noop. 130 * 131 * @param gfx Graphics object to paint into. 132 * @param box Rectangle within graphics object into which we should paint. 133 */ 134 public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) { 135 } 136 137 //---------------------------------------------------------------------- 138 139 /** 140 * This method is intended for use when generating Java code to set 141 * the value of the property. It should return a fragment of Java code 142 * that can be used to initialize a variable with the current property 143 * value. 144 * <p> 145 * Example results are "2", "new Color(127,127,34)", "Color.orange", etc. 146 * 147 * @return A fragment of Java code representing an initializer for the 148 * current value. 149 */ 150 public String getJavaInitializationString() { 151 return "???"; 152 } 153 154 //---------------------------------------------------------------------- 155 156 /** 157 * Gets the property value as a string suitable for presentation 158 * to a human to edit. 159 * 160 * @return The property value as a string suitable for presentation 161 * to a human to edit. 162 * <p> Returns null if the value can't be expressed as a string. 163 * <p> If a non-null value is returned, then the PropertyEditor should 164 * be prepared to parse that string back in setAsText(). 165 */ 166 public String getAsText() { 167 return (this.value != null) 168 ? this.value.toString() 169 : null; 170 } 171 172 /** 173 * Sets the property value by parsing a given String. May raise 174 * java.lang.IllegalArgumentException if either the String is 175 * badly formatted or if this kind of property can't be expressed 176 * as text. 177 * 178 * @param text The string to be parsed. 179 */ 180 public void setAsText(String text) throws java.lang.IllegalArgumentException { 181 if (value instanceof String) { 182 setValue(text); 183 return; 184 } 185 throw new java.lang.IllegalArgumentException(text); 186 } 187 188 //---------------------------------------------------------------------- 189 190 /** 191 * If the property value must be one of a set of known tagged values, 192 * then this method should return an array of the tag values. This can 193 * be used to represent (for example) enum values. If a PropertyEditor 194 * supports tags, then it should support the use of setAsText with 195 * a tag value as a way of setting the value. 196 * 197 * @return The tag values for this property. May be null if this 198 * property cannot be represented as a tagged value. 199 * 200 */ 201 public String[] getTags() { 202 return null; 203 } 204 205 //---------------------------------------------------------------------- 206 207 /** 208 * A PropertyEditor may chose to make available a full custom Component 209 * that edits its property value. It is the responsibility of the 210 * PropertyEditor to hook itself up to its editor Component itself and 211 * to report property value changes by firing a PropertyChange event. 212 * <P> 213 * The higher-level code that calls getCustomEditor may either embed 214 * the Component in some larger property sheet, or it may put it in 215 * its own individual dialog, or ... 216 * 217 * @return A java.awt.Component that will allow a human to directly 218 * edit the current property value. May be null if this is 219 * not supported. 220 */ 221 222 public java.awt.Component getCustomEditor() { 223 return null; 224 } 225 226 /** 227 * Determines whether the propertyEditor can provide a custom editor. 228 * 229 * @return True if the propertyEditor can provide a custom editor. 230 */ 231 public boolean supportsCustomEditor() { 232 return false; 233 } 234 235 //---------------------------------------------------------------------- 236 237 /** 238 * Adds a listener for the value change. 239 * When the property editor changes its value 240 * it should fire a {@link PropertyChangeEvent} 241 * on all registered {@link PropertyChangeListener}s, 242 * specifying the {@code null} value for the property name. 243 * If the source property is set, 244 * it should be used as the source of the event. 245 * <p> 246 * The same listener object may be added more than once, 247 * and will be called as many times as it is added. 248 * If {@code listener} is {@code null}, 249 * no exception is thrown and no action is taken. 250 * 251 * @param listener the {@link PropertyChangeListener} to add 252 */ 253 public synchronized void addPropertyChangeListener( 254 PropertyChangeListener listener) { 255 if (listeners == null) { 256 listeners = new java.util.Vector<>(); 257 } 258 listeners.addElement(listener); 259 } 260 261 /** 262 * Removes a listener for the value change. 263 * <p> 264 * If the same listener was added more than once, 265 * it will be notified one less time after being removed. 266 * If {@code listener} is {@code null}, or was never added, 267 * no exception is thrown and no action is taken. 268 * 269 * @param listener the {@link PropertyChangeListener} to remove 270 */ 271 public synchronized void removePropertyChangeListener( 272 PropertyChangeListener listener) { 273 if (listeners == null) { 274 return; 275 } 276 listeners.removeElement(listener); 277 } 278 279 /** 280 * Report that we have been modified to any interested listeners. 281 */ 282 public void firePropertyChange() { 283 java.util.Vector<PropertyChangeListener> targets; 284 synchronized (this) { 285 if (listeners == null) { 286 return; 287 } 288 targets = unsafeClone(listeners); 289 } 290 // Tell our listeners that "everything" has changed. 291 PropertyChangeEvent evt = new PropertyChangeEvent(source, null, null, null); 292 293 for (int i = 0; i < targets.size(); i++) { 294 PropertyChangeListener target = targets.elementAt(i); 295 target.propertyChange(evt); 296 } 297 } 298 299 @SuppressWarnings("unchecked") 300 private <T> java.util.Vector<T> unsafeClone(java.util.Vector<T> v) { 301 return (java.util.Vector<T>)v.clone(); 302 } 303 304 //---------------------------------------------------------------------- 305 306 private Object value; 307 private Object source; 308 private java.util.Vector<PropertyChangeListener> listeners; 309 }