79d59a749997e10096ba1a969acc9ac92a38afb0
[sw/motorsim] / gui / com / billkuker / rocketry / motorsim / visual / Editor.java
1 package com.billkuker.rocketry.motorsim.visual;\r
2 \r
3 import java.awt.Component;\r
4 import java.awt.Dimension;\r
5 import java.beans.IntrospectionException;\r
6 import java.beans.Introspector;\r
7 import java.beans.PropertyChangeEvent;\r
8 import java.beans.PropertyChangeListener;\r
9 import java.beans.PropertyDescriptor;\r
10 import java.beans.PropertyEditorManager;\r
11 import java.beans.PropertyEditorSupport;\r
12 import java.text.DecimalFormat;\r
13 import java.text.NumberFormat;\r
14 import java.util.EnumSet;\r
15 import java.util.Vector;\r
16 \r
17 import javax.measure.unit.SI;\r
18 import javax.measure.unit.Unit;\r
19 import javax.swing.DefaultComboBoxModel;\r
20 import javax.swing.JComboBox;\r
21 import javax.swing.JFrame;\r
22 import javax.swing.JLabel;\r
23 import javax.swing.JTable;\r
24 import javax.swing.JTextField;\r
25 import javax.swing.WindowConstants;\r
26 import javax.swing.table.TableCellRenderer;\r
27 \r
28 import org.apache.log4j.Logger;\r
29 import org.jscience.physics.amount.Amount;\r
30 \r
31 import com.billkuker.rocketry.motorsim.CylindricalChamber;\r
32 import com.billkuker.rocketry.motorsim.RocketScience;\r
33 import com.billkuker.rocketry.motorsim.cases.PVCCase;\r
34 import com.l2fprod.common.propertysheet.PropertySheetPanel;\r
35 import com.sun.org.apache.xml.internal.security.utils.EncryptionElementProxy;\r
36 \r
37 public class Editor extends PropertySheetPanel {\r
38         private static final long serialVersionUID = 1L;\r
39         private static final NumberFormat nf = new DecimalFormat("##########.###");\r
40         private static final Logger log = Logger.getLogger(Editor.class);\r
41 \r
42         private Object obj;\r
43 \r
44         @SuppressWarnings("deprecation")\r
45         public Editor(Object o) {\r
46                 obj = o;\r
47 \r
48                 PropertyEditorManager.registerEditor(Amount.class,\r
49                                 AmountPropertyEditor.class);\r
50                 \r
51                 setToolBarVisible(false);\r
52                 //setMinimumSize(new Dimension(150,200));\r
53                 \r
54                 getRendererRegistry().registerRenderer(Amount.class, AmountRenderer.class);\r
55 \r
56                 // Build the list of properties we want it to edit\r
57                 //final PropertySheetPanel ps = new PropertySheetPanel();\r
58                 PropertyDescriptor props[];\r
59                 try {\r
60                         props = Introspector.getBeanInfo(obj.getClass())\r
61                                         .getPropertyDescriptors();\r
62                 } catch (IntrospectionException e) {\r
63                         throw new Error(e);\r
64                 }\r
65                 Vector<PropertyDescriptor> v = new Vector<PropertyDescriptor>();\r
66                 for (int i = 0; i < props.length; i++) {\r
67                         if (props[i].getName().equals("class"))\r
68                                 continue;\r
69                         v.add(props[i]);\r
70                         \r
71                         if ( Enum.class.isAssignableFrom( props[i].getPropertyType() ) ){\r
72                                 getEditorRegistry().registerEditor(props[i].getPropertyType(), new EnumPropertyEditor(props[i].getPropertyType()));\r
73                         }\r
74                         \r
75                 }\r
76                 setProperties(v.toArray(new PropertyDescriptor[v.size()]));\r
77 \r
78                 readFromObject(obj);\r
79                 \r
80                 getTable().setRowHeight(22);\r
81                 \r
82                 setMinimumSize(new Dimension(\r
83                                 getTable().getPreferredSize().width,\r
84                                 getTable().getPreferredSize().height + 10));\r
85 \r
86                 addPropertySheetChangeListener(new PropertyChangeListener() {\r
87 \r
88                         public void propertyChange(PropertyChangeEvent evt) {\r
89                                 // When something changes just update the\r
90                                 // object, I want the changes to be immediate.\r
91                                 try {\r
92                                         log.debug("Writing properties to object.");\r
93                                         writeToObject(obj);\r
94                                 } catch (Exception v) {\r
95                                         // TODO\r
96                                         v.printStackTrace();\r
97                                         java.awt.Toolkit.getDefaultToolkit().beep();\r
98                                 } finally {\r
99                                         readFromObject(obj);\r
100                                 }\r
101                         }\r
102 \r
103                 });\r
104         }\r
105 \r
106         public void showAsWindow() {\r
107                 JFrame f = new JFrame();\r
108                 f.setTitle(obj.getClass().getName());\r
109                 f.setSize(600, 400);\r
110                 f.setContentPane(this);\r
111                 f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);\r
112                 f.setVisible(true);\r
113         }\r
114         \r
115         public static void main(String args[]){\r
116                 PVCCase o = new PVCCase();\r
117                 o.setLength(Amount.valueOf(100, SI.MILLIMETER));\r
118                 Editor e = new Editor(o);\r
119                 e.showAsWindow();\r
120         }\r
121         \r
122         public static class AmountRenderer implements TableCellRenderer {\r
123                 @Override\r
124                 public Component getTableCellRendererComponent(JTable table,\r
125                                 Object value, boolean isSelected, boolean hasFocus, int row,\r
126                                 int column) {\r
127                         return new JLabel(RocketScience.ammountToString((Amount<?>)value));\r
128                 }\r
129                 \r
130         }\r
131         \r
132         public static class EnumPropertyEditor<E extends Enum<E>> extends PropertyEditorSupport {\r
133                 JComboBox editor = new JComboBox();\r
134                 DefaultComboBoxModel model = new DefaultComboBoxModel();\r
135                 Class<E> clazz;\r
136                 public EnumPropertyEditor(Class<E> clazz){\r
137                         this.clazz = clazz;\r
138                         for ( E e : EnumSet.allOf(clazz) ){\r
139                                 model.addElement(e);\r
140                         }\r
141                         editor.setModel(model);\r
142                 }\r
143                 \r
144                 @Override\r
145                 public Object getValue() {\r
146                         return editor.getSelectedItem();\r
147                 }\r
148                 \r
149                 @Override\r
150                 public boolean supportsCustomEditor() {\r
151                         return true;\r
152                 }\r
153                 \r
154                 @Override\r
155                 public Component getCustomEditor() {\r
156                         return editor;\r
157                 }\r
158         }\r
159 \r
160         public static class AmountPropertyEditor extends PropertyEditorSupport {\r
161                 JTextField editor = new JTextField();\r
162                 Unit<?> oldUnit;\r
163 \r
164                 @Override\r
165                 public boolean supportsCustomEditor() {\r
166                         return true;\r
167                 }\r
168 \r
169                 @Override\r
170                 public String getAsText() {\r
171                         return editor.getText();\r
172                 }\r
173 \r
174                 @Override\r
175                 public Object getValue() {\r
176                         String text = editor.getText().trim();\r
177 \r
178                         // Trying to determine if the value is integer or\r
179                         // has a decimal part will prevent the uncertainty\r
180                         // term from appearing when user types an exact value\r
181                         try {\r
182                                 try {\r
183                                         return Amount.valueOf(Integer.parseInt(text), oldUnit);\r
184                                 } catch (NumberFormatException e) {\r
185 \r
186                                 }\r
187                                 Amount<?> a = Amount.valueOf(Double.parseDouble(text), oldUnit);\r
188                                 return a;\r
189                         } catch (NumberFormatException e) {\r
190                                 // Storing the old unit allows you to type 10 into a field\r
191                                 // that says 20 mm and get 10 mm, so you dont have to\r
192                                 // type the unit if they havn't changed.\r
193                                 \r
194                                 //Amount wants a leading 0\r
195                                 if (text.startsWith(".")){\r
196                                         text = "0" + text;\r
197                                 }\r
198                                 \r
199                                 Amount<?> a = Amount.valueOf(text);\r
200                                 oldUnit = a.getUnit();\r
201                                 return a;\r
202                         }\r
203 \r
204                 }\r
205 \r
206                 @SuppressWarnings("unchecked")\r
207                 @Override\r
208                 public void setValue(Object o) {\r
209                         Amount a = (Amount) o;\r
210                         oldUnit = a.getUnit();\r
211 \r
212                         String text;\r
213                         //Leave off the fractional part if it is not relevant\r
214                         if (a.isExact())\r
215                                 text = a.getExactValue() + " " + a.getUnit();\r
216                         else\r
217                                 text = nf.format(a.doubleValue(a.getUnit())) + " " + a.getUnit();\r
218 \r
219                         setAsText(text);\r
220                 }\r
221 \r
222                 @Override\r
223                 public void setAsText(String text) throws IllegalArgumentException {\r
224                         editor.setText(text);\r
225                 };\r
226 \r
227                 @Override\r
228                 public Component getCustomEditor() {\r
229                         return editor;\r
230                 }\r
231         }\r
232 \r
233 }\r