1 /*********************************************************************************
2 * *
3 * Raptor - Rapid prototyping of Swing GUIs based on JavaBeans like Java objects *
4 * Copyright (C) 2003 XCOM AG *
5 * *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of the GNU Lesser General Public *
8 * License as published by the Free Software Foundation; either *
9 * version 2.1 of the License, or (at your option) any later version. *
10 * *
11 * This library is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14 * Lesser General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU Lesser General Public *
17 * License along with this library; if not, write to the Free Software *
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
19 * *
20 *********************************************************************************/
21 package net.sf.raptor.ui.panels;
22
23 import java.awt.BorderLayout;
24 import java.awt.Component;
25 import java.awt.Frame;
26 import java.awt.GridBagConstraints;
27 import java.awt.GridBagLayout;
28 import java.awt.Insets;
29 import java.beans.BeanDescriptor;
30 import java.beans.BeanInfo;
31 import java.beans.Introspector;
32 import java.beans.PropertyDescriptor;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.Map;
36
37 import javax.swing.JComponent;
38 import javax.swing.JLabel;
39 import javax.swing.JPanel;
40 import javax.swing.border.EmptyBorder;
41
42 import net.sf.raptor.logging.Trace;
43 import net.sf.raptor.ui.BeanInfoUtils;
44 import net.sf.raptor.ui.WindowUtils;
45 import net.sf.raptor.ui.actions.ActionUtils;
46 import net.sf.raptor.ui.components.ComponentMapper;
47 import net.sf.raptor.ui.components.ComponentWrapper;
48 import net.sf.raptor.ui.components.InvalidValueException;
49 import net.sf.raptor.ui.dialog.BeanEditDialog;
50
51
52 /**
53 * The <code>BeanEditPanel</code> is used to present objects adhering to the
54 * {@link <a href="http://java.sun.com/products/javabeans/" target="_top">JavaBeans</a>}
55 * specification.
56 * @ru.k2s.example sample use.
57 * BeanEditPanel panel = new BeanEditPanel( bean );
58 * panel.{@link #doModalInDialog()};
59 *
60 * @author Thomas Goertz <thomas DOT goertz AT xcom DOT de>
61 * @author Klaus Zimmermann <klaus DOT zimmermann AT xcom DOT de>
62 * @todo add testcase
63 */
64 public class BeanEditPanel extends XPanel {
65
66 /** enables multi-column presentation of objects with many visible properties */
67 public final static int MAX_ENTRIES_PER_COLUMN = 10;
68
69 /** holds the JavaBeans property descriptors describing the contained bean */
70 private PropertyDescriptor[] propertyDescriptors;
71 /** list of the used {@link ComponentWrapper ComponentWrappers} */
72 private Map componentWrapper = new HashMap();
73 /**
74 * The beanInfo that is used in the construction of the panel.
75 * It may provide additional information about the bean and its properties.
76 * @see <a href="http://java.sun.com/products/javabeans/" target="_top">JavaBeans Specs.</a>
77 */
78 private BeanInfo beanInfo;
79
80 /** holds the bean */
81 protected Object editObject;
82
83 /**
84 * constructor
85 *
86 * @param toEdit
87 */
88 public BeanEditPanel(Object toEdit) {
89 this(toEdit, null);
90 }
91
92 /**
93 * constructor
94 *
95 * @param toEdit
96 */
97 public BeanEditPanel(Object toEdit, BeanInfo beanInfoValue) {
98 editObject = toEdit;
99 beanInfo = beanInfoValue;
100 initComponents();
101 }
102
103 /**
104 * sets the bean to the state of the panel
105 *
106 * @throws InvalidValueException when any of the used {@link ComponentWrapper ComponentWrappers} is unable to convert the UI representation of the value to its bean equivalent.
107 */
108 public void commit() throws InvalidValueException {
109 InvalidValueException exception=null;
110 for (Iterator iter = componentWrapper.values().iterator(); iter.hasNext();) {
111 ComponentWrapper element = (ComponentWrapper) iter.next();
112 try {
113 element.commit();
114 } catch (InvalidValueException e) {
115 exception=e;
116 }
117 }
118 if(exception!=null) throw exception;
119 }
120
121 /**
122 * reinits the panel to the initial state of the editObject.
123 */
124 public void refresh() {
125 Trace.warn("Refresh reinits the panel to the initial state of the editObject.");
126 for (Iterator iter = componentWrapper.values().iterator(); iter.hasNext();) {
127 ComponentWrapper element = (ComponentWrapper) iter.next();
128 element.refresh();
129 }
130 }
131
132 public void refresh( String propertyName ) {
133 ComponentWrapper wrapper = (ComponentWrapper)componentWrapper.get(propertyName);
134 wrapper.refresh();
135 }
136
137
138
139
140 /**
141 * builds the panel.
142 */
143 protected void initComponents() {
144
145 setLayout(new BorderLayout());
146
147 JPanel contentPanel = new JPanel();
148
149 GridBagLayout layout = new GridBagLayout();
150 contentPanel.setLayout(layout);
151 contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
152 Insets defaultInsets = new Insets(5, 5, 5, 5);
153
154 if (editObject != null) {
155
156 /* descriptoren f?r die eigenschaften der klasse */
157 if (beanInfo == null) {
158 beanInfo = BeanInfoUtils.getBeanInfoFor(editObject);
159 }
160 propertyDescriptors = beanInfo.getPropertyDescriptors();
161
162 int columns = 1;
163 if( propertyDescriptors.length>20 ) {
164 columns = propertyDescriptors.length / 20 + 1;
165 }
166
167 int x = 0;
168 int y = 0;
169
170 /* spalten anhand der eigenschaften der klasse hinzuf?gen */
171 for (int i = 0; i < propertyDescriptors.length; i++) {
172 PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
173 String propertyName = propertyDescriptor.getName();
174 Class propertyType = propertyDescriptor.getPropertyType();
175
176 // wir blenden die properties aus, die ...
177 // ... im property type null zur?ckliefern oder
178 // ... der name "class" ist
179 //////////////////////////////////////////////////////////////
180 if (propertyType != null && !propertyName.equals("class")
181 && !propertyDescriptor.isHidden() && !propertyName.equals("beanInfo")) {
182
183 JComponent component1 = new JLabel(propertyDescriptor.getDisplayName() + ":");
184 Component component2 = null;
185 try {
186 ComponentWrapper wrapper = ComponentMapper.getWrapperFor(editObject, propertyName);
187 if (wrapper == null) {
188 Trace.warn("Missing wrapper for " + editObject.getClass().getName() + "." + propertyName);
189 component2 = ComponentMapper.getComponentFor(editObject, propertyName);
190 } else {
191 Trace.info("wrapper for " + editObject.getClass().getName() + "." + propertyName + " is " + wrapper.getClass().getName() );
192 wrapper.setToolTipText(propertyDescriptor.getShortDescription());
193 component2 = wrapper.getRepresentation();
194 componentWrapper.put(propertyName, wrapper);
195 }
196 } catch (Exception e) {
197 net.sf.raptor.ui.dialog.ExceptionDialog.showExceptionDialog(e);
198
199 }
200
201 component1.setToolTipText(propertyDescriptor.getShortDescription());
202 /** komponenten hinzuf?gen */
203 contentPanel.add(component1, new GridBagConstraints(x, y, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, defaultInsets, 0, 0));
204 contentPanel.add(component2, new GridBagConstraints(x + 1, y, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, defaultInsets, 0, 0));
205
206 /** neue poistionen, spalten etc. f?r n?chtes element vorbereiten */
207 x+=2;
208 if( x>columns) {
209 x=0; y++;
210 }
211
212 }
213
214 }
215
216 add(contentPanel, BorderLayout.CENTER);
217
218 add( ActionUtils.createButtonPanel(this), BorderLayout.EAST);
219
220 }
221
222 super.doLayout();
223
224 }
225
226 /**
227 * provides the bean actually edited.
228 *
229 * @return the bean
230 */
231 public Object getEditObject() {
232 return editObject;
233 }
234
235
236 /**
237 * wraps the panel in a {@link BeanEditDialog} and presents this dialog to the user.
238 * This happens modally, i.e. no other IO with the application can occur.
239 * @see net.sf.raptor.ui.panels.XPanel#doModalInDialog()
240 */
241 public Object doModalInDialog() {
242 BeanEditDialog dialog;
243 if( parentDialog!=null) {
244 dialog = new BeanEditDialog( parentDialog );
245 } else if (parentFrame!=null) {
246 dialog = new BeanEditDialog( parentFrame );
247 } else {
248 Frame defaultFrame = WindowUtils.getDefaultParentFrame();
249 dialog = defaultFrame==null ? new BeanEditDialog() : new BeanEditDialog(defaultFrame);
250 }
251 dialog.setBeanEditPanel(this);
252 String title="";
253 Object value = getEditObject();
254 try {
255 BeanDescriptor beanDescriptor = Introspector.getBeanInfo(value.getClass()).getBeanDescriptor();
256 String shortDescription = beanDescriptor.getShortDescription();
257 title = BeanInfoUtils.formatShortDescription(value, shortDescription);
258 } catch (Exception e) {
259 Trace.info("Could not figure out shortDescription: "+e.getLocalizedMessage());
260 }
261 dialog.setTitle(title);
262 return WindowUtils.wrapInDialog(this, dialog);
263 }
264
265 }