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