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