cleared some minor TODOs
[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                                         log.error(v);\r
94                                         java.awt.Toolkit.getDefaultToolkit().beep();\r
95                                 } finally {\r
96                                         readFromObject(obj);\r
97                                 }\r
98                         }\r
99 \r
100                 });\r
101         }\r
102 \r
103         public void showAsWindow() {\r
104                 JFrame f = new JFrame();\r
105                 f.setTitle(obj.getClass().getName());\r
106                 f.setSize(600, 400);\r
107                 f.setContentPane(this);\r
108                 f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);\r
109                 f.setVisible(true);\r
110         }\r
111 /*      \r
112         public static void main(String args[]){\r
113                 Schedule40 o = new Schedule40();\r
114                 o.setLength(Amount.valueOf(100, SI.MILLIMETER));\r
115                 Editor e = new Editor(o);\r
116                 e.showAsWindow();\r
117         }\r
118         */\r
119         public static class AmountRenderer implements TableCellRenderer {\r
120                 @Override\r
121                 public Component getTableCellRendererComponent(JTable table,\r
122                                 Object value, boolean isSelected, boolean hasFocus, int row,\r
123                                 int column) {\r
124                         return new JLabel(RocketScience.ammountToString((Amount<?>)value));\r
125                 }\r
126                 \r
127         }\r
128         \r
129         public class EnumPropertyEditor<E extends Enum<E>> extends PropertyEditorSupport {\r
130                 JComboBox editor = new JComboBox(){\r
131                         private static final long serialVersionUID = 1L;\r
132                         {\r
133                                 addActionListener(new ActionListener(){\r
134                                         @Override\r
135                                         public void actionPerformed(ActionEvent e) {\r
136                                                 getTable().commitEditing();\r
137                                         }});\r
138                         }\r
139                 };\r
140                 DefaultComboBoxModel model = new DefaultComboBoxModel();\r
141                 Class<E> clazz;\r
142                 public EnumPropertyEditor(Class<E> clazz){\r
143                         this.clazz = clazz;\r
144                         for ( E e : EnumSet.allOf(clazz) ){\r
145                                 model.addElement(e);\r
146                         }\r
147                         editor.setModel(model);\r
148                 }\r
149                 \r
150                 @Override\r
151                 public Object getValue() {\r
152                         return editor.getSelectedItem();\r
153                 }\r
154                 \r
155                 @Override\r
156                 public boolean supportsCustomEditor() {\r
157                         return true;\r
158                 }\r
159                 \r
160                 @Override\r
161                 public Component getCustomEditor() {\r
162                         return editor;\r
163                 }\r
164         }\r
165 \r
166         public static class AmountPropertyEditor extends PropertyEditorSupport {\r
167                 JTextField editor = new JTextField();\r
168                 Unit<?> oldUnit;\r
169 \r
170                 @Override\r
171                 public boolean supportsCustomEditor() {\r
172                         return true;\r
173                 }\r
174 \r
175                 @Override\r
176                 public String getAsText() {\r
177                         return editor.getText();\r
178                 }\r
179 \r
180                 @Override\r
181                 public Object getValue() {\r
182                         String text = editor.getText().trim();\r
183 \r
184                         // Trying to determine if the value is integer or\r
185                         // has a decimal part will prevent the uncertainty\r
186                         // term from appearing when user types an exact value\r
187                         try {\r
188                                 try {\r
189                                         return Amount.valueOf(Integer.parseInt(text), oldUnit);\r
190                                 } catch (NumberFormatException e) {\r
191 \r
192                                 }\r
193                                 Amount<?> a = Amount.valueOf(Double.parseDouble(text), oldUnit);\r
194                                 return a;\r
195                         } catch (NumberFormatException e) {\r
196                                 // Storing the old unit allows you to type 10 into a field\r
197                                 // that says 20 mm and get 10 mm, so you dont have to\r
198                                 // type the unit if they havn't changed.\r
199                                 \r
200                                 //Amount wants a leading 0\r
201                                 if (text.startsWith(".")){\r
202                                         text = "0" + text;\r
203                                 }\r
204                                 \r
205                                 Amount<?> a = Amount.valueOf(text);\r
206                                 oldUnit = a.getUnit();\r
207                                 return a;\r
208                         }\r
209 \r
210                 }\r
211 \r
212                 @SuppressWarnings("unchecked")\r
213                 @Override\r
214                 public void setValue(Object o) {\r
215                         Amount a = (Amount) o;\r
216                         oldUnit = a.getUnit();\r
217 \r
218                         String text;\r
219                         //Leave off the fractional part if it is not relevant\r
220                         if (a.isExact())\r
221                                 text = a.getExactValue() + " " + a.getUnit();\r
222                         else\r
223                                 text = nf.format(a.doubleValue(a.getUnit())) + " " + a.getUnit();\r
224 \r
225                         setAsText(text);\r
226                 }\r
227 \r
228                 @Override\r
229                 public void setAsText(String text) throws IllegalArgumentException {\r
230                         editor.setText(text);\r
231                 };\r
232 \r
233                 @Override\r
234                 public Component getCustomEditor() {\r
235                         return editor;\r
236                 }\r
237         }\r
238 \r
239 }\r