Make fuel editors take fuel in ctor
[sw/motorsim] / gui / com / billkuker / rocketry / motorsim / visual / MultiObjectEditor.java
1 package com.billkuker.rocketry.motorsim.visual;\r
2 import java.awt.Component;\r
3 import java.awt.FileDialog;\r
4 import java.awt.Frame;\r
5 import java.awt.event.ActionEvent;\r
6 import java.awt.event.ActionListener;\r
7 import java.io.File;\r
8 import java.io.IOException;\r
9 import java.util.HashMap;\r
10 import java.util.HashSet;\r
11 import java.util.List;\r
12 import java.util.Map;\r
13 import java.util.Set;\r
14 import java.util.Vector;\r
15 \r
16 import javax.swing.JMenu;\r
17 import javax.swing.JMenuItem;\r
18 import javax.swing.JOptionPane;\r
19 import javax.swing.JTabbedPane;\r
20 \r
21 import org.apache.log4j.Logger;\r
22 \r
23 \r
24 public abstract class MultiObjectEditor<OBJECT, EDITOR extends Component> extends JTabbedPane {\r
25 \r
26         private static final long serialVersionUID = 1L;\r
27 \r
28         private static final Logger log = Logger.getLogger(MultiObjectEditor.class);\r
29         \r
30         private final Frame frame;\r
31         \r
32         private final String noun;\r
33         \r
34         private final Map<OBJECT, EDITOR> objectToEditor = new HashMap<OBJECT, EDITOR>();\r
35         private final Map<EDITOR, OBJECT> editorToObject = new HashMap<EDITOR, OBJECT>();\r
36         private final Map<File, EDITOR> fileToEditor = new HashMap<File, EDITOR>();\r
37         private final Map<EDITOR, File> editorToFile = new HashMap<EDITOR, File>();\r
38         \r
39         private final Set<OBJECT> dirty = new HashSet<OBJECT>();\r
40         \r
41         public MultiObjectEditor(final Frame frame, final String noun){\r
42                 this.frame = frame;\r
43                 this.noun = " " + noun.trim();\r
44         }\r
45         \r
46         public final void dirty(final OBJECT o){\r
47                 if ( !dirty.contains(o) )\r
48                         setTitleAt(indexOfComponent(objectToEditor.get(o)), "*" + getTitleAt(indexOfComponent(objectToEditor.get(o))));\r
49                 dirty.add(o);\r
50         }\r
51         \r
52         public final void dirty(final EDITOR e){\r
53                 dirty(editorToObject.get(e));\r
54         }\r
55         \r
56         private final void undirty(final OBJECT o){\r
57                 if ( dirty.contains(o) )\r
58                         setTitleAt(indexOfComponent(objectToEditor.get(o)), getTitleAt(indexOfComponent(objectToEditor.get(o))).replaceAll("^\\*", ""));\r
59                 dirty.remove(o);\r
60         }\r
61         \r
62         public final JMenu getMenu(){\r
63                 JMenu ret = new JMenu("File");\r
64                 for ( JMenuItem i : getMenuItems() )\r
65                         ret.add(i);\r
66                 return ret;\r
67         }\r
68         \r
69         private void menuNew(){\r
70                 add(newObject());\r
71         }\r
72         \r
73         @SuppressWarnings("unchecked")\r
74         @Override\r
75         public EDITOR getSelectedComponent(){\r
76                 return (EDITOR)super.getSelectedComponent();\r
77         }\r
78         \r
79         private void close(){\r
80                 EDITOR e = getSelectedComponent();\r
81                 OBJECT o = editorToObject.get(e);\r
82                 File f = editorToFile.get(e);\r
83                 \r
84                 if ( dirty.contains(o) ){\r
85                          int response = JOptionPane.showConfirmDialog(this, "Object is unsaved. Save Before Closing?", "Confirm", JOptionPane.YES_NO_CANCEL_OPTION);\r
86                          if ( response == JOptionPane.YES_OPTION ){\r
87                                  saveDialog();\r
88                          } else if ( response == JOptionPane.CANCEL_OPTION ){\r
89                                  return;\r
90                          }\r
91                 }\r
92                 \r
93                 objectToEditor.remove(o);\r
94                 editorToObject.remove(e);\r
95                 fileToEditor.remove(f);\r
96                 editorToFile.remove(e);\r
97                 remove(e);\r
98         }\r
99         \r
100         private void saveDialog(){\r
101                 EDITOR e = getSelectedComponent();\r
102                 if ( !editorToFile.containsKey(e) ){\r
103                         log.debug("Editor has no file, saving as...");\r
104                         saveAsDialog();\r
105                         return;\r
106                 }\r
107                 File file = editorToFile.get(e);\r
108                 log.debug("Saving to " + file.getAbsolutePath());\r
109                 try {\r
110                         saveToFile(editorToObject.get(e), file);\r
111                         undirty(editorToObject.get(e));\r
112                 } catch (IOException e1) {\r
113                         errorDialog(e1);\r
114                 }\r
115         }\r
116         private void saveAsDialog(){\r
117                 EDITOR e = getSelectedComponent();\r
118                 final FileDialog fd = new FileDialog(frame, "Save" + noun + " As", FileDialog.SAVE);\r
119                 fd.setVisible(true);\r
120                 if (fd.getFile() != null ) {\r
121                         File file = new File(fd.getDirectory() + fd.getFile());\r
122                         try {\r
123                                 OBJECT o = editorToObject.get(e);\r
124                                 saveToFile(o, file);\r
125                                 undirty(o);\r
126                                 objectToEditor.put(o, e);\r
127                                 editorToObject.put(e, o);\r
128                                 fileToEditor.put(file, e);\r
129                                 editorToFile.put(e, file);\r
130                                 setTitleAt(\r
131                                                 getSelectedIndex(),\r
132                                                 file.getName());\r
133                         } catch (Exception e1) {\r
134                                 errorDialog(e1);\r
135                         }\r
136                 }\r
137         }\r
138         \r
139         private void openDialog(){\r
140                 final FileDialog fd = new FileDialog(frame, "Open" + noun + "...", FileDialog.LOAD);\r
141                 fd.setVisible(true);\r
142                 if ( fd.getFile() != null ) {\r
143                         File file = new File(fd.getDirectory() + fd.getFile());\r
144                         log.debug("Opening File " + file.getAbsolutePath());\r
145                         if ( fileToEditor.containsKey(file) ){\r
146                                 log.debug("File " + file.getAbsolutePath() + "Already open, focusing");\r
147                                 setSelectedComponent(fileToEditor.get(file));\r
148                                 return;\r
149                         }\r
150                         try {\r
151                                 OBJECT o = loadFromFile(file);\r
152                                 EDITOR e = createEditor(o);\r
153                                 objectToEditor.put(o, e);\r
154                                 editorToObject.put(e, o);\r
155                                 fileToEditor.put(file, e);\r
156                                 editorToFile.put(e, file);\r
157                                 addTab(file.getName(), e);                                                                      \r
158                         } catch (Exception e) {\r
159                                 errorDialog(e);\r
160                         }\r
161                 }\r
162         }\r
163         \r
164         public final List<JMenuItem> getMenuItems(){\r
165                 List<JMenuItem> ret = new Vector<JMenuItem>();\r
166                 ret.add(new JMenuItem("New" + noun){\r
167                         private static final long serialVersionUID = 1L;\r
168                         {\r
169                                 addActionListener(new ActionListener() {\r
170                                         @Override\r
171                                         public void actionPerformed(ActionEvent ae) {\r
172                                                 log.debug("New");\r
173                                                 menuNew();\r
174                                         }\r
175                                 });\r
176                         }\r
177                 });\r
178                 ret.add(new JMenuItem("Open" + noun + "..."){\r
179                                 private static final long serialVersionUID = 1L;\r
180                                 {\r
181                                         addActionListener(new ActionListener() {\r
182                                                 @Override\r
183                                                 public void actionPerformed(ActionEvent ae) {\r
184                                                         log.debug("Open...");\r
185                                                         openDialog();\r
186                                                 }\r
187                                         });\r
188                                 }\r
189                         });\r
190                 ret.add(new JMenuItem("Close" + noun){\r
191                         private static final long serialVersionUID = 1L;\r
192                         {\r
193                                 addActionListener(new ActionListener() {\r
194                                         @Override\r
195                                         public void actionPerformed(ActionEvent ae) {\r
196                                                 log.debug("Close");\r
197                                                 close();\r
198                                         }\r
199                                 });\r
200                         }\r
201                 });\r
202                 ret.add(new JMenuItem("Save" + noun){\r
203                         private static final long serialVersionUID = 1L;\r
204                         {\r
205                                 addActionListener(new ActionListener() {\r
206                                         @Override\r
207                                         public void actionPerformed(ActionEvent ae) {\r
208                                                 log.debug("Save");\r
209                                                 saveDialog();\r
210                                         }\r
211                                 });\r
212                         }\r
213                 });\r
214                 ret.add(new JMenuItem("Save" + noun + " As..."){\r
215                         private static final long serialVersionUID = 1L;\r
216                         {\r
217                                 addActionListener(new ActionListener() {\r
218                                         @Override\r
219                                         public void actionPerformed(ActionEvent ae) {\r
220                                                 log.debug("Save As...");\r
221                                                 saveAsDialog();\r
222                                         }\r
223                                 });\r
224                         }\r
225                 });\r
226                 return ret;\r
227         }\r
228 \r
229         protected final void add(final OBJECT o){\r
230                 EDITOR e = createEditor(o);\r
231                 objectToEditor.put(o, e);\r
232                 editorToObject.put(e, o);\r
233                 addTab("new", e);\r
234                 dirty(o);\r
235         }\r
236         \r
237         public final void load(final File f) throws IOException{\r
238                 OBJECT o = loadFromFile(f);\r
239                 EDITOR e = createEditor(o);\r
240                 objectToEditor.put(o, e);\r
241                 editorToObject.put(e, o);\r
242                 fileToEditor.put(f, e);\r
243                 editorToFile.put(e, f);\r
244                 addTab(f.getName(), e);\r
245         }\r
246         \r
247         public abstract EDITOR createEditor(final OBJECT o);\r
248         \r
249         public abstract OBJECT newObject();\r
250         \r
251         protected abstract OBJECT loadFromFile(final File f) throws IOException;\r
252         \r
253         protected abstract void saveToFile(final OBJECT o, final File f) throws IOException;\r
254 \r
255         \r
256         private final void errorDialog(final Throwable t){\r
257                 t.printStackTrace();\r
258                 JOptionPane.showMessageDialog(MultiObjectEditor.this, t.getClass().getSimpleName() + ": " + t.getMessage());\r
259         }\r
260 }\r