001: /*
002: * Copyright (c) 2004 JETA Software, Inc. All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without modification,
005: * are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JETA Software nor the names of its contributors may
015: * be used to endorse or promote products derived from this software without
016: * specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
021: * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
022: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
023: * INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
024: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
025: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026: * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: */
029:
030: package com.jeta.forms.gui.beans;
031:
032: import java.lang.reflect.Method;
033:
034: import com.jeta.forms.gui.common.FormException;
035: import com.jeta.forms.gui.common.FormUtils;
036: import com.jeta.forms.store.properties.JETAProperty;
037:
038: /**
039: * A <code>DynamicPropertyDescriptor</code> is similar to a standard Java
040: * Beans PropertyDescriptor. However, these descriptors can be dynamically added
041: * and removed. For example, some Swing components such as JTables and JLists
042: * are almost always contained within a JScrollPane. So, instead of working with
043: * a JScrollPane, we add a scrollable property to the Swing components instead.
044: * This scrollable property is an example of a dynamic property since it is not
045: * defined by the Java Bean. Dynamic properties are defined by a
046: * <code>DynamicPropertyDescriptor</code> and are assigned to a bean using
047: * <code>BeanFactory</code> instances.
048: *
049: * @author Jeff Tassin
050: */
051: public class DynamicPropertyDescriptor implements
052: JETAPropertyDescriptor {
053: /** The name of the property associated with this descriptor */
054: private String m_name;
055:
056: /** The type of the property value associated with this descriptor */
057: private Class m_type;
058:
059: /**
060: * Flag that indicates if the property associated with this descriptor is
061: * preferred or not.
062: */
063: private boolean m_preferred;
064:
065: /**
066: * Flag that indicates if this property associated with this descriptor can
067: * be stored. Set to true if the property should not be stored.
068: */
069: private boolean m_transient = false;
070:
071: /**
072: * Creates a <code>DynamicPropertyDescriptor</code> instance with the
073: * specified name, type and preferred/transient flags.
074: *
075: * @param name
076: * the programmatic name for the property
077: * @param type
078: * the type for the property
079: * @param pref
080: * set to true if the property is a preferred property.
081: * @param istransient
082: * set to true if the property value is NOT persistent.
083: */
084: public DynamicPropertyDescriptor(String name, Class type,
085: boolean pref, boolean istransient) {
086: m_name = name;
087: m_type = type;
088: m_preferred = pref;
089: m_transient = istransient;
090: }
091:
092: /** @return the value for this property */
093: public Object getPropertyValue(JETABean bean) throws FormException {
094: return bean.getCustomProperty(getName());
095: }
096:
097: /** @return the name of the property associated with this descriptor */
098: public String getName() {
099: return m_name;
100: }
101:
102: /**
103: * Return the display name for the property.
104: */
105: public String getDisplayName() {
106: return getName();
107: }
108:
109: /**
110: * Gets the short description for the property.
111: */
112: public String getShortDescription() {
113: return getName();
114: }
115:
116: /**
117: * Gets a PropertyEditor class that has been registered for the property.
118: * Null is returned if no property editor class has been registered. Not
119: * currently used for any dynamic properties.
120: */
121: public Class getPropertyEditorClass() {
122: return null;
123: }
124:
125: /** @return the type of the property value associated with this descriptor */
126: public Class getPropertyType() {
127: return m_type;
128: }
129:
130: /**
131: * Dynamic properties do not use write methods. Instead, they must implement
132: * updateBean() method of JETAProperty. Always returns null.
133: */
134: public Method getWriteMethod() {
135: return null;
136: }
137:
138: /**
139: * The "preferred" flag is used to identify features that are particularly
140: * important for presenting to humans
141: */
142: public boolean isPreferred() {
143: return m_preferred;
144: }
145:
146: /**
147: * The "hidden" flag is used to identify features that are intended only for
148: * tool use, and which should not be exposed to humans.
149: */
150: public boolean isHidden() {
151: return false;
152: }
153:
154: /**
155: * Returns true if the underlying property should not be stored.
156: */
157: public boolean isTransient() {
158: return m_transient;
159: }
160:
161: /**
162: * Returns true if the property is writable. Dynamic properties are always
163: * writable (currently).
164: */
165: public boolean isWritable() {
166: return true;
167: }
168:
169: /**
170: * Sets the value for the property associated with this descriptor. This is
171: * potentially a two step process. First, the property value itself is
172: * updated. This may or may not have an effect on the bean - it depends on
173: * the type of property. Second, we tell the property to update the bean.
174: * Some properties require a two step process because of the nature of the
175: * property. For example, a scrollable property has a value that defines
176: * when scroll bars should be displayed. Additionally, we need to tell the
177: * scroll property to update the bean after its value has been set. This
178: * action instantiates the JScrollPane instance and substitutes it for the
179: * actual java bean on the form.
180: *
181: * @param bean
182: * the JETABean object whose property we are setting.
183: * @param value
184: * the value of the property to set.
185: */
186: public void setPropertyValue(JETABean bean, Object value)
187: throws FormException {
188: JETAProperty old_prop = bean.getCustomProperty(getName());
189: FormUtils.safeAssert(old_prop != null);
190: if (old_prop != null) {
191: if (value instanceof JETAProperty
192: && value.getClass() == old_prop.getClass()) {
193: JETAProperty prop = (JETAProperty) value;
194: if (!getName().equals(prop.getName())) {
195: /** This should never happen */
196: System.out
197: .println("DynamicPropertyDescriptor.setPropertyValue getName(): "
198: + getName()
199: + " prop.getName(): "
200: + prop.getName());
201: FormUtils.safeAssert(false);
202: }
203:
204: try {
205: if (FormUtils.isDesignMode()) {
206: /**
207: * We make a copy of the property mainly to support
208: * undo/redo when setting properties in the designer.
209: */
210: prop = (JETAProperty) value.getClass()
211: .newInstance();
212: prop.setValue(value);
213: bean.setCustomProperty(getName(), prop);
214: prop.updateBean(bean);
215: return;
216: }
217: } catch (Exception e) {
218: e.printStackTrace();
219: }
220: }
221:
222: old_prop.setValue(value);
223: old_prop.updateBean(bean);
224: }
225: }
226:
227: /**
228: * Sets this property to preferred.
229: */
230: public void setPreferred(boolean bpref) {
231: m_preferred = bpref;
232: }
233:
234: }
|