Source of PropertySheet.java


  1: import java.awt.*;
  2: import java.awt.event.*;
  3: import java.beans.*;
  4: import java.lang.reflect.*;
  5: import java.util.*;
  6: import javax.swing.*;
  7: import javax.swing.event.*;


 10: /**
 11:    A component filled with editors for all editable properties 
 12:    of an object.
 13: */
 14: public class PropertySheet extends JPanel
 15: {
 16:    /**
 17:       Constructs a property sheet that shows the editable
 18:       properties of a given object.
 19:       @param object the object whose properties are being edited
 20:    */
 21:    public PropertySheet(Object bean)
 22:    {
 23:       try
 24:       {
 25:          BeanInfo info 
 26:             = Introspector.getBeanInfo(bean.getClass());
 27:          PropertyDescriptor[] descriptors 
 28:             = (PropertyDescriptor[])info.getPropertyDescriptors().clone();      
 29:          setLayout(new FormLayout());
 30:          for (int i = 0; i < descriptors.length; i++)
 31:          {
 32:             PropertyEditor editor 
 33:                = getEditor(bean, descriptors[i]);
 34:             if (editor != null)
 35:             {
 36:                add(new JLabel(descriptors[i].getName()));
 37:                add(getEditorComponent(editor));
 38:             }
 39:          }
 40:       }
 41:       catch (IntrospectionException exception)
 42:       {
 43:          exception.printStackTrace();
 44:       }
 45:    }

 47:    /**
 48:       Gets the property editor for a given property,
 49:       and wires it so that it updates the given object.
 50:       @param bean the object whose properties are being edited
 51:       @param descriptor the descriptor of the property to
 52:       be edited
 53:       @return a property editor that edits the property
 54:       with the given descriptor and updates the given object
 55:    */
 56:    public PropertyEditor getEditor(final Object bean,
 57:       PropertyDescriptor descriptor)
 58:    {
 59:       try
 60:       {
 61:          Method getter = descriptor.getReadMethod();
 62:          if (getter == null) return null;
 63:          final Method setter = descriptor.getWriteMethod();
 64:          if (setter == null) return null;
 65:          Class type = descriptor.getPropertyType();
 66:          PropertyEditor ed = null;
 67:          Class editorClass = descriptor.getPropertyEditorClass();
 68:          if (editorClass != null)            
 69:             ed = (PropertyEditor) editorClass.newInstance();
 70:          else
 71:             ed = PropertyEditorManager.findEditor(type);
 72:          if (ed == null && Enum.class.isAssignableFrom(type))
 73:             ed = new EnumEditor(type);
 74:          if (ed == null) return null;

 76:          final PropertyEditor editor = ed;

 78:          Object value = getter.invoke(bean, new Object[] {});
 79:          editor.setValue(value);
 80:          editor.addPropertyChangeListener(new
 81:             PropertyChangeListener()
 82:             {
 83:                public void propertyChange(PropertyChangeEvent event)
 84:                {
 85:                   try
 86:                   {
 87:                      setter.invoke(bean, 
 88:                         new Object[] { editor.getValue() });
 89:                      fireStateChanged(null);
 90:                   }
 91:                   catch (IllegalAccessException exception)
 92:                   {
 93:                      exception.printStackTrace();
 94:                   }
 95:                   catch (InvocationTargetException exception)
 96:                   {
 97:                      exception.printStackTrace();
 98:                   }
 99:                }
100:             });
101:          return editor;
102:       }
103:       catch (InstantiationException exception)
104:       {
105:          exception.printStackTrace();
106:          return null;
107:       }
108:       catch (IllegalAccessException exception)
109:       {
110:          exception.printStackTrace();
111:          return null;
112:       }
113:       catch (InvocationTargetException exception)
114:       {
115:          exception.printStackTrace();
116:          return null;
117:       }
118:    }

120:    /**
121:       Wraps a property editor into a component.
122:       @param editor the editor to wrap
123:       @return a button (if there is a custom editor), 
124:       combo box (if the editor has tags), or text field (otherwise)
125:    */      
126:    public Component getEditorComponent(final PropertyEditor editor)   
127:    {      
128:       String[] tags = editor.getTags();
129:       String text = editor.getAsText();
130:       if (editor.supportsCustomEditor())
131:          return editor.getCustomEditor();         
132:       else if (tags != null)
133:       {
134:          // make a combo box that shows all tags
135:          final JComboBox comboBox = new JComboBox(tags);
136:          comboBox.setSelectedItem(text);
137:          comboBox.addItemListener(new
138:             ItemListener()
139:             {
140:                public void itemStateChanged(ItemEvent event)
141:                {
142:                   if (event.getStateChange() == ItemEvent.SELECTED)
143:                      editor.setAsText(
144:                         (String)comboBox.getSelectedItem());
145:                }
146:             });
147:          return comboBox;
148:       }
149:       else 
150:       {
151:          final JTextField textField = new JTextField(text, 10);
152:          textField.getDocument().addDocumentListener(new
153:             DocumentListener()
154:             {
155:                public void insertUpdate(DocumentEvent e) 
156:                {
157:                   try
158:                   {
159:                      editor.setAsText(textField.getText());
160:                   }
161:                   catch (IllegalArgumentException exception)
162:                   {
163:                   }
164:                }
165:                public void removeUpdate(DocumentEvent e) 
166:                {
167:                   try
168:                   {
169:                      editor.setAsText(textField.getText());
170:                   }
171:                   catch (IllegalArgumentException exception)
172:                   {
173:                   }
174:                }
175:                public void changedUpdate(DocumentEvent e) 
176:                {
177:                }
178:             });
179:          return textField;
180:       }
181:    }

183:    /**
184:       Adds a change listener to the list of listeners.
185:       @param listener the listener to add
186:    */
187:    public void addChangeListener(ChangeListener listener)
188:    {
189:       changeListeners.add(listener);
190:    }

192:    /**
193:       Notifies all listeners of a state change.
194:       @param event the event to propagate
195:    */
196:    private void fireStateChanged(ChangeEvent event)
197:    {
198:       for (ChangeListener listener : changeListeners)
199:          listener.stateChanged(event);
200:    }
201:    
202:    private ArrayList<ChangeListener> changeListeners 
203:          = new ArrayList<ChangeListener>();
204: }