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
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
16 import javax.swing.JComponent;
\r
17 import javax.swing.JMenu;
\r
18 import javax.swing.JMenuItem;
\r
19 import javax.swing.JOptionPane;
\r
20 import javax.swing.JSeparator;
\r
21 import javax.swing.JTabbedPane;
\r
23 import org.apache.log4j.Logger;
\r
26 public abstract class MultiObjectEditor<OBJECT, EDITOR extends Component> extends JTabbedPane {
\r
28 private static final long serialVersionUID = 1L;
\r
30 private static final Logger log = Logger.getLogger(MultiObjectEditor.class);
\r
32 protected abstract class ObjectCreator {
\r
33 public abstract OBJECT newObject();
\r
34 public abstract String getName();
\r
37 protected final Frame frame;
\r
39 private final String noun;
\r
41 private List<ObjectCreator> creators = new Vector<ObjectCreator>();
\r
43 private final Map<OBJECT, EDITOR> objectToEditor = new HashMap<OBJECT, EDITOR>();
\r
44 private final Map<EDITOR, OBJECT> editorToObject = new HashMap<EDITOR, OBJECT>();
\r
45 private final Map<File, EDITOR> fileToEditor = new HashMap<File, EDITOR>();
\r
46 private final Map<EDITOR, File> editorToFile = new HashMap<EDITOR, File>();
\r
49 private final Set<OBJECT> dirty = new HashSet<OBJECT>();
\r
51 public MultiObjectEditor(final Frame frame, final String noun){
\r
53 this.noun = " " + noun.trim();
\r
56 protected boolean has(OBJECT o){
\r
57 return objectToEditor.containsKey(o);
\r
60 protected void objectAdded(OBJECT o, EDITOR e){}
\r
62 protected void objectRemoved(OBJECT o, EDITOR e){}
\r
64 protected final void addCreator(ObjectCreator c){
\r
68 public boolean hasDirty(){
\r
69 return dirty.size() > 0;
\r
72 public final void dirty(final OBJECT o){
\r
73 if ( !dirty.contains(o) )
\r
74 setTitleAt(indexOfComponent(objectToEditor.get(o)), "*" + getTitleAt(indexOfComponent(objectToEditor.get(o))));
\r
78 public final void dirty(final EDITOR e){
\r
79 dirty(editorToObject.get(e));
\r
82 private final void undirty(final OBJECT o){
\r
83 if ( dirty.contains(o) )
\r
84 setTitleAt(indexOfComponent(objectToEditor.get(o)), getTitleAt(indexOfComponent(objectToEditor.get(o))).replaceAll("^\\*", ""));
\r
88 public JMenu getMenu(){
\r
89 JMenu ret = new JMenu("File");
\r
90 for ( JComponent i : getMenuItems() )
\r
95 private void menuNew(ObjectCreator c){
\r
99 @SuppressWarnings("unchecked")
\r
100 public EDITOR getSelectedEditor() {
\r
101 EDITOR e = (EDITOR) super.getSelectedComponent();
\r
102 if (editorToObject.containsKey(e))
\r
107 private void close(){
\r
108 EDITOR e = getSelectedEditor();
\r
111 OBJECT o = editorToObject.get(e);
\r
112 File f = editorToFile.get(e);
\r
114 if ( dirty.contains(o) ){
\r
115 int response = JOptionPane.showConfirmDialog(this, "Object is unsaved. Save Before Closing?", "Confirm", JOptionPane.YES_NO_CANCEL_OPTION);
\r
116 if ( response == JOptionPane.YES_OPTION ){
\r
118 } else if ( response == JOptionPane.CANCEL_OPTION ){
\r
124 objectToEditor.remove(o);
\r
125 editorToObject.remove(e);
\r
126 fileToEditor.remove(f);
\r
127 editorToFile.remove(e);
\r
128 objectRemoved(o, e);
\r
132 private void saveDialog(){
\r
133 EDITOR e = getSelectedEditor();
\r
136 if ( !editorToFile.containsKey(e) ){
\r
137 log.debug("Editor has no file, saving as...");
\r
141 File file = editorToFile.get(e);
\r
142 log.debug("Saving to " + file.getAbsolutePath());
\r
144 saveToFile(editorToObject.get(e), file);
\r
145 undirty(editorToObject.get(e));
\r
146 } catch (IOException e1) {
\r
150 private void saveAsDialog(){
\r
151 EDITOR e = getSelectedEditor();
\r
154 final FileDialog fd = new FileDialog(frame, "Save" + noun + " As", FileDialog.SAVE);
\r
155 fd.setVisible(true);
\r
156 if (fd.getFile() != null ) {
\r
157 File file = new File(fd.getDirectory() + fd.getFile());
\r
159 OBJECT o = editorToObject.get(e);
\r
160 saveToFile(o, file);
\r
162 objectToEditor.put(o, e);
\r
163 editorToObject.put(e, o);
\r
164 fileToEditor.put(file, e);
\r
165 editorToFile.put(e, file);
\r
167 getSelectedIndex(),
\r
169 } catch (Exception e1) {
\r
175 private void openDialog(){
\r
176 final FileDialog fd = new FileDialog(frame, "Open" + noun + "...", FileDialog.LOAD);
\r
177 fd.setVisible(true);
\r
178 if ( fd.getFile() != null ) {
\r
179 File file = new File(fd.getDirectory() + fd.getFile());
\r
180 log.debug("Opening File " + file.getAbsolutePath());
\r
181 if ( fileToEditor.containsKey(file) ){
\r
182 log.debug("File " + file.getAbsolutePath() + "Already open, focusing");
\r
183 setSelectedComponent(fileToEditor.get(file));
\r
187 OBJECT o = loadFromFile(file);
\r
188 EDITOR e = createEditor(o);
\r
189 objectToEditor.put(o, e);
\r
190 editorToObject.put(e, o);
\r
191 fileToEditor.put(file, e);
\r
192 editorToFile.put(e, file);
\r
193 addTab(file.getName(), e);
\r
195 setSelectedComponent(e);
\r
196 } catch (Exception e) {
\r
202 public final List<JComponent> getMenuItems(){
\r
203 List<JComponent> ret = new Vector<JComponent>();
\r
204 if ( creators.size() == 1 ){
\r
205 final ObjectCreator c = creators.get(0);
\r
206 ret.add(new JMenuItem("New " + c.getName()){
\r
207 private static final long serialVersionUID = 1L;
\r
209 addActionListener(new ActionListener() {
\r
211 public void actionPerformed(ActionEvent ae) {
\r
219 ret.add(new JMenu("New"){
\r
220 private static final long serialVersionUID = 1L;
\r
222 for (final ObjectCreator c : creators ){
\r
223 add(new JMenuItem("New " + c.getName()){
\r
224 private static final long serialVersionUID = 1L;
\r
226 addActionListener(new ActionListener() {
\r
228 public void actionPerformed(ActionEvent ae) {
\r
239 ret.add(new JMenuItem("Open" + noun + "..."){
\r
240 private static final long serialVersionUID = 1L;
\r
242 addActionListener(new ActionListener() {
\r
244 public void actionPerformed(ActionEvent ae) {
\r
245 log.debug("Open...");
\r
251 ret.add(new JMenuItem("Close" + noun){
\r
252 private static final long serialVersionUID = 1L;
\r
254 addActionListener(new ActionListener() {
\r
256 public void actionPerformed(ActionEvent ae) {
\r
257 log.debug("Close");
\r
263 ret.add(new JSeparator());
\r
264 ret.add(new JMenuItem("Save" + noun){
\r
265 private static final long serialVersionUID = 1L;
\r
267 addActionListener(new ActionListener() {
\r
269 public void actionPerformed(ActionEvent ae) {
\r
276 ret.add(new JMenuItem("Save" + noun + " As..."){
\r
277 private static final long serialVersionUID = 1L;
\r
279 addActionListener(new ActionListener() {
\r
281 public void actionPerformed(ActionEvent ae) {
\r
282 log.debug("Save As...");
\r
291 protected final void add(final OBJECT o){
\r
292 EDITOR e = createEditor(o);
\r
293 objectToEditor.put(o, e);
\r
294 editorToObject.put(e, o);
\r
298 setSelectedComponent(e);
\r
301 protected final void add(final OBJECT o, final File f){
\r
302 EDITOR e = createEditor(o);
\r
303 objectToEditor.put(o, e);
\r
304 editorToObject.put(e, o);
\r
305 fileToEditor.put(f, e);
\r
306 editorToFile.put(e, f);
\r
307 addTab(f.getName(), e);
\r
309 setSelectedComponent(e);
\r
312 public final void load(final File f) throws IOException{
\r
313 OBJECT o = loadFromFile(f);
\r
314 EDITOR e = createEditor(o);
\r
315 objectToEditor.put(o, e);
\r
316 editorToObject.put(e, o);
\r
317 fileToEditor.put(f, e);
\r
318 editorToFile.put(e, f);
\r
319 addTab(f.getName(), e);
\r
321 setSelectedComponent(e);
\r
324 public abstract EDITOR createEditor(final OBJECT o);
\r
326 protected abstract OBJECT loadFromFile(final File f) throws IOException;
\r
328 protected abstract void saveToFile(final OBJECT o, final File f) throws IOException;
\r
331 private final void errorDialog(final Throwable t){
\r
332 t.printStackTrace();
\r
333 JOptionPane.showMessageDialog(MultiObjectEditor.this, t.getClass().getSimpleName() + ": " + t.getMessage());
\r