source: src/main/java/weka/gui/Main.java @ 24

Last change on this file since 24 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 57.8 KB
Line 
1/*
2 *    This program is free software; you can redistribute it and/or modify
3 *    it under the terms of the GNU General Public License as published by
4 *    the Free Software Foundation; either version 2 of the License, or
5 *    (at your option) any later version.
6 *
7 *    This program is distributed in the hope that it will be useful,
8 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *    GNU General Public License for more details.
11 *
12 *    You should have received a copy of the GNU General Public License
13 *    along with this program; if not, write to the Free Software
14 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 * Main.java
19 * Copyright (C) 2006 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23package weka.gui;
24
25import weka.classifiers.bayes.net.GUI;
26import weka.classifiers.evaluation.ThresholdCurve;
27import weka.core.Copyright;
28import weka.core.Instances;
29import weka.core.Memory;
30import weka.core.Option;
31import weka.core.OptionHandler;
32import weka.core.SelectedTag;
33import weka.core.SystemInfo;
34import weka.core.Tag;
35import weka.core.Utils;
36import weka.core.Version;
37import weka.core.scripting.Groovy;
38import weka.core.scripting.Jython;
39import weka.gui.arffviewer.ArffViewerMainPanel;
40import weka.gui.beans.KnowledgeFlowApp;
41import weka.gui.beans.StartUpListener;
42import weka.gui.boundaryvisualizer.BoundaryVisualizer;
43import weka.gui.experiment.Experimenter;
44import weka.gui.explorer.Explorer;
45import weka.gui.graphvisualizer.GraphVisualizer;
46import weka.gui.scripting.GroovyPanel;
47import weka.gui.scripting.JythonPanel;
48import weka.gui.sql.SqlViewer;
49import weka.gui.treevisualizer.Node;
50import weka.gui.treevisualizer.NodePlace;
51import weka.gui.treevisualizer.PlaceNode2;
52import weka.gui.treevisualizer.TreeBuild;
53import weka.gui.treevisualizer.TreeVisualizer;
54import weka.gui.visualize.PlotData2D;
55import weka.gui.visualize.ThresholdVisualizePanel;
56import weka.gui.visualize.VisualizePanel;
57
58import java.awt.BorderLayout;
59import java.awt.Color;
60import java.awt.Component;
61import java.awt.Container;
62import java.awt.Dimension;
63import java.awt.Graphics;
64import java.awt.GridLayout;
65import java.awt.Image;
66import java.awt.LayoutManager;
67import java.awt.Point;
68import java.awt.Toolkit;
69import java.awt.event.ActionEvent;
70import java.awt.event.ActionListener;
71import java.awt.event.WindowAdapter;
72import java.awt.event.WindowEvent;
73import java.io.BufferedReader;
74import java.io.File;
75import java.io.FileInputStream;
76import java.io.FileReader;
77import java.io.Reader;
78import java.util.Collections;
79import java.util.Enumeration;
80import java.util.HashSet;
81import java.util.Hashtable;
82import java.util.Iterator;
83import java.util.Vector;
84
85import javax.swing.BorderFactory;
86import javax.swing.ImageIcon;
87import javax.swing.JDesktopPane;
88import javax.swing.JFileChooser;
89import javax.swing.JFrame;
90import javax.swing.JInternalFrame;
91import javax.swing.JLabel;
92import javax.swing.JMenu;
93import javax.swing.JMenuBar;
94import javax.swing.JMenuItem;
95import javax.swing.JOptionPane;
96import javax.swing.JPanel;
97import javax.swing.JScrollPane;
98import javax.swing.JSeparator;
99import javax.swing.JTable;
100import javax.swing.SwingConstants;
101import javax.swing.WindowConstants;
102import javax.swing.event.InternalFrameAdapter;
103import javax.swing.event.InternalFrameEvent;
104
105/**
106 * Menu-based GUI for Weka, replacement for the GUIChooser.
107 *
108 <!-- options-start -->
109 * Valid options are: <p/>
110 *
111 * <pre> -gui &lt;MDI|SDI&gt;
112 *  Determines the layout of the GUI:
113 *  MDI = MDI Layout
114 *  SDI = SDI Layout
115 *  (default: MDI)</pre>
116 *
117 <!-- options-end -->
118 *
119 * @author  fracpete (fracpete at waikato dot ac dot nz)
120 * @version $Revision: 5837 $
121 */
122public class Main
123  extends JFrame
124  implements OptionHandler {
125 
126  /** for serialization. */
127  private static final long serialVersionUID = 1453813254824253849L;
128 
129  /**
130   * DesktopPane with background image.
131   *
132   * @author  fracpete (fracpete at waikato dot ac dot nz)
133   * @version $Revision: 5837 $
134   */
135  public static class BackgroundDesktopPane
136    extends JDesktopPane {
137   
138    /** for serialization. */
139    private static final long serialVersionUID = 2046713123452402745L;
140   
141    /** the actual background image. */
142    protected Image m_Background;
143   
144    /**
145     * intializes the desktop pane.
146     *
147     * @param image     the image to use as background
148     */
149    public BackgroundDesktopPane(String image) {
150      super();
151     
152      try {
153        m_Background = Toolkit.getDefaultToolkit().getImage(ClassLoader.getSystemResource(image));
154      }
155      catch (Exception e) {
156        e.printStackTrace();
157      }
158    }
159   
160    /**
161     * draws the background image.
162     *
163     * @param g         the graphics context
164     */
165    public void paintComponent(Graphics g) {
166      super.paintComponent(g);
167     
168      if (m_Background != null) {
169        g.setColor(Color.WHITE);
170        g.clearRect(0, 0, getWidth(), getHeight());
171       
172        int width  = m_Background.getWidth(null);
173        int height = m_Background.getHeight(null);
174        int x = (getWidth() - width) / 2;
175        int y = (getHeight() - height) / 2;
176        g.drawImage(m_Background, x, y, width, height, this);
177      }
178    }
179  }
180 
181  /**
182   * Specialized JFrame class.
183   *
184   * @author  fracpete (fracpete at waikato dot ac dot nz)
185   * @version $Revision: 5837 $
186   */
187  public static class ChildFrameSDI 
188    extends JFrame {
189   
190    /** for serialization. */
191    private static final long serialVersionUID = 8588293938686425618L;
192   
193    /** the parent frame. */
194    protected Main m_Parent;
195   
196    /**
197     * constructs a new internal frame that knows about its parent.
198     *
199     * @param parent    the parent frame
200     * @param title     the title of the frame
201     */
202    public ChildFrameSDI(Main parent, String title) {
203      super(title);
204     
205      m_Parent = parent;
206
207      addWindowListener(new WindowAdapter() {
208        public void windowActivated(WindowEvent e) {
209          // update title of parent
210          if (getParentFrame() != null)
211            getParentFrame().createTitle(getTitle());
212        }
213      });
214     
215      // add to parent
216      if (getParentFrame() != null) {
217        getParentFrame().addChildFrame(this);
218        setIconImage(getParentFrame().getIconImage());
219      }
220    }
221   
222    /**
223     * returns the parent frame, can be null.
224     *
225     * @return          the parent frame
226     */
227    public Main getParentFrame() {
228      return m_Parent;
229    }
230   
231    /**
232     * de-registers the child frame with the parent first.
233     */
234    public void dispose() {
235      if (getParentFrame() != null) {
236        getParentFrame().removeChildFrame(this);
237        getParentFrame().createTitle("");
238      }
239     
240      super.dispose();
241    }
242  }
243 
244  /**
245   * Specialized JInternalFrame class.
246   *
247   * @author  fracpete (fracpete at waikato dot ac dot nz)
248   * @version $Revision: 5837 $
249   */
250  public static class ChildFrameMDI
251    extends JInternalFrame {
252   
253    /** for serialization. */
254    private static final long serialVersionUID = 3772573515346899959L;
255   
256    /** the parent frame. */
257    protected Main m_Parent;
258   
259    /**
260     * constructs a new internal frame that knows about its parent.
261     *
262     * @param parent    the parent frame
263     * @param title     the title of the frame
264     */
265    public ChildFrameMDI(Main parent, String title) {
266      super(title, true, true, true, true);
267     
268      m_Parent = parent;
269
270      addInternalFrameListener(new InternalFrameAdapter() {
271        public void internalFrameActivated(InternalFrameEvent e) {
272          // update title of parent
273          if (getParentFrame() != null)
274            getParentFrame().createTitle(getTitle());
275        }
276      });
277     
278      // add to parent
279      if (getParentFrame() != null) {
280        getParentFrame().addChildFrame(this);
281        getParentFrame().jDesktopPane.add(this);
282      }
283    }
284   
285    /**
286     * returns the parent frame, can be null.
287     *
288     * @return          the parent frame
289     */
290    public Main getParentFrame() {
291      return m_Parent;
292    }
293   
294    /**
295     * de-registers the child frame with the parent first.
296     */
297    public void dispose() {
298      if (getParentFrame() != null) {
299        getParentFrame().removeChildFrame(this);
300        getParentFrame().createTitle("");
301      }
302     
303      super.dispose();
304    }
305  }
306
307  /** displays the GUI as MDI. */
308  public final static int GUI_MDI = 0;
309  /** displays the GUI as SDI. */
310  public final static int GUI_SDI = 1;
311  /** GUI tags. */
312  public static final Tag[] TAGS_GUI = {
313    new Tag(GUI_MDI, "MDI", "MDI Layout"),
314    new Tag(GUI_SDI, "SDI", "SDI Layout")
315  };
316 
317  /** the frame itself. */
318  protected Main m_Self;
319 
320  /** the type of GUI to display. */
321  protected int m_GUIType = GUI_MDI;
322 
323  /** variable for the Main class which would be set to null by the memory
324   *  monitoring thread to free up some memory if we running out of memory. */
325  protected static Main m_MainCommandline;
326 
327  /** singleton instance of the GUI. */
328  protected static Main m_MainSingleton;
329
330  /** list of things to be notified when the startup process of
331   *  the KnowledgeFlow is complete. */
332  protected static Vector m_StartupListeners = new Vector();
333
334  /** for monitoring the Memory consumption. */
335  protected static Memory m_Memory = new Memory(true);
336 
337  /** contains the child frames (title &lt;-&gt; object). */
338  protected HashSet<Container> m_ChildFrames = new HashSet<Container>();
339
340  /** The frame of the LogWindow. */
341  protected static LogWindow m_LogWindow = new LogWindow();
342
343  /** filechooser for the TreeVisualizer. */
344  protected JFileChooser m_FileChooserTreeVisualizer = new JFileChooser(new File(System.getProperty("user.dir")));
345
346  /** filechooser for the GraphVisualizer. */
347  protected JFileChooser m_FileChooserGraphVisualizer = new JFileChooser(new File(System.getProperty("user.dir")));
348
349  /** filechooser for Plots. */
350  protected JFileChooser m_FileChooserPlot = new JFileChooser(new File(System.getProperty("user.dir")));
351
352  /** filechooser for ROC curves. */
353  protected JFileChooser m_FileChooserROC = new JFileChooser(new File(System.getProperty("user.dir")));
354 
355  // GUI components
356  private JMenu jMenuHelp;
357  private JMenu jMenuVisualization;
358  private JMenu jMenuTools;
359  private JDesktopPane jDesktopPane;
360  private JMenu jMenuApplications;
361  private JMenuItem jMenuItemHelpSystemInfo;
362  private JMenuItem jMenuItemHelpAbout;
363  private JMenuItem jMenuItemHelpHomepage;
364  private JMenuItem jMenuItemHelpWekaWiki;
365  private JMenuItem jMenuItemHelpWekaDoc;
366  private JMenuItem jMenuItemHelpSourceforge;
367  private JMenuItem jMenuItemVisualizationBoundaryVisualizer;
368  private JMenuItem jMenuItemVisualizationGraphVisualizer;
369  private JMenuItem jMenuItemVisualizationTreeVisualizer;
370  private JMenuItem jMenuItemVisualizationROC;
371  private JMenuItem jMenuItemVisualizationPlot;
372  private JMenuItem jMenuItemToolsEnsembleLibrary;
373  private JMenuItem jMenuItemToolsSqlViewer;
374  private JMenuItem jMenuItemToolsGroovyConsole;
375  private JMenuItem jMenuItemToolsJythonConsole;
376  private JMenuItem jMenuItemToolsArffViewer;
377  private JMenuItem jMenuItemApplicationsSimpleCLI;
378  private JMenuItem jMenuItemApplicationsKnowledgeFlow;
379  private JMenuItem jMenuItemApplicationsExperimenter;
380  private JMenuItem jMenuItemApplicationsExplorer;
381  private JMenuItem jMenuItemProgramExit;
382  private JMenuItem jMenuItemProgramLogWindow;
383  private JMenuItem jMenuItemProgramMemoryUsage;
384  private JMenuItem jMenuItemProgramPreferences;  // TODO: see below
385  private JMenu jMenuProgram;
386  private JMenu jMenuExtensions;
387  private JMenu jMenuWindows;
388  private JMenuBar jMenuBar;
389 
390  /**
391   * default constructor.
392   */
393  public Main() {
394    super();
395  }
396 
397  /**
398   * creates a frame (depending on m_GUIType) and returns it.
399   *
400   * @param parent              the parent of the generated frame
401   * @param title               the title of the frame
402   * @param c                   the component to place, can be null
403   * @param layout              the layout to use, e.g., BorderLayout
404   * @param layoutConstraints   the layout constraints, e.g., BorderLayout.CENTER
405   * @param width               the width of the frame, ignored if -1
406   * @param height              the height of the frame, ignored if -1
407   * @param menu                an optional menu
408   * @param listener            if true a default listener is added
409   * @param visible             if true then the frame is made visible immediately
410   * @return                    the generated frame
411   * @see                       #m_GUIType
412   */
413  protected Container createFrame(
414      Main parent, String title, Component c, LayoutManager layout, 
415      Object layoutConstraints, int width, int height, JMenuBar menu,
416      boolean listener, boolean visible) {
417
418    Container result = null;
419   
420    if (m_GUIType == GUI_MDI) {
421      final ChildFrameMDI frame = new ChildFrameMDI(parent, title);
422     
423      // layout
424      frame.setLayout(layout);
425      if (c != null)
426        frame.getContentPane().add(c, layoutConstraints);
427     
428      // menu
429      frame.setJMenuBar(menu);
430     
431      // size
432      frame.pack();
433      if ((width > -1) && (height > -1))
434        frame.setSize(width, height);
435      frame.validate();
436
437      // listener?
438      if (listener) {
439        frame.addInternalFrameListener(new InternalFrameAdapter() {
440          public void internalFrameClosing(InternalFrameEvent e) {
441            frame.dispose();
442          }
443        });
444      }
445     
446      // display frame
447      if (visible) {
448        frame.setVisible(true);
449        try {
450          frame.setSelected(true);
451        }
452        catch (Exception e) {
453          e.printStackTrace();
454        }
455      }
456     
457      result = frame;
458    }
459    else if (m_GUIType == GUI_SDI) {
460      final ChildFrameSDI frame = new ChildFrameSDI(parent, title);
461     
462      // layout
463      frame.setLayout(layout);
464      if (c != null)
465        frame.getContentPane().add(c, layoutConstraints);
466     
467      // menu
468      frame.setJMenuBar(menu);
469     
470      // size
471      frame.pack();
472      if ((width > -1) && (height > -1))
473        frame.setSize(width, height);
474      frame.validate();
475
476      // location
477      int screenHeight = getGraphicsConfiguration().getBounds().height;
478      int screenWidth  = getGraphicsConfiguration().getBounds().width;
479      frame.setLocation(
480          (screenWidth - frame.getBounds().width) / 2,
481          (screenHeight - frame.getBounds().height) / 2);
482     
483      // listener?
484      if (listener) {
485        frame.addWindowListener(new WindowAdapter() {
486          public void windowClosing(WindowEvent e) {
487            frame.dispose();
488          }
489        });
490      }
491     
492      // display frame
493      if (visible)
494        frame.setVisible(true);
495
496      result = frame;
497    }
498   
499    return result;
500  }
501 
502  /**
503   * insert the menu item in a sorted fashion.
504   *
505   * @param menu        the menu to add the item to
506   * @param menuitem    the menu item to add
507   */
508  protected void insertMenuItem(JMenu menu, JMenuItem menuitem) {
509    insertMenuItem(menu, menuitem, 0);
510  }
511 
512  /**
513   * insert the menu item in a sorted fashion.
514   *
515   * @param menu        the menu to add the item to
516   * @param menuitem    the menu item to add
517   * @param startIndex  the index in the menu to start with (0-based)
518   */
519  protected void insertMenuItem(JMenu menu, JMenuItem menuitem, int startIndex) {
520    boolean     inserted;
521    int         i;
522    JMenuItem   current;
523    String      currentStr;
524    String      newStr;
525   
526    inserted = false;
527    newStr   = menuitem.getText().toLowerCase();
528   
529    // try to find a spot inbetween
530    for (i = startIndex; i < menu.getMenuComponentCount(); i++) {
531      if (!(menu.getMenuComponent(i) instanceof JMenuItem))
532        continue;
533     
534      current    = (JMenuItem) menu.getMenuComponent(i);
535      currentStr = current.getText().toLowerCase();
536      if (currentStr.compareTo(newStr) > 0) {
537        inserted = true;
538        menu.insert(menuitem, i);
539        break;
540      }
541    }
542   
543    // add it at the end if not yet inserted
544    if (!inserted)
545      menu.add(menuitem);
546  }
547 
548  /**
549   * initializes the GUI.
550   */
551  protected void initGUI() {
552    m_Self = this;
553   
554    try {
555      // main window
556      createTitle("");
557      this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
558      this.setIconImage(new ImageIcon(getClass().getClassLoader().getResource("weka/gui/weka_icon.gif")).getImage());
559
560      // bits and pieces
561      m_FileChooserGraphVisualizer.addChoosableFileFilter(
562          new ExtensionFileFilter(".bif", "BIF Files (*.bif)"));
563      m_FileChooserGraphVisualizer.addChoosableFileFilter(
564          new ExtensionFileFilter(".xml", "XML Files (*.xml)"));
565
566      m_FileChooserPlot.addChoosableFileFilter(
567          new ExtensionFileFilter(
568              Instances.FILE_EXTENSION,
569              "ARFF Files (*" + Instances.FILE_EXTENSION + ")"));
570      m_FileChooserPlot.setMultiSelectionEnabled(true);
571
572      m_FileChooserROC.addChoosableFileFilter(
573          new ExtensionFileFilter(
574              Instances.FILE_EXTENSION,
575              "ARFF Files (*" + Instances.FILE_EXTENSION + ")"));
576
577      // Desktop
578      if (m_GUIType == GUI_MDI) {
579        jDesktopPane = new BackgroundDesktopPane("weka/gui/images/weka_background.gif");
580        jDesktopPane.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
581        setContentPane(jDesktopPane);
582      }
583      else {
584        jDesktopPane = null;
585      }
586
587      // Menu
588      jMenuBar = new JMenuBar();
589      setJMenuBar(jMenuBar);
590
591      // Program
592      jMenuProgram = new JMenu();
593      jMenuBar.add(jMenuProgram);
594      jMenuProgram.setText("Program");
595      jMenuProgram.setMnemonic('P');
596
597      // Program/Preferences
598      // TODO: read all properties from all props file and display them
599      /*
600        jMenuItemProgramPreferences = new JMenuItem();
601        jMenuProgram.add(jMenuItemProgramPreferences);
602        jMenuItemProgramPreferences.setText("Preferences");
603        jMenuItemProgramPreferences.setMnemonic('P');
604        jMenuItemProgramPreferences.addActionListener(new ActionListener() {
605          public void actionPerformed(ActionEvent evt) {
606            System.out.println("jMenuItemProgramPreferences.actionPerformed, event="+evt);
607            //TODO add your code for jMenuItemProgramPreferences.actionPerformed
608          }
609        });
610       */
611
612      // Program/LogWindow
613      jMenuItemProgramLogWindow = new JMenuItem();
614      jMenuProgram.add(jMenuItemProgramLogWindow);
615      jMenuItemProgramLogWindow.setText("LogWindow");
616      jMenuItemProgramLogWindow.setMnemonic('L');
617      jMenuItemProgramLogWindow.addActionListener(new ActionListener() {
618        public void actionPerformed(ActionEvent evt) {
619          m_LogWindow.setVisible(true);
620        }
621      });
622     
623      jMenuItemProgramMemoryUsage = new JMenuItem();
624      jMenuProgram.add(jMenuItemProgramMemoryUsage);
625      jMenuItemProgramMemoryUsage.setText("Memory usage");
626      jMenuItemProgramMemoryUsage.setMnemonic('M');
627      jMenuItemProgramMemoryUsage.addActionListener(new ActionListener() {
628        public void actionPerformed(ActionEvent evt) {
629          String title = jMenuItemProgramMemoryUsage.getText();
630          if (!containsWindow(title)) {
631            final MemoryUsagePanel panel = new MemoryUsagePanel();
632            Container c = createFrame(
633                m_Self, title, panel, new BorderLayout(), 
634                BorderLayout.CENTER, 400, 50, null, true, true);
635           
636            // optimize size
637            Dimension size = c.getPreferredSize();
638            c.setSize(new Dimension((int) size.getWidth(), (int) size.getHeight()));
639
640            // stop threads
641            if (m_GUIType == GUI_MDI) {
642              final ChildFrameMDI frame = (ChildFrameMDI) c;
643              Point l = panel.getFrameLocation();
644              if ((l.x != -1) && (l.y != -1))
645                frame.setLocation(l);
646              frame.addInternalFrameListener(new InternalFrameAdapter() {
647                public void internalFrameClosing(InternalFrameEvent e) {
648                  panel.stopMonitoring();
649                }
650              });
651            }
652            else {
653              final ChildFrameSDI frame = (ChildFrameSDI) c;
654              Point l = panel.getFrameLocation();
655              if ((l.x != -1) && (l.y != -1))
656                frame.setLocation(l);
657              frame.addWindowListener(new WindowAdapter() {
658                public void windowClosing(WindowEvent e) {
659                  panel.stopMonitoring();
660                }
661              });
662            }
663          }
664          else {
665            showWindow(getWindow(title));
666          }
667        }
668      });
669
670      jMenuProgram.add(new JSeparator());
671
672      // Program/Exit
673      jMenuItemProgramExit = new JMenuItem();
674      jMenuProgram.add(jMenuItemProgramExit);
675      jMenuItemProgramExit.setText("Exit");
676      jMenuItemProgramExit.setMnemonic('E');
677      jMenuItemProgramExit.addActionListener(new ActionListener() {     
678        public void actionPerformed(ActionEvent evt) {
679          // close all children
680          Iterator iter = getWindowList();
681          Vector<Container> list = new Vector<Container>();
682          while (iter.hasNext())
683            list.add((Container) iter.next());
684          for (int i = 0; i < list.size(); i++) {
685            Container c = list.get(i);
686            if (c instanceof ChildFrameMDI)
687              ((ChildFrameMDI) c).dispose();
688            else if (c instanceof ChildFrameSDI)
689              ((ChildFrameSDI) c).dispose();
690          }
691          // close logwindow
692          m_LogWindow.dispose();
693          // close main window
694          m_Self.dispose();
695          // make sure we stop
696          System.exit(0);
697        }
698      });
699
700      // Applications
701      jMenuApplications = new JMenu();
702      jMenuBar.add(jMenuApplications);
703      jMenuApplications.setText("Applications");
704      jMenuApplications.setMnemonic('A');
705
706      // Applications/Explorer
707      jMenuItemApplicationsExplorer = new JMenuItem();
708      jMenuApplications.add(jMenuItemApplicationsExplorer);
709      jMenuItemApplicationsExplorer.setText("Explorer");
710      jMenuItemApplicationsExplorer.setMnemonic('E');
711      jMenuItemApplicationsExplorer.addActionListener(new ActionListener() {
712        public void actionPerformed(ActionEvent evt) {
713          String title = jMenuItemApplicationsExplorer.getText();
714          if (!containsWindow(title)) {
715            createFrame(
716                m_Self, title, new Explorer(), new BorderLayout(), 
717                BorderLayout.CENTER, 800, 600, null, true, true);
718          }
719          else {
720            showWindow(getWindow(title));
721          }
722        }
723      });
724
725      // Applications/Experimenter
726      jMenuItemApplicationsExperimenter = new JMenuItem();
727      jMenuApplications.add(jMenuItemApplicationsExperimenter);
728      jMenuItemApplicationsExperimenter.setText("Experimenter");
729      jMenuItemApplicationsExperimenter.setMnemonic('X');
730      jMenuItemApplicationsExperimenter.addActionListener(new ActionListener() {
731        public void actionPerformed(ActionEvent evt) {
732          String title = jMenuItemApplicationsExperimenter.getText();
733          if (!containsWindow(title)) {
734            createFrame(
735                m_Self, title, new Experimenter(false), new BorderLayout(), 
736                BorderLayout.CENTER, 800, 600, null, true, true);
737          }
738          else {
739            showWindow(getWindow(title));
740          }
741        }
742      });
743
744      // Applications/KnowledgeFlow
745      jMenuItemApplicationsKnowledgeFlow = new JMenuItem();
746      jMenuApplications.add(jMenuItemApplicationsKnowledgeFlow);
747      jMenuItemApplicationsKnowledgeFlow.setText("KnowledgeFlow");
748      jMenuItemApplicationsKnowledgeFlow.setMnemonic('K');
749      jMenuItemApplicationsKnowledgeFlow.addActionListener(new ActionListener() {
750        public void actionPerformed(ActionEvent evt) {
751          String title = jMenuItemApplicationsKnowledgeFlow.getText();
752          if (!containsWindow(title)) {
753            KnowledgeFlowApp.createSingleton(new String[0]);
754            createFrame(
755                m_Self, title, KnowledgeFlowApp.getSingleton(), new BorderLayout(), 
756                BorderLayout.CENTER, 900, 600, null, true, true);
757          }
758          else {
759            showWindow(getWindow(title));
760          }
761        }
762      });
763
764      // Applications/SimpleCLI
765      jMenuItemApplicationsSimpleCLI = new JMenuItem();
766      jMenuApplications.add(jMenuItemApplicationsSimpleCLI);
767      jMenuItemApplicationsSimpleCLI.setText("SimpleCLI");
768      jMenuItemApplicationsSimpleCLI.setMnemonic('S');
769      jMenuItemApplicationsSimpleCLI.addActionListener(new ActionListener() {
770        public void actionPerformed(ActionEvent evt) {
771          String title = jMenuItemApplicationsSimpleCLI.getText();
772          if (!containsWindow(title)) {
773            try {
774              createFrame(
775                  m_Self, title, new SimpleCLIPanel(), new BorderLayout(), 
776                  BorderLayout.CENTER, 600, 500, null, true, true);
777            }
778            catch (Exception e) {
779              e.printStackTrace();
780              JOptionPane.showMessageDialog(
781                  m_Self, "Error instantiating SimpleCLI:\n" + e.getMessage());
782              return;
783            }
784          }
785          else {
786            showWindow(getWindow(title));
787          }
788        }
789      });
790
791      // Tools
792      jMenuTools = new JMenu();
793      jMenuBar.add(jMenuTools);
794      jMenuTools.setText("Tools");
795      jMenuTools.setMnemonic('T');
796
797      // Tools/ArffViewer
798      jMenuItemToolsArffViewer = new JMenuItem();
799      jMenuTools.add(jMenuItemToolsArffViewer);
800      jMenuItemToolsArffViewer.setText("ArffViewer");
801      jMenuItemToolsArffViewer.setMnemonic('A');
802      jMenuItemToolsArffViewer.addActionListener(new ActionListener() {
803        public void actionPerformed(ActionEvent evt) {
804          String title = jMenuItemToolsArffViewer.getText();
805          if (!containsWindow(title)) {
806            ArffViewerMainPanel panel = new ArffViewerMainPanel(null);
807            panel.setConfirmExit(false);
808            Container frame = createFrame(
809                m_Self, title, panel, new BorderLayout(), 
810                BorderLayout.CENTER, 800, 600, panel.getMenu(), true, true);
811            panel.setParent(frame);
812          }
813          else {
814            showWindow(getWindow(title));
815          }
816        }
817      });
818
819      // Tools/SqlViewer
820      jMenuItemToolsSqlViewer = new JMenuItem();
821      jMenuTools.add(jMenuItemToolsSqlViewer);
822      jMenuItemToolsSqlViewer.setText("SqlViewer");
823      jMenuItemToolsSqlViewer.setMnemonic('S');
824      jMenuItemToolsSqlViewer.addActionListener(new ActionListener() {
825        public void actionPerformed(ActionEvent evt) {
826          String title = jMenuItemToolsSqlViewer.getText();
827          if (!containsWindow(title)) {
828            final SqlViewer sql = new SqlViewer(null);
829            final Container frame = createFrame(
830                m_Self, title, sql, new BorderLayout(), 
831                BorderLayout.CENTER, -1, -1, null, false, true);
832
833            // custom listener
834            if (frame instanceof ChildFrameMDI) {
835              ((ChildFrameMDI) frame).addInternalFrameListener(new InternalFrameAdapter() {
836                public void internalFrameClosing(InternalFrameEvent e) {
837                  sql.saveSize();
838                  ((ChildFrameMDI) frame).dispose();
839                }
840              });
841            }
842            else if (frame instanceof ChildFrameSDI) {
843              ((ChildFrameSDI) frame).addWindowListener(new WindowAdapter() {
844                public void windowClosing(WindowEvent e) {
845                  sql.saveSize();
846                  ((ChildFrameSDI) frame).dispose();
847                }
848              });
849            }
850          }
851          else {
852            showWindow(getWindow(title));
853          }
854        }
855      });
856     
857      // Tools/Bayes net editor
858      // Tools/Bayes net editor
859      final JMenuItem jMenuItemBayesNet = new JMenuItem();
860      jMenuTools.add(jMenuItemBayesNet);
861      jMenuItemBayesNet.setText("Bayes net editor");
862      jMenuItemBayesNet.setMnemonic('N');
863
864      jMenuItemBayesNet.addActionListener(new ActionListener() {
865        public void actionPerformed(ActionEvent e) {
866          String title = jMenuItemBayesNet.getText();
867         
868          if (!containsWindow(title)) {
869            final GUI bayesNetGUI = new GUI();
870            final Container frame = createFrame(
871                m_Self, title, bayesNetGUI, new BorderLayout(), 
872                BorderLayout.CENTER, 800, 600, bayesNetGUI.getMenuBar(), false, true);
873          }
874          else {
875            showWindow(getWindow(title));
876          }         
877        }       
878      });
879
880      // Tools/Groovy console
881      if (Groovy.isPresent()) {
882        jMenuItemToolsGroovyConsole = new JMenuItem();
883        jMenuTools.add(jMenuItemToolsGroovyConsole);
884        jMenuItemToolsGroovyConsole.setText("Groovy console");
885        jMenuItemToolsGroovyConsole.setMnemonic('G');
886        jMenuItemToolsGroovyConsole.addActionListener(new ActionListener() {
887          public void actionPerformed(ActionEvent evt) {
888            String title = jMenuItemToolsGroovyConsole.getText();
889            if (!containsWindow(title)) {
890              final GroovyPanel panel = new GroovyPanel();
891              final Container frame = createFrame(
892                  m_Self, title, panel, new BorderLayout(), 
893                  BorderLayout.CENTER, 800, 600, panel.getMenuBar(), false, true);
894
895              // custom listener
896              if (frame instanceof ChildFrameMDI) {
897                ((ChildFrameMDI) frame).addInternalFrameListener(new InternalFrameAdapter() {
898                  public void internalFrameClosing(InternalFrameEvent e) {
899                    ((ChildFrameMDI) frame).dispose();
900                  }
901                });
902              }
903              else if (frame instanceof ChildFrameSDI) {
904                ((ChildFrameSDI) frame).addWindowListener(new WindowAdapter() {
905                  public void windowClosing(WindowEvent e) {
906                    ((ChildFrameSDI) frame).dispose();
907                  }
908                });
909              }
910            }
911            else {
912              showWindow(getWindow(title));
913            }
914          }
915        });
916      }
917
918      // Tools/Jython console
919      if (Jython.isPresent()) {
920        jMenuItemToolsJythonConsole = new JMenuItem();
921        jMenuTools.add(jMenuItemToolsJythonConsole);
922        jMenuItemToolsJythonConsole.setText("Jython console");
923        jMenuItemToolsJythonConsole.setMnemonic('J');
924        jMenuItemToolsJythonConsole.addActionListener(new ActionListener() {
925          public void actionPerformed(ActionEvent evt) {
926            String title = jMenuItemToolsJythonConsole.getText();
927            if (!containsWindow(title)) {
928              final JythonPanel panel = new JythonPanel();
929              final Container frame = createFrame(
930                  m_Self, title, panel, new BorderLayout(), 
931                  BorderLayout.CENTER, 800, 600, panel.getMenuBar(), false, true);
932
933              // custom listener
934              if (frame instanceof ChildFrameMDI) {
935                ((ChildFrameMDI) frame).addInternalFrameListener(new InternalFrameAdapter() {
936                  public void internalFrameClosing(InternalFrameEvent e) {
937                    ((ChildFrameMDI) frame).dispose();
938                  }
939                });
940              }
941              else if (frame instanceof ChildFrameSDI) {
942                ((ChildFrameSDI) frame).addWindowListener(new WindowAdapter() {
943                  public void windowClosing(WindowEvent e) {
944                    ((ChildFrameSDI) frame).dispose();
945                  }
946                });
947              }
948            }
949            else {
950              showWindow(getWindow(title));
951            }
952          }
953      });
954      }
955
956      // Tools/EnsembleLibrary
957      /* currently disabled due to bugs... FracPete
958      jMenuItemToolsEnsembleLibrary = new JMenuItem();
959      jMenuTools.add(jMenuItemToolsEnsembleLibrary);
960      jMenuItemToolsEnsembleLibrary.setText("EnsembleLibrary");
961      jMenuItemToolsEnsembleLibrary.setMnemonic('E');
962      jMenuItemToolsEnsembleLibrary.addActionListener(new ActionListener() {
963        public void actionPerformed(ActionEvent evt) {
964          String title = jMenuItemToolsEnsembleLibrary.getText();
965          if (!containsWindow(title)) {
966            EnsembleLibrary value = new EnsembleLibrary();
967            EnsembleLibraryEditor libraryEditor = new EnsembleLibraryEditor();
968            libraryEditor.setValue(value);
969            createFrame(
970                m_Self, title, libraryEditor.getCustomEditor(), new BorderLayout(),
971                BorderLayout.CENTER, 800, 600, null, true, true);
972          }
973          else {
974            showWindow(getWindow(title));
975          }
976        }
977      });
978      */
979
980      // Visualization
981      jMenuVisualization = new JMenu();
982      jMenuBar.add(jMenuVisualization);
983      jMenuVisualization.setText("Visualization");
984      jMenuVisualization.setMnemonic('V');
985
986      // Visualization/Plot
987      jMenuItemVisualizationPlot = new JMenuItem();
988      jMenuVisualization.add(jMenuItemVisualizationPlot);
989      jMenuItemVisualizationPlot.setText("Plot");
990      jMenuItemVisualizationPlot.setMnemonic('P');
991      jMenuItemVisualizationPlot.addActionListener(new ActionListener() {
992        public void actionPerformed(ActionEvent evt) {
993          // choose file
994          int retVal = m_FileChooserPlot.showOpenDialog(m_Self);
995          if (retVal != JFileChooser.APPROVE_OPTION)
996            return;
997
998          // build plot
999          VisualizePanel panel = new VisualizePanel();
1000          String filenames = "";
1001          File[] files = m_FileChooserPlot.getSelectedFiles();
1002          for (int j = 0; j < files.length; j++) {
1003            String filename = files[j].getAbsolutePath();
1004            if (j > 0)
1005              filenames += ", ";
1006            filenames += filename;
1007            System.err.println("Loading instances from " + filename);
1008            try {
1009              Reader r = new java.io.BufferedReader(new FileReader(filename));
1010              Instances i = new Instances(r);
1011              i.setClassIndex(i.numAttributes()-1);
1012              PlotData2D pd1 = new PlotData2D(i);
1013
1014              if (j == 0) {
1015                pd1.setPlotName("Master plot");
1016                panel.setMasterPlot(pd1);
1017              } else {
1018                pd1.setPlotName("Plot "+(j+1));
1019                pd1.m_useCustomColour = true;
1020                pd1.m_customColour = (j % 2 == 0) ? Color.red : Color.blue; 
1021                panel.addPlot(pd1);
1022              }
1023            }
1024            catch (Exception e) {
1025              e.printStackTrace();
1026              JOptionPane.showMessageDialog(
1027                  m_Self, "Error loading file '" + files[j] + "':\n" + e.getMessage());
1028              return;
1029            }
1030          }
1031
1032          // create frame
1033          createFrame(
1034              m_Self, jMenuItemVisualizationPlot.getText() + " - " + filenames, 
1035              panel, new BorderLayout(), 
1036              BorderLayout.CENTER, 800, 600, null, true, true);
1037        }
1038      });
1039
1040      // Visualization/ROC
1041      // based on this Wiki article:
1042      // http://weka.sourceforge.net/wiki/index.php/Visualizing_ROC_curve
1043      jMenuItemVisualizationROC = new JMenuItem();
1044      jMenuVisualization.add(jMenuItemVisualizationROC);
1045      jMenuItemVisualizationROC.setText("ROC");
1046      jMenuItemVisualizationROC.setMnemonic('R');
1047      jMenuItemVisualizationROC.addActionListener(new ActionListener() {
1048        public void actionPerformed(ActionEvent evt) {
1049          // choose file
1050          int retVal = m_FileChooserROC.showOpenDialog(m_Self);
1051          if (retVal != JFileChooser.APPROVE_OPTION)
1052            return;
1053
1054          // create plot
1055          String filename  = m_FileChooserROC.getSelectedFile().getAbsolutePath();
1056          Instances result = null;
1057          try {
1058            result = new Instances(new BufferedReader(new FileReader(filename)));
1059          }
1060          catch (Exception e) {
1061            e.printStackTrace();
1062            JOptionPane.showMessageDialog(
1063                m_Self, "Error loading file '" + filename + "':\n" + e.getMessage());
1064            return;
1065          }
1066          result.setClassIndex(result.numAttributes() - 1);
1067          ThresholdVisualizePanel vmc = new ThresholdVisualizePanel();
1068          vmc.setROCString("(Area under ROC = " + 
1069              Utils.doubleToString(ThresholdCurve.getROCArea(result), 4) + ")");
1070          vmc.setName(result.relationName());
1071          PlotData2D tempd = new PlotData2D(result);
1072          tempd.setPlotName(result.relationName());
1073          tempd.addInstanceNumberAttribute();
1074          try {
1075            vmc.addPlot(tempd);
1076          }
1077          catch (Exception e) {
1078            e.printStackTrace();
1079            JOptionPane.showMessageDialog(
1080                m_Self, "Error adding plot:\n" + e.getMessage());
1081            return;
1082          }
1083
1084          createFrame(
1085              m_Self, jMenuItemVisualizationROC.getText() + " - " + filename, 
1086              vmc, new BorderLayout(), 
1087              BorderLayout.CENTER, 800, 600, null, true, true);
1088        }
1089      });
1090
1091      // Visualization/TreeVisualizer
1092      jMenuItemVisualizationTreeVisualizer = new JMenuItem();
1093      jMenuVisualization.add(jMenuItemVisualizationTreeVisualizer);
1094      jMenuItemVisualizationTreeVisualizer.setText("TreeVisualizer");
1095      jMenuItemVisualizationTreeVisualizer.setMnemonic('T');
1096      jMenuItemVisualizationTreeVisualizer.addActionListener(new ActionListener() {
1097        public void actionPerformed(ActionEvent evt) {
1098          // choose file
1099          int retVal = m_FileChooserTreeVisualizer.showOpenDialog(m_Self);
1100          if (retVal != JFileChooser.APPROVE_OPTION)
1101            return;
1102
1103          // build tree
1104          String filename = m_FileChooserTreeVisualizer.getSelectedFile().getAbsolutePath();
1105          TreeBuild builder = new TreeBuild();
1106          Node top = null;
1107          NodePlace arrange = new PlaceNode2();
1108          try {
1109            top = builder.create(new FileReader(filename));
1110          }
1111          catch (Exception e) {
1112            e.printStackTrace();
1113            JOptionPane.showMessageDialog(
1114                m_Self, "Error loading file '" + filename + "':\n" + e.getMessage());
1115            return;
1116          }
1117
1118          // create frame
1119          createFrame(
1120              m_Self, jMenuItemVisualizationTreeVisualizer.getText() + " - " + filename, 
1121              new TreeVisualizer(null, top, arrange), new BorderLayout(), 
1122              BorderLayout.CENTER, 800, 600, null, true, true);
1123        }
1124      });
1125
1126      // Visualization/GraphVisualizer
1127      jMenuItemVisualizationGraphVisualizer = new JMenuItem();
1128      jMenuVisualization.add(jMenuItemVisualizationGraphVisualizer);
1129      jMenuItemVisualizationGraphVisualizer.setText("GraphVisualizer");
1130      jMenuItemVisualizationGraphVisualizer.setMnemonic('G');
1131      jMenuItemVisualizationGraphVisualizer.addActionListener(new ActionListener() {
1132        public void actionPerformed(ActionEvent evt) {
1133          // choose file
1134          int retVal = m_FileChooserGraphVisualizer.showOpenDialog(m_Self);
1135          if (retVal != JFileChooser.APPROVE_OPTION)
1136            return;
1137
1138          // build graph
1139          String filename = m_FileChooserGraphVisualizer.getSelectedFile().getAbsolutePath();
1140          GraphVisualizer panel = new GraphVisualizer();
1141          try{
1142            if (    filename.toLowerCase().endsWith(".xml") 
1143                || filename.toLowerCase().endsWith(".bif") ) {
1144              panel.readBIF(new FileInputStream(filename));
1145            }
1146            else {
1147              panel.readDOT(new FileReader(filename));
1148            }
1149          }
1150          catch (Exception e) {
1151            e.printStackTrace();
1152            JOptionPane.showMessageDialog(
1153                m_Self, "Error loading file '" + filename + "':\n" + e.getMessage());
1154            return;
1155          }
1156
1157          // create frame
1158          createFrame(
1159              m_Self, jMenuItemVisualizationGraphVisualizer.getText() + " - " + filename, 
1160              panel, new BorderLayout(), 
1161              BorderLayout.CENTER, 800, 600, null, true, true);
1162        }
1163      });
1164
1165      // Visualization/BoundaryVisualizer
1166      jMenuItemVisualizationBoundaryVisualizer = new JMenuItem();
1167      jMenuVisualization.add(jMenuItemVisualizationBoundaryVisualizer);
1168      jMenuItemVisualizationBoundaryVisualizer.setText("BoundaryVisualizer");
1169      jMenuItemVisualizationBoundaryVisualizer.setMnemonic('B');
1170      jMenuItemVisualizationBoundaryVisualizer.addActionListener(new ActionListener() {
1171        public void actionPerformed(ActionEvent evt) {
1172          String title = jMenuItemVisualizationBoundaryVisualizer.getText();
1173          if (!containsWindow(title)) {
1174            createFrame(
1175                m_Self, title, new BoundaryVisualizer(), new BorderLayout(), 
1176                BorderLayout.CENTER, 800, 600, null, true, true);
1177            // dont' do a System.exit after last window got closed!
1178            BoundaryVisualizer.setExitIfNoWindowsOpen(false);
1179          }
1180          else {
1181            showWindow(getWindow(title));
1182          }
1183        }
1184      });
1185
1186      // Extensions
1187      jMenuExtensions = new JMenu("Extensions");
1188      jMenuExtensions.setMnemonic(java.awt.event.KeyEvent.VK_E);
1189      jMenuBar.add(jMenuExtensions);
1190      jMenuExtensions.setVisible(false);
1191
1192      String extensions = GenericObjectEditor.EDITOR_PROPERTIES.getProperty(
1193          MainMenuExtension.class.getName(), "");
1194
1195      if (extensions.length() > 0) {
1196        jMenuExtensions.setVisible(true);
1197        String[] classnames = GenericObjectEditor.EDITOR_PROPERTIES.getProperty(
1198            MainMenuExtension.class.getName(), "").split(",");
1199        Hashtable<String,JMenu> submenus = new Hashtable<String,JMenu>();
1200
1201        // add all extensions
1202        for (int i = 0; i < classnames.length; i++) {
1203          String classname = classnames[i];
1204          try {
1205            MainMenuExtension ext = (MainMenuExtension) Class.forName(classname).newInstance();
1206
1207            // menuitem in a submenu?
1208            JMenu submenu = null;
1209            if (ext.getSubmenuTitle() != null) {
1210              submenu = submenus.get(ext.getSubmenuTitle());
1211              if (submenu == null) {
1212                submenu = new JMenu(ext.getSubmenuTitle());
1213                submenus.put(ext.getSubmenuTitle(), submenu);
1214                insertMenuItem(jMenuExtensions, submenu);
1215              }
1216            }
1217
1218            // create menu item
1219            JMenuItem menuitem = new JMenuItem();
1220            menuitem.setText(ext.getMenuTitle());
1221            // does the extension need a frame or does it have its own ActionListener?
1222            ActionListener listener = ext.getActionListener(m_Self);
1223            if (listener != null) {
1224              menuitem.addActionListener(listener);
1225            }
1226            else {
1227              final JMenuItem finalMenuitem = menuitem;
1228              final MainMenuExtension finalExt = ext;
1229              menuitem.addActionListener(new ActionListener() {
1230                public void actionPerformed(ActionEvent e) {
1231                  Component frame = createFrame(
1232                      m_Self, finalMenuitem.getText(), 
1233                      null, null, null, -1, -1, null, false, false);
1234                  finalExt.fillFrame(frame);
1235                  frame.setVisible(true);
1236                }
1237              });
1238            }
1239
1240            // sorted insert of menu item
1241            if (submenu != null)
1242              insertMenuItem(submenu, menuitem);
1243            else
1244              insertMenuItem(jMenuExtensions, menuitem);
1245          }
1246          catch (Exception e) {
1247            e.printStackTrace();
1248          }
1249        }
1250      }
1251
1252      // Windows
1253      jMenuWindows = new JMenu("Windows");
1254      jMenuWindows.setMnemonic(java.awt.event.KeyEvent.VK_W);
1255      jMenuBar.add(jMenuWindows);
1256      jMenuWindows.setVisible(false);  // initially, there are no windows open
1257
1258      // Help
1259      jMenuHelp = new JMenu();
1260      jMenuBar.add(jMenuHelp);
1261      jMenuHelp.setText("Help");
1262      jMenuHelp.setMnemonic('H');
1263
1264      // Help/Homepage
1265      jMenuItemHelpHomepage = new JMenuItem();
1266      jMenuHelp.add(jMenuItemHelpHomepage);
1267      jMenuItemHelpHomepage.setText("Weka homepage");
1268      jMenuItemHelpHomepage.setMnemonic('H');
1269      jMenuItemHelpHomepage.addActionListener(new ActionListener() {
1270        public void actionPerformed(ActionEvent evt) {
1271          BrowserHelper.openURL(m_Self, "http://www.cs.waikato.ac.nz/~ml/weka/");
1272        }
1273      });
1274
1275      jMenuHelp.add(new JSeparator());
1276
1277/*      // Help/WekaDoc
1278      jMenuItemHelpWekaDoc = new JMenuItem();
1279      jMenuHelp.add(jMenuItemHelpWekaDoc);
1280      jMenuItemHelpWekaDoc.setText("Online documentation");
1281      jMenuItemHelpWekaDoc.setMnemonic('D');
1282      jMenuItemHelpWekaDoc.addActionListener(new ActionListener() {
1283        public void actionPerformed(ActionEvent evt) {
1284          BrowserHelper.openURL(m_Self, "http://weka.sourceforge.net/wekadoc/");
1285        }
1286      }); */
1287
1288      // Help/WekaWiki
1289      jMenuItemHelpWekaWiki = new JMenuItem();
1290      jMenuHelp.add(jMenuItemHelpWekaWiki);
1291      jMenuItemHelpWekaWiki.setText("HOWTOs, code snippets, etc.");
1292      jMenuItemHelpWekaWiki.setMnemonic('W');
1293      jMenuItemHelpWekaWiki.addActionListener(new ActionListener() {
1294        public void actionPerformed(ActionEvent evt) {
1295          BrowserHelper.openURL(m_Self, "http://weka.wikispaces.com/");
1296        }
1297      });
1298
1299      // Help/Sourceforge
1300      jMenuItemHelpSourceforge = new JMenuItem();
1301      jMenuHelp.add(jMenuItemHelpSourceforge);
1302      jMenuItemHelpSourceforge.setText("Weka on SourceForge");
1303      jMenuItemHelpSourceforge.setMnemonic('F');
1304      jMenuItemHelpSourceforge.addActionListener(new ActionListener() {
1305        public void actionPerformed(ActionEvent evt) {
1306          BrowserHelper.openURL(m_Self, "http://sourceforge.net/projects/weka/");
1307        }
1308      });
1309
1310      jMenuHelp.add(new JSeparator());
1311
1312      // Help/SystemInfo
1313      jMenuItemHelpSystemInfo = new JMenuItem();
1314      jMenuHelp.add(jMenuItemHelpSystemInfo);
1315      jMenuItemHelpSystemInfo.setText("SystemInfo");
1316      jMenuItemHelpHomepage.setMnemonic('S');
1317      jMenuItemHelpSystemInfo.addActionListener(new ActionListener() {
1318        public void actionPerformed(ActionEvent evt) {
1319          String title = jMenuItemHelpSystemInfo.getText();
1320          if (!containsWindow(title)) {
1321            // get info
1322            Hashtable info = new SystemInfo().getSystemInfo();
1323
1324            // sort names
1325            Vector names = new Vector();
1326            Enumeration enm = info.keys();
1327            while (enm.hasMoreElements())
1328              names.add(enm.nextElement());
1329            Collections.sort(names);
1330
1331            // generate table
1332            String[][] data = new String[info.size()][2];
1333            for (int i = 0; i < names.size(); i++) {
1334              data[i][0] = names.get(i).toString();
1335              data[i][1] = info.get(data[i][0]).toString();
1336            }
1337            String[] titles = new String[]{"Key", "Value"};
1338            JTable table = new JTable(data, titles);
1339
1340            createFrame(
1341                m_Self, title, new JScrollPane(table), new BorderLayout(), 
1342                BorderLayout.CENTER, 800, 600, null, true, true);
1343          }
1344          else {
1345            showWindow(getWindow(title));
1346          }
1347        }
1348      });
1349
1350      jMenuHelp.add(new JSeparator());
1351
1352      // Help/About
1353      jMenuItemHelpAbout = new JMenuItem();
1354      jMenuHelp.add(jMenuItemHelpAbout);
1355      jMenuItemHelpAbout.setText("About");
1356      jMenuItemHelpAbout.setMnemonic('A');
1357      jMenuItemHelpAbout.addActionListener(new ActionListener() {
1358        public void actionPerformed(ActionEvent evt) {
1359          String title = jMenuItemHelpAbout.getText();
1360          if (!containsWindow(title)) {
1361            JPanel wekaPan = new JPanel();
1362            wekaPan.setToolTipText("Weka, a native bird of New Zealand");
1363            ImageIcon wii = new ImageIcon(Toolkit.getDefaultToolkit().getImage(ClassLoader.getSystemResource("weka/gui/weka3.gif")));
1364            JLabel wekaLab = new JLabel(wii);
1365            wekaPan.add(wekaLab);
1366            Container frame = createFrame(
1367                m_Self, title, wekaPan, new BorderLayout(), 
1368                BorderLayout.CENTER, -1, -1, null, true, true);
1369
1370            JPanel titlePan = new JPanel();
1371            titlePan.setLayout(new GridLayout(8,1));
1372            titlePan.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5));
1373            titlePan.add(new JLabel("Waikato Environment for", SwingConstants.CENTER));
1374            titlePan.add(new JLabel("Knowledge Analysis", SwingConstants.CENTER));
1375            titlePan.add(new JLabel(""));
1376            titlePan.add(new JLabel("Version " + Version.VERSION, SwingConstants.CENTER));
1377            titlePan.add(new JLabel(""));
1378            titlePan.add(new JLabel("(c) " + Copyright.getFromYear() + " - " + Copyright.getToYear(), SwingConstants.CENTER));
1379            titlePan.add(new JLabel(Copyright.getOwner(), SwingConstants.CENTER));
1380            titlePan.add(new JLabel(Copyright.getAddress(), SwingConstants.CENTER));
1381
1382            if (frame instanceof ChildFrameMDI) {
1383              ((ChildFrameMDI) frame).getContentPane().add(titlePan, BorderLayout.NORTH);
1384              ((ChildFrameMDI) frame).pack();
1385            }
1386            else if (frame instanceof ChildFrameSDI) {
1387              ((ChildFrameSDI) frame).getContentPane().add(titlePan, BorderLayout.NORTH);
1388              ((ChildFrameSDI) frame).pack();
1389            }
1390          }
1391          else {
1392            showWindow(getWindow(title));
1393          }
1394        }
1395      });
1396
1397      // size + position
1398      int screenHeight = getGraphicsConfiguration().getBounds().height;
1399      int screenWidth  = getGraphicsConfiguration().getBounds().width;
1400      if (m_GUIType == GUI_MDI) {
1401        int newHeight = (int) (((double) screenHeight) * 0.75);
1402        int newWidth  = (int) (((double) screenWidth)  * 0.75);
1403        setSize(
1404            1000 > newWidth  ? newWidth  : 1000,
1405                800  > newHeight ? newHeight : 800);
1406        setLocation(
1407            (screenWidth - getBounds().width) / 2,
1408            (screenHeight - getBounds().height) / 2);
1409      }
1410      else if (m_GUIType == GUI_SDI) {
1411        pack();
1412        setSize(screenWidth, getHeight());
1413        setLocation(0, 0);
1414      }
1415    } 
1416    catch (Exception e) {
1417      e.printStackTrace();
1418    }
1419  }
1420 
1421  /**
1422   * creates and displays the title.
1423   *
1424   * @param title       the additional part of the title
1425   */
1426  protected void createTitle(String title) {
1427    String      newTitle;
1428   
1429    newTitle = "Weka " + new Version();
1430    if (title.length() != 0)
1431      newTitle += " - " + title;
1432   
1433    setTitle(newTitle);
1434  }
1435 
1436  /**
1437   * adds the given child frame to the list of frames.
1438   *
1439   * @param c           the child frame to add
1440   */
1441  public void addChildFrame(Container c) {
1442    m_ChildFrames.add(c);
1443    windowListChanged();
1444  }
1445 
1446  /**
1447   * tries to remove the child frame, it returns true if it could do such.
1448   *
1449   * @param c           the child frame to remove
1450   * @return            true if the child frame could be removed
1451   */
1452  public boolean removeChildFrame(Container c) {
1453    boolean result = m_ChildFrames.remove(c);
1454    windowListChanged();
1455    return result;
1456  }
1457 
1458  /**
1459   * brings child frame to the top.
1460   *
1461   * @param c           the frame to activate
1462   * @return            true if frame was activated
1463   */
1464  public boolean showWindow(Container c) {
1465    boolean             result;
1466    ChildFrameMDI       mdiFrame;
1467    ChildFrameSDI       sdiFrame;
1468   
1469    if (c != null) {
1470      try {
1471        if (c instanceof ChildFrameMDI) {
1472          mdiFrame = (ChildFrameMDI) c;
1473          mdiFrame.setIcon(false);
1474          mdiFrame.toFront();
1475          createTitle(mdiFrame.getTitle());
1476        }
1477        else if (c instanceof ChildFrameSDI) {
1478          sdiFrame = (ChildFrameSDI) c;
1479          sdiFrame.setExtendedState(JFrame.NORMAL);
1480          sdiFrame.toFront();
1481          createTitle(sdiFrame.getTitle());
1482        }
1483      }
1484      catch (Exception e) {
1485        e.printStackTrace();
1486      }
1487      result = true;
1488    }
1489    else {
1490      result = false;
1491    }
1492   
1493    return result;
1494  }
1495 
1496  /**
1497   * brings the first frame to the top that is of the specified
1498   * window class.
1499   * 
1500   * @param windowClass the class to display the first child for
1501   * @return            true, if a child was found and brought to front
1502   */
1503  public boolean showWindow(Class windowClass) {
1504    return showWindow(getWindow(windowClass));
1505  }
1506 
1507  /**
1508   * returns all currently open frames.
1509   *
1510   * @return            an iterator over all currently open frame
1511   */
1512  public Iterator getWindowList() {
1513    return m_ChildFrames.iterator();
1514  }
1515
1516  /**
1517   * returns the first instance of the given window class, null if none can be
1518   * found.
1519   *
1520   * @param windowClass the class to retrieve the first instance for
1521   * @return            null, if no instance can be found
1522   */
1523  public Container getWindow(Class windowClass) {
1524    Container   result;
1525    Iterator    iter;
1526    Container   current;
1527   
1528    result = null;
1529    iter   = getWindowList();
1530    while (iter.hasNext()) {
1531      current = (Container) iter.next();
1532      if (current.getClass() == windowClass) {
1533        result = current;
1534        break;
1535      }
1536    }
1537   
1538    return result;
1539  }
1540
1541  /**
1542   * returns the first window with the given title, null if none can be
1543   * found.
1544   *
1545   * @param title       the title to look for
1546   * @return            null, if no instance can be found
1547   */
1548  public Container getWindow(String title) {
1549    Container   result;
1550    Iterator    iter;
1551    Container   current;
1552    boolean     found;
1553   
1554    result = null;
1555    iter   = getWindowList();
1556    while (iter.hasNext()) {
1557      current = (Container) iter.next();
1558      found   = false;
1559     
1560      if (current instanceof ChildFrameMDI)
1561        found = ((ChildFrameMDI) current).getTitle().equals(title);
1562      else if (current instanceof ChildFrameSDI)
1563        found = ((ChildFrameSDI) current).getTitle().equals(title);
1564       
1565      if (found) {
1566        result = current;
1567        break;
1568      }
1569    }
1570   
1571    return result;
1572  }
1573 
1574  /**
1575   * checks, whether an instance of the given window class is already in
1576   * the Window list.
1577   *
1578   * @param windowClass the class to check for an instance in the current
1579   *                    window list
1580   * @return            true if the class is already listed in the Window list
1581   */
1582  public boolean containsWindow(Class windowClass) {
1583    return (getWindow(windowClass) != null);
1584  }
1585 
1586  /**
1587   * checks, whether a window with the given title is already in
1588   * the Window list.
1589   *
1590   * @param title       the title to check for in the current window list
1591   * @return            true if a window with the given title is already
1592   *                    listed in the Window list
1593   */
1594  public boolean containsWindow(String title) {
1595    return (getWindow(title) != null);
1596  }
1597 
1598  /**
1599   * minimizes all windows.
1600   */
1601  public void minimizeWindows() {
1602    Iterator    iter;
1603    Container   frame;
1604   
1605    iter = getWindowList();
1606    while (iter.hasNext()) {
1607      frame = (Container) iter.next();
1608      try {
1609        if (frame instanceof ChildFrameMDI)
1610          ((ChildFrameMDI) frame).setIcon(true);
1611        else if (frame instanceof ChildFrameSDI)
1612          ((ChildFrameSDI) frame).setExtendedState(JFrame.ICONIFIED);
1613      }
1614      catch (Exception e) {
1615        e.printStackTrace();
1616      }
1617    }
1618  }
1619 
1620  /**
1621   * restores all windows.
1622   */
1623  public void restoreWindows() {
1624    Iterator    iter;
1625    Container   frame;
1626   
1627    iter = getWindowList();
1628    while (iter.hasNext()) {
1629      frame = (Container) iter.next();
1630      try {
1631        if (frame instanceof ChildFrameMDI)
1632          ((ChildFrameMDI) frame).setIcon(false);
1633        else if (frame instanceof ChildFrameSDI)
1634          ((ChildFrameSDI) frame).setExtendedState(JFrame.NORMAL);
1635    }
1636      catch (Exception e) {
1637        e.printStackTrace();
1638      }
1639    }
1640  }
1641 
1642  /**
1643   * is called when window list changed somehow (add or remove).
1644   */
1645  public void windowListChanged() {
1646    createWindowMenu();
1647  }
1648 
1649  /**
1650   * creates the menu of currently open windows.
1651   */
1652  protected synchronized void createWindowMenu() {
1653    Iterator          iter;
1654    JMenuItem         menuItem;
1655    int               startIndex;
1656   
1657    // remove all existing entries
1658    jMenuWindows.removeAll();
1659   
1660    // minimize + restore + separator
1661    menuItem = new JMenuItem("Minimize");
1662    menuItem.addActionListener(new ActionListener() {
1663      public void actionPerformed(ActionEvent evt) {
1664        minimizeWindows();
1665      }
1666    });
1667    jMenuWindows.add(menuItem);
1668   
1669    menuItem = new JMenuItem("Restore");
1670    menuItem.addActionListener(new ActionListener() {
1671      public void actionPerformed(ActionEvent evt) {
1672        restoreWindows();
1673      }
1674    });
1675    jMenuWindows.add(menuItem);
1676   
1677    jMenuWindows.addSeparator();
1678   
1679    // windows
1680    startIndex = jMenuWindows.getMenuComponentCount() - 1;
1681    iter = getWindowList();
1682    jMenuWindows.setVisible(iter.hasNext());
1683    while (iter.hasNext()) {
1684      Container frame = (Container) iter.next();
1685      if (frame instanceof ChildFrameMDI)
1686        menuItem = new JMenuItem(((ChildFrameMDI) frame).getTitle());
1687      else if (frame instanceof ChildFrameSDI)
1688        menuItem = new JMenuItem(((ChildFrameSDI) frame).getTitle());
1689      insertMenuItem(jMenuWindows, menuItem, startIndex);
1690      menuItem.setActionCommand(Integer.toString(frame.hashCode()));
1691      menuItem.addActionListener(new ActionListener() {
1692        public void actionPerformed(ActionEvent evt) {
1693          Container frame = null;
1694          Iterator iter = getWindowList();
1695          while (iter.hasNext()) {
1696            frame = (Container) iter.next();
1697            String hashFrame = Integer.toString(frame.hashCode());
1698            if (hashFrame.equals(evt.getActionCommand())) {
1699              showWindow(frame);
1700              break;
1701            }
1702          }
1703          showWindow(frame);
1704        }
1705      });
1706    }
1707  }
1708 
1709  /**
1710   * Shows or hides this component depending on the value of parameter b.
1711   *
1712   * @param b           if true, shows this component; otherwise, hides this
1713   *                    component
1714   */
1715  public void setVisible(boolean b) {
1716    super.setVisible(b);
1717   
1718    if (b)
1719      paint(this.getGraphics());
1720  }
1721 
1722  /**
1723   * Create the singleton instance of the Main GUI.
1724   *
1725   * @param args        commandline options
1726   */
1727  public static void createSingleton(String[] args) {
1728    if (m_MainSingleton == null)
1729      m_MainSingleton = new Main();
1730   
1731    // set options
1732    try {
1733      m_MainSingleton.setOptions(args);
1734    }
1735    catch (Exception e) {
1736      e.printStackTrace();
1737    }
1738
1739    // notify listeners (if any)
1740    for (int i = 0; i < m_StartupListeners.size(); i++)
1741      ((StartUpListener) m_StartupListeners.elementAt(i)).startUpComplete();
1742  }
1743
1744  /**
1745   * Return the singleton instance of the Main GUI.
1746   *
1747   * @return the singleton instance
1748   */
1749  public static Main getSingleton() {
1750    return m_MainSingleton;
1751  }
1752
1753  /**
1754   * Add a listener to be notified when startup is complete.
1755   *
1756   * @param s           a listener to add
1757   */
1758  public static void addStartupListener(StartUpListener s) {
1759    m_StartupListeners.add(s);
1760  }
1761
1762  /**
1763   * Gets an enumeration describing the available options.
1764   *
1765   * @return            an enumeration of all the available options.
1766   */
1767  public Enumeration listOptions(){
1768    Vector              result;
1769    String              desc;
1770    SelectedTag         tag;
1771    int                 i;
1772
1773    result = new Vector();
1774
1775    desc  = "";
1776    for (i = 0; i < TAGS_GUI.length; i++) {
1777      tag = new SelectedTag(TAGS_GUI[i].getID(), TAGS_GUI);
1778      desc  +=   "\t" + tag.getSelectedTag().getIDStr() 
1779               + " = " + tag.getSelectedTag().getReadable()
1780               + "\n";
1781    }
1782    result.addElement(new Option(
1783        "\tDetermines the layout of the GUI:\n"
1784        + desc
1785        + "\t(default: " + new SelectedTag(GUI_MDI, TAGS_GUI) + ")",
1786        "gui", 1, "-gui " + Tag.toOptionList(TAGS_GUI)));
1787
1788    return result.elements();
1789  }
1790 
1791  /**
1792   * returns the options of the current setup.
1793   *
1794   * @return            the current options
1795   */
1796  public String[] getOptions(){
1797    Vector<String>      result;
1798
1799    result = new Vector();
1800
1801    result.add("-gui");
1802    result.add("" + getGUIType());
1803
1804    return result.toArray(new String[result.size()]);     
1805  }
1806
1807  /**
1808   * Parses the options for this object. <p/>
1809   *
1810   <!-- options-start -->
1811   * Valid options are: <p/>
1812   *
1813   * <pre> -gui &lt;MDI|SDI&gt;
1814   *  Determines the layout of the GUI:
1815   *  MDI = MDI Layout
1816   *  SDI = SDI Layout
1817   *  (default: MDI)</pre>
1818   *
1819   <!-- options-end -->
1820   *
1821   * @param options     the options to use
1822   * @throws Exception  if setting of options fails
1823   */
1824  public void setOptions(String[] options) throws Exception {
1825    String      tmpStr;
1826
1827    tmpStr = Utils.getOption("gui", options);
1828    if (tmpStr.length() != 0)
1829      setGUIType(new SelectedTag(tmpStr, TAGS_GUI));
1830    else
1831      setGUIType(new SelectedTag(GUI_MDI, TAGS_GUI));
1832  }
1833
1834  /**
1835   * Sets the type of GUI to use.
1836   *
1837   * @param value       .the GUI type
1838   */
1839  public void setGUIType(SelectedTag value) {
1840    if (value.getTags() == TAGS_GUI) {
1841      m_GUIType = value.getSelectedTag().getID();
1842      initGUI();
1843    }
1844  }
1845
1846  /**
1847   * Gets the currently set type of GUI to display.
1848   *
1849   * @return            the current GUI Type.
1850   */
1851  public SelectedTag getGUIType() {
1852    return new SelectedTag(m_GUIType, TAGS_GUI);
1853  }
1854 
1855  /**
1856   * starts the application.
1857   *
1858   * @param args        the commandline arguments - ignored
1859   */
1860  public static void main(String[] args) {
1861    weka.core.logging.Logger.log(weka.core.logging.Logger.Level.INFO, "Logging started");
1862   
1863    LookAndFeel.setLookAndFeel();
1864   
1865    try {
1866      // uncomment the following line to disable the memory management:
1867      //m_Memory.setEnabled(false);
1868
1869      // help?
1870      if (Utils.getFlag('h', args)) {
1871        System.out.println();
1872        System.out.println("Help requested.");
1873        System.out.println();
1874        System.out.println("General options:");
1875        System.out.println();
1876        System.out.println("-h");
1877        System.out.println("\tprints this help screen");
1878        System.out.println();
1879
1880        Enumeration enu = new Main().listOptions();
1881        while (enu.hasMoreElements()) {
1882          Option option = (Option) enu.nextElement();
1883          System.out.println(option.synopsis());
1884          System.out.println(option.description());
1885        }
1886
1887        System.out.println();
1888        System.exit(0);
1889      }
1890     
1891      // setup splash screen
1892      Main.addStartupListener(new weka.gui.beans.StartUpListener() {
1893        public void startUpComplete() {
1894          m_MainCommandline = Main.getSingleton();
1895          m_MainCommandline.setVisible(true);
1896        }
1897      });
1898      Main.addStartupListener(new StartUpListener() {
1899        public void startUpComplete() {
1900          SplashWindow.disposeSplash();
1901        }
1902      });
1903      SplashWindow.splash(ClassLoader.getSystemResource("weka/gui/images/weka_splash.gif"));
1904
1905      // start GUI
1906      final String[] options = (String[]) args.clone();
1907      Thread nt = new Thread() {
1908        public void run() {
1909          weka.gui.SplashWindow.invokeMethod(
1910              Main.class.getName(), "createSingleton", options);
1911        }
1912      };
1913      nt.start();
1914     
1915      Thread memMonitor = new Thread() {
1916        public void run() {
1917          while(true) {
1918            try {
1919              Thread.sleep(4000);
1920              System.gc();
1921             
1922              if (m_Memory.isOutOfMemory()) {
1923                // clean up
1924                m_MainCommandline = null;
1925                System.gc();
1926               
1927                // stop threads
1928                m_Memory.stopThreads();
1929               
1930                // display error
1931                System.err.println("\ndisplayed message:");
1932                m_Memory.showOutOfMemory();
1933                System.err.println("\nexiting");
1934                System.exit(-1);
1935              }
1936             
1937            } catch(InterruptedException ex) { ex.printStackTrace(); }
1938          }
1939        }
1940      };
1941     
1942      memMonitor.setPriority(Thread.MAX_PRIORITY);
1943      memMonitor.start();
1944    }
1945    catch (Exception ex) {
1946      ex.printStackTrace();
1947      System.err.println(ex.getMessage());
1948    }
1949  }
1950}
Note: See TracBrowser for help on using the repository browser.