1
2
3
4
5
6
7
8
9
10 package nl.tudelft.simulation.dsol.gui.windows;
11
12 import java.awt.BorderLayout;
13 import java.awt.Color;
14 import java.awt.Component;
15 import java.awt.Dimension;
16 import java.awt.Toolkit;
17 import java.io.IOException;
18 import java.lang.reflect.Constructor;
19 import java.net.URL;
20 import java.util.ArrayList;
21 import java.util.Iterator;
22 import java.util.List;
23
24 import javax.swing.Action;
25 import javax.swing.BorderFactory;
26 import javax.swing.JEditorPane;
27 import javax.swing.JFrame;
28 import javax.swing.JMenu;
29 import javax.swing.JMenuBar;
30 import javax.swing.JPanel;
31 import javax.swing.JScrollPane;
32 import javax.swing.JSeparator;
33 import javax.swing.JTree;
34 import javax.swing.SwingConstants;
35 import javax.swing.UIManager;
36 import javax.swing.WindowConstants;
37
38 import nl.tudelft.simulation.dsol.experiment.Experiment;
39 import nl.tudelft.simulation.dsol.gui.DSOLApplicationInterface;
40 import nl.tudelft.simulation.dsol.gui.UIInitializer;
41 import nl.tudelft.simulation.dsol.gui.menu.HelpMenu;
42 import nl.tudelft.simulation.dsol.gui.panels.ControlPanel;
43 import nl.tudelft.simulation.dsol.gui.panels.ExperimentTree;
44 import nl.tudelft.simulation.dsol.gui.panels.Statusbar;
45 import nl.tudelft.simulation.dsol.gui.panels.TabbedPane;
46 import nl.tudelft.simulation.event.EventInterface;
47 import nl.tudelft.simulation.event.EventListenerInterface;
48 import nl.tudelft.simulation.language.io.URLResource;
49 import nl.tudelft.simulation.language.reflection.ClassUtil;
50 import nl.tudelft.simulation.logger.Logger;
51
52 import org.jdom.Element;
53 import org.jdom.input.SAXBuilder;
54
55 /***
56 * DSOL Frame <br>
57 * (c) copyright 2002-2005 <a href="http://www.simulation.tudelft.nl">Delft
58 * University of Technology </a>, the Netherlands. <br>
59 * See for project information <a
60 * href="http://www.simulation.tudelft.nl">www.simulation.tudelft.nl </a> <br>
61 * License of use: <a href="http://www.gnu.org/copyleft/lesser.html">Lesser
62 * General Public License (LGPL) </a>, no warranty.
63 *
64 * @version $Revision$ $Date$
65 * @author <a href="http://www.tbm.tudelft.nl/webstaf/peterja">Peter Jacobs </a>
66 */
67 public class DSOLFrame extends JFrame implements EventListenerInterface
68 {
69 /*** builder the xerces parser with validation turned on */
70 private static SAXBuilder builder = new SAXBuilder(
71 "org.apache.xerces.parsers.SAXParser", true);
72
73 static
74 {
75
76 builder.setFeature("http://xml.org/sax/features/validation", true);
77 builder.setFeature("http://apache.org/xml/features/validation/schema",
78 true);
79
80
81 String xsd = URLResource.getResource("/navigation.xsd")
82 .toExternalForm();
83 builder
84 .setProperty(
85 "http://apache.org/xml/properties/schema/external-schemaLocation",
86 "http://www.simulation.tudelft.nl/dsol " + xsd);
87 }
88
89 /*** the preferredSize is the preferredSize of the panel */
90 public static final Dimension PREFERRED_SIZE = new Dimension(400, 375);
91
92 /*** the application */
93 protected DSOLApplicationInterface application = null;
94
95 /*** tabbedPanel */
96 protected TabbedPane tabbedPanel = null;
97
98 /*** the experimentTree */
99 protected JTree experimentTree = null;
100
101 /*** the statusbar */
102 protected Statusbar statusbar = null;
103
104 /*** the controlPanel */
105 protected ControlPanel controlPanel = null;
106
107 /***
108 * constructs a new DSOLFrame
109 *
110 * @param application the application
111 * @param navigation the URL address of the xml-based navigation structure.
112 */
113 public DSOLFrame(final DSOLApplicationInterface application,
114 final URL navigation)
115 {
116 super("DSOL main window");
117
118 try
119 {
120 UIManager
121 .setLookAndFeel("com.jgoodies.plaf.plastic.Plastic3DLookAndFeel");
122
123
124 UIInitializer.initialize();
125 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
126 this.setLocation((int) Math.round(screenSize.width * 0.5 - 0.5
127 * PREFERRED_SIZE.width), (int) Math.round(screenSize.height
128 * 0.33 - 0.5 * PREFERRED_SIZE.height));
129 this.application = application;
130 this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
131 this.application.addListener(this,
132 DSOLApplicationInterface.EXPERIMENT_CHANGED_EVENT);
133 } catch (Exception exception)
134 {
135 Logger.warning(this, "DSOLFrame", exception);
136 }
137 this.initialize(navigation);
138 this.pack();
139 this.setVisible(true);
140 }
141
142 /***
143 * initializes the DSOL Frame
144 *
145 * @param navigation the navigation file
146 */
147 private void initialize(final URL navigation)
148 {
149 JPanel contentPane = new JPanel();
150 contentPane.setPreferredSize(PREFERRED_SIZE);
151 contentPane.setLayout(new BorderLayout());
152 this.setContentPane(contentPane);
153
154 this.setJMenuBar(this.createMenuBar(navigation));
155
156 this.controlPanel = new ControlPanel(this.application);
157
158 this.tabbedPanel = new TabbedPane(SwingConstants.TOP);
159 this.tabbedPanel.setBorder(BorderFactory.createCompoundBorder(
160 BorderFactory.createEtchedBorder(), BorderFactory
161 .createEmptyBorder()));
162 contentPane.add(this.tabbedPanel, BorderLayout.CENTER);
163 this.statusbar = new Statusbar(this.application);
164
165 this.experimentTree = new JTree();
166 this.experimentTree.setEditable(false);
167 this.experimentTree.setFocusable(false);
168
169 URL about = URLResource.getResource("/html/about.html");
170 JEditorPane aboutPane = null;
171 try
172 {
173 aboutPane = new JEditorPane(about);
174 } catch (IOException exception)
175 {
176 Logger.warning(this, "initialize", exception);
177 }
178 aboutPane.setAlignmentY(Component.BOTTOM_ALIGNMENT);
179 aboutPane.setEditable(false);
180 this.tabbedPanel.add("About", aboutPane);
181 }
182
183 /***
184 * creates a menu bar
185 *
186 * @param navigation the xml-based navigation
187 *
188 * @return the menu bar
189 */
190 private JMenuBar createMenuBar(final URL navigation)
191 {
192 Logger.info(this, "createMenuBar", "using "
193 + navigation.toExternalForm());
194 try
195 {
196 JMenuBar menuBar = new JMenuBar();
197 menuBar.setBorder(BorderFactory.createLineBorder(Color.GRAY));
198
199 Element rootElement = builder.build(navigation).getRootElement();
200 for (Iterator i = rootElement.getChildren("menu").iterator(); i
201 .hasNext();)
202 {
203 Element menu = (Element) i.next();
204 menuBar.add(this.parseMenu(menu));
205 }
206 menuBar.add(new HelpMenu(this.application));
207 return menuBar;
208 } catch (Exception exception)
209 {
210 Logger.warning(this, "initialze2", exception.getMessage());
211 return null;
212 }
213 }
214
215 /***
216 * parses an xml-based element into a JMenu
217 *
218 * @param element the JDOM element
219 * @return the JMenu
220 * @throws Exception on IOException
221 */
222 private JMenu parseMenu(final Element element) throws Exception
223 {
224 JMenu menu = new JMenu(element.getAttributeValue("name"));
225 for (Iterator i = element.getChildren().iterator(); i.hasNext();)
226 {
227 Element child = (Element) i.next();
228 if (child.getName().equals("menu"))
229 {
230 menu.add(this.parseMenu(child));
231 } else if (child.getName().equals("separator"))
232 {
233 menu.add(new JSeparator());
234 } else if (child.getName().equals("action"))
235 {
236 Class actionClass = Class.forName(child
237 .getAttributeValue("className"));
238 List arguments = new ArrayList();
239 arguments.add(this.application);
240 for (Iterator ii = child.getChildren("argument").iterator(); ii
241 .hasNext();)
242 {
243 arguments.add(((Element) ii.next()).getValue());
244 }
245 Class[] argumentClasses = new Class[arguments.size()];
246 argumentClasses[0] = DSOLApplicationInterface.class;
247 for (int loop = 0; loop < argumentClasses.length - 1; loop++)
248 {
249 argumentClasses[loop + 1] = String.class;
250 }
251 Constructor actionConstructor = ClassUtil.resolveConstructor(
252 actionClass, argumentClasses);
253 Object action = actionConstructor.newInstance(arguments
254 .toArray());
255 if (action instanceof Action)
256 {
257 menu.add((Action) action);
258 } else if (action instanceof JMenu)
259 {
260 menu.add((JMenu) action);
261 }
262 }
263 }
264 return menu;
265 }
266
267 /***
268 * @see nl.tudelft.simulation.event.EventListenerInterface
269 * #notify(nl.tudelft.simulation.event.EventInterface)
270 */
271 public void notify(final EventInterface event)
272 {
273 if (event.getSource().equals(this.application)
274 && event.getType().equals(
275 DSOLApplicationInterface.EXPERIMENT_CHANGED_EVENT))
276 {
277 this.tabbedPanel.remove("Description");
278 this.tabbedPanel.remove("Experiment");
279 this.tabbedPanel.remove("Control");
280 if (event.getContent() != null)
281 {
282 Experiment experiment = (Experiment) event.getContent();
283 try
284 {
285 String descriptionName = "/";
286 if (experiment.getModel().getClass().getPackage() != null)
287 {
288 descriptionName = descriptionName
289 + experiment.getModel().getClass().getPackage()
290 .getName().replace('.', '/');
291 }
292 descriptionName = descriptionName + "/package.html";
293 URL description = experiment.getModel().getClass()
294 .getResource(descriptionName);
295 JEditorPane descriptionPane = null;
296 descriptionPane = new JEditorPane(description);
297 descriptionPane.setAlignmentY(Component.BOTTOM_ALIGNMENT);
298 descriptionPane.setEditable(false);
299 this.tabbedPanel.add("Description", 0, new JScrollPane(
300 descriptionPane));
301 } catch (IOException exception)
302 {
303 Logger
304 .fine(this, "initialize",
305 "experiment has no package.html describing the experiment");
306 }
307 this.setTitle("DSOL main window ("
308 + experiment.getProperty(Experiment.EXPERIMENT_NAME)
309 + ")");
310 this.experimentTree.setModel(new ExperimentTree(experiment));
311 this.tabbedPanel.add("Experiment", 1, new JScrollPane(
312 this.experimentTree));
313 this.tabbedPanel.add("Control", 2, this.controlPanel);
314 this.getContentPane().add(this.statusbar, BorderLayout.SOUTH);
315 } else
316 {
317 this.setTitle("DSOL main window");
318 this.getContentPane().remove(this.statusbar);
319 }
320 this.validate();
321 this.repaint();
322 }
323 }
324 }