Details | Last modification | View Log | SVN | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 15 | arune | 1 | /** |
| 2 | * File created by Jimmy |
||
| 3 | * at 2003-dec-23 21:43:41 |
||
| 4 | */ |
||
| 5 | package Macbeth; |
||
| 6 | |||
| 7 | import Macbeth.System.*; |
||
| 8 | import Macbeth.Utilities.*; |
||
| 9 | import com.jgoodies.plaf.windows.ExtWindowsLookAndFeel; |
||
| 10 | import com.jgoodies.plaf.plastic.PlasticXPLookAndFeel; |
||
| 11 | import com.jgoodies.plaf.plastic.Plastic3DLookAndFeel; |
||
| 12 | import javax.swing.*; |
||
| 13 | import javax.swing.event.*; |
||
| 14 | import java.awt.*; |
||
| 15 | import java.awt.event.*; |
||
| 16 | import java.util.HashMap; |
||
| 17 | import java.util.Iterator; |
||
| 18 | import java.io.IOException; |
||
| 19 | import java.net.URL; |
||
| 20 | |||
| 21 | /** |
||
| 22 | * A full featured kernel with graphical user interface. |
||
| 23 | * @author Jimmy |
||
| 24 | */ |
||
| 25 | public class GUIKernel extends MbKernel { |
||
| 26 | |||
| 27 | //a list of references to all loaded module GUI windows |
||
| 28 | private HashMap loadedModuleGUIs; |
||
| 29 | //the module whose info page we're currently viewing |
||
| 30 | private MbModule selectedModule; |
||
| 31 | |||
| 32 | /** |
||
| 33 | * Creates a new instance of GUIKernel. |
||
| 34 | * @param configFile The XML-configuration file to use. |
||
| 35 | */ |
||
| 36 | public GUIKernel(String configFile) { |
||
| 37 | super(configFile); |
||
| 38 | selectedModule = null; |
||
| 39 | //create GUI |
||
| 40 | try { |
||
| 41 | _debug.println("Loading Swing look and feel"); |
||
| 42 | //UIManager.setLookAndFeel(new ExtWindowsLookAndFeel()); |
||
| 43 | UIManager.setLookAndFeel(new Plastic3DLookAndFeel()); |
||
| 44 | } catch (Exception e) {} |
||
| 45 | _debug.println("Creating Swing GUI"); |
||
| 46 | GUI g = new GUI(); |
||
| 47 | g.setVisible(true); |
||
| 48 | try { |
||
| 49 | startup(); |
||
| 50 | } catch (MbStartupException e) { |
||
| 51 | _errors.println("Failed to start up kernel! (message: '" + e.getMessage() + "')"); |
||
| 52 | shutdown(); |
||
| 53 | } |
||
| 54 | g.updateHTMLBar(); |
||
| 55 | } |
||
| 56 | |||
| 57 | /** |
||
| 58 | * Gets a short description of the kernel. |
||
| 59 | * @return A short description of the kernel. |
||
| 60 | */ |
||
| 61 | public String description() { |
||
| 62 | return "Advanced kernel with graphical user interface"; |
||
| 63 | } |
||
| 64 | |||
| 65 | /** |
||
| 66 | * Starts up this kernel. |
||
| 67 | */ |
||
| 68 | public void startup() throws MbStartupException { |
||
| 69 | //startup MbKernel |
||
| 70 | super.startup(); |
||
| 71 | loadedModuleGUIs = new HashMap(32); |
||
| 72 | } |
||
| 73 | |||
| 74 | /** |
||
| 75 | * Shuts down this kernel. |
||
| 76 | */ |
||
| 77 | public void shutdown() { |
||
| 78 | //shut down MbKernel |
||
| 79 | super.shutdown(); |
||
| 80 | } |
||
| 81 | |||
| 82 | /** |
||
| 83 | * Finds out whether or not a module has a graphical user interface. |
||
| 84 | * @param moduleName The classname of the module. |
||
| 85 | * @return True if this module has a GUI, false otherwise (or if module wasn't found). |
||
| 86 | */ |
||
| 87 | public boolean moduleHasGUI(String moduleName) { |
||
| 88 | //get the module |
||
| 89 | MbModule m = (MbModule)loadedModules.get(moduleName); |
||
| 90 | if (m!=null) { |
||
| 91 | //get its interfaces |
||
| 92 | Class[] interfaces = m.getClass().getInterfaces(); |
||
| 93 | //check whether the module implements the MbModuleGUI interface |
||
| 94 | for (int i=0; i<interfaces.length; i++) { |
||
| 95 | if (interfaces[i].getName().equals("Macbeth.System.MbModuleGUI")) { |
||
| 96 | return true; |
||
| 97 | } |
||
| 98 | } |
||
| 99 | } |
||
| 100 | return false; |
||
| 101 | } |
||
| 102 | |||
| 103 | /** |
||
| 104 | * Gets the HTML-page from a specified module. |
||
| 105 | * @param moduleName The classname of the module whose HTML-page you want to get. |
||
| 106 | * @return Full HTML-code for this modules HTML-page. If the specified module |
||
| 107 | * doesn't have a HTML-interface, its description is returned instead. |
||
| 108 | */ |
||
| 109 | public String getHTMLPage(String moduleName) { |
||
| 110 | //get the module |
||
| 111 | MbModule mod = (MbModule)loadedModules.get(moduleName); |
||
| 112 | //get its html-interface |
||
| 113 | MbHTMLInterface html = mod.getHTMLInterface(); |
||
| 114 | //if this module has a HTML-interface |
||
| 115 | if (html!=null) { |
||
| 116 | //then return the HTML-page |
||
| 117 | return html.getHTMLPage(); |
||
| 118 | //else, if this module doesn't have a html-interface |
||
| 119 | } else { |
||
| 120 | //return description instead |
||
| 121 | return mod.description(); |
||
| 122 | } |
||
| 123 | } |
||
| 124 | |||
| 125 | /** |
||
| 126 | * The whole graphical user interface for this kernel. |
||
| 127 | */ |
||
| 128 | private class GUI extends JFrame implements ActionListener,WindowListener { |
||
| 129 | //private JSplitPane contentArea; |
||
| 130 | private JEditorPane htmlBar; |
||
| 131 | private JScrollPane htmlBarScrolled; |
||
| 132 | private JTabbedPane tabbedArea; |
||
| 133 | private JEditorPane tabInfo; |
||
| 134 | private JScrollPane tabInfoScrolled; |
||
| 135 | private MDIDesktopPane tabGUI; |
||
| 136 | private JScrollPane tabGUIScrolled; |
||
| 137 | //private JTextArea console; |
||
| 138 | private JEditorPane console; |
||
| 139 | //private MbHTMLDocument consoleDocument; |
||
| 140 | private JScrollPane consoleScrolled; |
||
| 141 | private JMenuBar menuBar; |
||
| 142 | |||
| 143 | public GUI() { |
||
| 144 | setTitle("Macbeth GUI kernel"); |
||
| 145 | |||
| 146 | //create html bar |
||
| 147 | htmlBar = new JEditorPane(); |
||
| 148 | htmlBar.setEditable(false); |
||
| 149 | htmlBar.setBorder(BorderFactory.createEmptyBorder()); |
||
| 150 | htmlBar.setContentType("text/html"); |
||
| 151 | htmlBar.addHyperlinkListener(new HyperlinkActionsHTMLBar()); |
||
| 152 | htmlBarScrolled = new JScrollPane(htmlBar); |
||
| 153 | htmlBarScrolled.setMinimumSize(new Dimension(100,100)); |
||
| 154 | htmlBarScrolled.setBorder(BorderFactory.createEmptyBorder()); |
||
| 155 | |||
| 156 | //create info tab |
||
| 157 | tabInfo = new JEditorPane(); |
||
| 158 | tabInfo.setBorder(BorderFactory.createEmptyBorder()); |
||
| 159 | tabInfo.setContentType("text/html"); |
||
| 160 | tabInfo.addHyperlinkListener(new HyperlinkActionsInfoPage()); |
||
| 161 | tabInfo.setText("<html><h1>Macbeth!</h1></html>"); |
||
| 162 | tabInfo.setEditable(false); |
||
| 163 | tabInfoScrolled = new JScrollPane(tabInfo); |
||
| 164 | tabInfoScrolled.setBorder(BorderFactory.createEmptyBorder()); |
||
| 165 | |||
| 166 | //create gui tab |
||
| 167 | tabGUI = new MDIDesktopPane(); |
||
| 168 | tabGUI.setBorder(BorderFactory.createEmptyBorder()); |
||
| 169 | tabGUIScrolled = new JScrollPane(tabGUI); |
||
| 170 | tabGUIScrolled.setBorder(BorderFactory.createEmptyBorder()); |
||
| 171 | |||
| 172 | //create tabbed view |
||
| 173 | tabbedArea = new JTabbedPane(); |
||
| 174 | tabbedArea.addTab("Info Page", null, tabInfoScrolled, "Module information"); |
||
| 175 | tabbedArea.addTab("GUI Desktop", null, tabGUIScrolled, "Module GUI desktop"); |
||
| 176 | tabbedArea.setPreferredSize(new Dimension(600,500)); |
||
| 177 | tabbedArea.setMinimumSize(new Dimension(100,100)); |
||
| 178 | tabbedArea.setBorder(BorderFactory.createEmptyBorder()); |
||
| 179 | |||
| 180 | //create console area |
||
| 181 | console = new JEditorPane(); |
||
| 182 | console.setEditable(false); |
||
| 183 | console.setContentType("text/html"); |
||
| 184 | //console = new JTextArea(); |
||
| 185 | //console.setMargin(new Insets(5,5,5,5)); |
||
| 186 | console.setBorder(BorderFactory.createEmptyBorder()); |
||
| 187 | consoleScrolled = new JScrollPane(console); |
||
| 188 | consoleScrolled.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); |
||
| 189 | consoleScrolled.setPreferredSize(new Dimension(600,80)); |
||
| 190 | consoleScrolled.setMinimumSize(new Dimension(200,50)); |
||
| 191 | consoleScrolled.setBorder(BorderFactory.createEmptyBorder()); |
||
| 192 | consoleScrolled.addComponentListener( |
||
| 193 | new ComponentListener(){ |
||
| 194 | //when console is resized, make sure it scrolls down to bottom |
||
| 195 | public void componentResized(ComponentEvent e) { |
||
| 196 | //hmm....ugly hack, but it doesn't seem to work without the 0-position |
||
| 197 | console.setCaretPosition(0); |
||
| 198 | console.setCaretPosition(console.getDocument().getLength()); |
||
| 199 | } |
||
| 200 | public void componentMoved(ComponentEvent e) {} |
||
| 201 | public void componentShown(ComponentEvent e) {} |
||
| 202 | public void componentHidden(ComponentEvent e) {} |
||
| 203 | }); |
||
| 204 | |||
| 205 | _errors = new TextFormatterStream(new EditorPaneStream(console)); |
||
| 206 | ((TextFormatterStream)_errors).setPreString("<font size=\"-1\" color=\"red\">"); |
||
| 207 | ((TextFormatterStream)_errors).setPostString("</font>"); |
||
| 208 | _info = new TextFormatterStream(new EditorPaneStream(console)); |
||
| 209 | ((TextFormatterStream)_info).setPreString("<font size=\"-1\" color=\"black\">"); |
||
| 210 | ((TextFormatterStream)_info).setPostString("</font>"); |
||
| 211 | _debug = new TextFormatterStream(new EditorPaneStream(console)); |
||
| 212 | ((TextFormatterStream)_debug).setPreString("<font size=\"-1\" color=\"#777777\">"); |
||
| 213 | ((TextFormatterStream)_debug).setPostString("</font>"); |
||
| 214 | |||
| 215 | //create menu bar |
||
| 216 | menuBar = new JMenuBar(); |
||
| 217 | setJMenuBar(menuBar); |
||
| 218 | JMenu menu; |
||
| 219 | JMenuItem menuItem; |
||
| 220 | menu = new JMenu("System"); |
||
| 221 | menu.getAccessibleContext().setAccessibleDescription("System commands"); |
||
| 222 | menuBar.add(menu); |
||
| 223 | menuItem = new JMenuItem("Restart modules"); |
||
| 224 | menuItem.getAccessibleContext().setAccessibleDescription("Restart all modules"); |
||
| 225 | menu.add(menuItem); |
||
| 226 | menuItem = new JMenuItem("Restart kernel"); |
||
| 227 | menu.add(menuItem); |
||
| 228 | menu.addSeparator(); |
||
| 229 | menuItem = new JMenuItem("Quit"); |
||
| 230 | menu.add(menuItem); |
||
| 231 | |||
| 232 | //create a split pane that holds the HTML bar to the left and the tabview to the right |
||
| 233 | JSplitPane splitHorizontal = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,new TitledControl(htmlBarScrolled,"Macbeth menu"),tabbedArea); |
||
| 234 | splitHorizontal.setDividerLocation(130); |
||
| 235 | splitHorizontal.setDividerSize(6); |
||
| 236 | //tabbedArea will get all extra space when resizing |
||
| 237 | splitHorizontal.setResizeWeight(0.0); |
||
| 238 | //JWindowPane splitHorizontal = new JWindowPane(JWindowPane.HORIZONTAL,"Macbeth components",htmlBarScrolled,"Content",tabbedArea,null); |
||
| 239 | |||
| 240 | //create a split pane that holds the the content at top and the console at bottom |
||
| 241 | JSplitPane splitVertical = new JSplitPane(JSplitPane.VERTICAL_SPLIT,splitHorizontal,new TitledControl(consoleScrolled,"Console")); |
||
| 242 | splitVertical.setResizeWeight(0.8); |
||
| 243 | //JWindowPane splitVertical = new JWindowPane(JWindowPane.VERTICAL,"top",splitHorizontal,"Console",consoleScrolled,null); |
||
| 244 | |||
| 245 | //add everything to main frame |
||
| 246 | Container content = this.getContentPane(); |
||
| 247 | content.setLayout(new BorderLayout()); |
||
| 248 | content.add(splitVertical,BorderLayout.CENTER); |
||
| 249 | pack(); |
||
| 250 | setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); |
||
| 251 | addWindowListener(this); |
||
| 252 | } |
||
| 253 | |||
| 254 | /* EVENT HANDLERS... */ |
||
| 255 | public void actionPerformed(ActionEvent e) {} |
||
| 256 | public void windowClosing(WindowEvent e) { |
||
| 257 | //when kernel GUI is closed, it's time to shut down |
||
| 258 | shutdown(); |
||
| 259 | setVisible(false); |
||
| 260 | _errors = System.err; |
||
| 261 | _info = System.out; |
||
| 262 | _debug = System.out; |
||
| 263 | _debug.println("GUI has been closed"); |
||
| 264 | _debug.println("Waiting for threads to stop"); |
||
| 265 | dispose(); |
||
| 266 | } |
||
| 267 | public void windowOpened(WindowEvent e) {} |
||
| 268 | public void windowClosed(WindowEvent e) {} |
||
| 269 | public void windowIconified(WindowEvent e) {} |
||
| 270 | public void windowDeiconified(WindowEvent e) {} |
||
| 271 | public void windowActivated(WindowEvent e) {} |
||
| 272 | public void windowDeactivated(WindowEvent e) {} |
||
| 273 | |||
| 274 | /** |
||
| 275 | * Responds to hyperlink clicks in the left HTML bar. |
||
| 276 | */ |
||
| 277 | class HyperlinkActionsHTMLBar implements HyperlinkListener { |
||
| 278 | public void hyperlinkUpdate(HyperlinkEvent e) { |
||
| 279 | if (e.getEventType()==HyperlinkEvent.EventType.ACTIVATED) { |
||
| 280 | URL url = e.getURL(); |
||
| 281 | String description = e.getDescription(); |
||
| 282 | //if a valid URL exists for the link |
||
| 283 | if (url!=null) { |
||
| 284 | //load the page in the main browser |
||
| 285 | try { |
||
| 286 | tabInfo.setPage(url); |
||
| 287 | selectedModule = null; |
||
| 288 | } catch (IOException e1) { |
||
| 289 | e1.printStackTrace(); |
||
| 290 | } |
||
| 291 | } |
||
| 292 | //else, use the description to find out what to do |
||
| 293 | else { |
||
| 294 | //interprete the description as an internal macbeth command |
||
| 295 | String[] cmd = description.split(":"); |
||
| 296 | if (cmd.length<=0) { |
||
| 297 | return; |
||
| 298 | } |
||
| 299 | //shows information on the specified macbeth component |
||
| 300 | if (cmd[0].equalsIgnoreCase("ShowInfo")) { |
||
| 301 | tabInfo.setText(getHTMLPage(cmd[1])); |
||
| 302 | selectedModule = (MbModule)loadedModules.get(cmd[1]); |
||
| 303 | } |
||
| 304 | //adds a module GUI to the GUI desktop |
||
| 305 | else if (cmd[0].equalsIgnoreCase("ShowGUI")) { |
||
| 306 | loadModuleGUI(cmd[1]); |
||
| 307 | } |
||
| 308 | //unloads a module |
||
| 309 | else if (cmd[0].equalsIgnoreCase("Unload")) { |
||
| 310 | unloadModule(cmd[1]); |
||
| 311 | updateHTMLBar(); |
||
| 312 | } |
||
| 313 | //loads an unloaded module |
||
| 314 | else if (cmd[0].equalsIgnoreCase("Load")) { |
||
| 315 | try { |
||
| 316 | loadModule(cmd[1]); |
||
| 317 | } catch (Exception el) { |
||
| 318 | _errors.println("Error loading module: " + el); |
||
| 319 | } |
||
| 320 | updateHTMLBar(); |
||
| 321 | } |
||
| 322 | } |
||
| 323 | |||
| 324 | } |
||
| 325 | } |
||
| 326 | } |
||
| 327 | |||
| 328 | /** |
||
| 329 | * Responds to hyperlink clicks on module info page. |
||
| 330 | */ |
||
| 331 | class HyperlinkActionsInfoPage implements HyperlinkListener { |
||
| 332 | public void hyperlinkUpdate(HyperlinkEvent e) { |
||
| 333 | if (e.getEventType()==HyperlinkEvent.EventType.ACTIVATED) { |
||
| 334 | URL url = e.getURL(); |
||
| 335 | String description = e.getDescription(); |
||
| 336 | //if a valid URL exists for the link |
||
| 337 | if (url!=null) { |
||
| 338 | //load the page in the main browser |
||
| 339 | try { |
||
| 340 | tabInfo.setPage(url); |
||
| 341 | } catch (IOException e1) { |
||
| 342 | e1.printStackTrace(); |
||
| 343 | } |
||
| 344 | } |
||
| 345 | //else, notify the current module about the click |
||
| 346 | else { |
||
| 347 | if (selectedModule!=null) { |
||
| 348 | MbHTMLInterface html = selectedModule.getHTMLInterface(); |
||
| 349 | if (html!=null) { |
||
| 350 | html.linkPressed(description); |
||
| 351 | } |
||
| 352 | } |
||
| 353 | } |
||
| 354 | |||
| 355 | } |
||
| 356 | } |
||
| 357 | } |
||
| 358 | |||
| 359 | public void updateHTMLBar() { |
||
| 360 | String html = "<html>" + MySystem.lineBreak; |
||
| 361 | html += "<body><b>Loaded modules</b><p>" + MySystem.lineBreak; |
||
| 362 | //iterate through loaded modules-list |
||
| 363 | Iterator it = loadedModules.keySet().iterator(); |
||
| 364 | while (it.hasNext()) { |
||
| 365 | String modname = (String)it.next(); |
||
| 366 | html += "<b>" + modname + "</b><br>" + MySystem.lineBreak; |
||
| 367 | html += " - [<a href=\"ShowInfo:" + modname + "\">Show Info</a>]<br>" + MySystem.lineBreak; |
||
| 368 | if (moduleHasGUI(modname)) { |
||
| 369 | html += " - [<a href=\"ShowGUI:" + modname + "\">Load GUI</a>]<br>" + MySystem.lineBreak; |
||
| 370 | } |
||
| 371 | html += " - [<a href=\"Unload:" + modname + "\">Unload</a>]<br>" + MySystem.lineBreak; |
||
| 372 | } |
||
| 373 | html += "</p>" + MySystem.lineBreak; |
||
| 374 | html += "<b>Unloaded modules</b><p>"; |
||
| 375 | //iterate through module list to find unloaded modules |
||
| 376 | it = moduleList.keySet().iterator(); |
||
| 377 | while (it.hasNext()) { |
||
| 378 | String modname = (String)it.next(); |
||
| 379 | //only show unloaded modules |
||
| 380 | if (!loadedModules.containsKey(modname)) { |
||
| 381 | html += "<b>" + modname + "</b><br>" + MySystem.lineBreak; |
||
| 382 | html += " - [<a href=\"Load:" + modname + "\">Load</a>]<br>" + MySystem.lineBreak; |
||
| 383 | } |
||
| 384 | } |
||
| 385 | html += "</p>" + MySystem.lineBreak; |
||
| 386 | html += "</body></html>"; |
||
| 387 | htmlBar.setText(html); |
||
| 388 | } |
||
| 389 | |||
| 390 | |||
| 391 | /** |
||
| 392 | * Loads the GUI for the specified module. |
||
| 393 | * @param moduleName The module whose GUI should be loaded. |
||
| 394 | */ |
||
| 395 | public void loadModuleGUI(String moduleName) { |
||
| 396 | //if a GUI is already loaded for this module |
||
| 397 | if (loadedModuleGUIs.containsKey(moduleName)) { |
||
| 398 | //then bring this GUI to the front |
||
| 399 | ModuleGUIWindow w = (ModuleGUIWindow)loadedModuleGUIs.get(moduleName); |
||
| 400 | w.moveToFront(); |
||
| 401 | return; |
||
| 402 | } |
||
| 403 | //else, if this module does have a GUI |
||
| 404 | else if (moduleHasGUI(moduleName)) { |
||
| 405 | //create a new window for the GUI |
||
| 406 | MbModuleGUI i = (MbModuleGUI)loadedModules.get(moduleName); |
||
| 407 | ModuleGUIWindow w = new ModuleGUIWindow(moduleName); |
||
| 408 | //and render GUI into this window |
||
| 409 | i.renderGUI(w.getContentPane()); |
||
| 410 | w.setTitle(moduleName); |
||
| 411 | //pack the contents to minimum possible size and show frame |
||
| 412 | w.pack(); |
||
| 413 | w.setVisible(true); |
||
| 414 | tabGUI.add(w); |
||
| 415 | } else { |
||
| 416 | //the module doesn't have any GUI |
||
| 417 | } |
||
| 418 | } |
||
| 419 | |||
| 420 | /** |
||
| 421 | * A window for a module GUI. This window will be shown |
||
| 422 | * on the GUI desktop located inside the tabview. |
||
| 423 | */ |
||
| 424 | private class ModuleGUIWindow extends JInternalFrame implements InternalFrameListener { |
||
| 425 | private String moduleName; |
||
| 426 | |||
| 427 | /** |
||
| 428 | * Creates a new GUI window. |
||
| 429 | * @param moduleName The name of the module. |
||
| 430 | */ |
||
| 431 | public ModuleGUIWindow(String moduleName) { |
||
| 432 | super(); |
||
| 433 | this.moduleName = moduleName; |
||
| 434 | setDefaultCloseOperation(DISPOSE_ON_CLOSE); |
||
| 435 | setResizable(true); |
||
| 436 | setClosable(true); |
||
| 437 | setMaximizable(false); |
||
| 438 | addInternalFrameListener(this); |
||
| 439 | } |
||
| 440 | |||
| 441 | public void internalFrameOpened(InternalFrameEvent e) { |
||
| 442 | //put a reference to this window into the hashmap |
||
| 443 | loadedModuleGUIs.put(moduleName,this); |
||
| 444 | } |
||
| 445 | |||
| 446 | public void internalFrameClosed(InternalFrameEvent e) { |
||
| 447 | //remove our reference from the hashmap |
||
| 448 | loadedModuleGUIs.remove(moduleName); |
||
| 449 | } |
||
| 450 | |||
| 451 | public void internalFrameClosing(InternalFrameEvent e) {} |
||
| 452 | public void internalFrameIconified(InternalFrameEvent e) {} |
||
| 453 | public void internalFrameDeiconified(InternalFrameEvent e) {} |
||
| 454 | public void internalFrameActivated(InternalFrameEvent e) {} |
||
| 455 | public void internalFrameDeactivated(InternalFrameEvent e) {} |
||
| 456 | } |
||
| 457 | } |
||
| 458 | |||
| 459 | |||
| 460 | /** |
||
| 461 | * Program entry point. |
||
| 462 | * @param args The command line arguments. |
||
| 463 | */ |
||
| 464 | public static void main(String[] args) { |
||
| 465 | String configFile = "Config\\Kernel.xml"; |
||
| 466 | //config file can also be specified with command line args |
||
| 467 | if (args.length>0) { |
||
| 468 | configFile = args[0]; |
||
| 469 | } |
||
| 470 | //create new kernel |
||
| 471 | new GUIKernel(configFile); |
||
| 472 | } |
||
| 473 | |||
| 474 | } |