001    /**
002     * Copyright (C) 2007-2008, Jens Lehmann
003     *
004     * This file is part of DL-Learner.
005     * 
006     * DL-Learner is free software; you can redistribute it and/or modify
007     * it under the terms of the GNU General Public License as published by
008     * the Free Software Foundation; either version 3 of the License, or
009     * (at your option) any later version.
010     *
011     * DL-Learner is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014     * GNU General Public License for more details.
015     *
016     * You should have received a copy of the GNU General Public License
017     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018     *
019     */
020    package org.dllearner.gui;
021    
022    import java.awt.BorderLayout;
023    import java.awt.Color;
024    import java.awt.Dimension;
025    import java.awt.Toolkit;
026    import java.awt.event.ActionEvent;
027    import java.awt.event.ActionListener;
028    import java.io.File;
029    import java.io.IOException;
030    import java.util.LinkedList;
031    import java.util.List;
032    
033    import javax.swing.JFileChooser;
034    import javax.swing.JFrame;
035    import javax.swing.JMenu;
036    import javax.swing.JMenuBar;
037    import javax.swing.JMenuItem;
038    import javax.swing.JTabbedPane;
039    import javax.swing.UIManager;
040    import javax.swing.UnsupportedLookAndFeelException;
041    import javax.swing.event.ChangeEvent;
042    import javax.swing.event.ChangeListener;
043    import javax.swing.filechooser.FileFilter;
044    
045    import org.apache.log4j.ConsoleAppender;
046    import org.apache.log4j.Level;
047    import org.apache.log4j.Logger;
048    import org.apache.log4j.SimpleLayout;
049    import org.dllearner.algorithms.refinement2.ROLComponent2;
050    import org.dllearner.core.Component;
051    import org.dllearner.core.KnowledgeSource;
052    import org.dllearner.core.LearningAlgorithm;
053    import org.dllearner.core.LearningProblem;
054    import org.dllearner.core.ReasonerComponent;
055    import org.dllearner.kb.OWLAPIOntology;
056    import org.dllearner.kb.OWLFile;
057    import org.dllearner.learningproblems.PosNegLPStandard;
058    import org.dllearner.reasoning.FastInstanceChecker;
059    
060    /**
061     * This class builds the basic GUI elements and is used to start the DL-Learner
062     * GUI.
063     * 
064     * @author Tilo Hielscher
065     * @author Jens Lehmann
066     */
067    public class StartGUI extends JFrame implements ActionListener {
068    
069            private static final long serialVersionUID = -739265982906533775L;
070    
071            private static Logger logger = Logger.getLogger(StartGUI.class);        
072            private JTabbedPane tabPane = new JTabbedPane();
073    
074            private Config config = new Config(this);
075    
076    //      private ConfigLoad configLoad = new ConfigLoad(config, this);
077    //      private ConfigSave configSave = new ConfigSave(config, this);
078    
079            // the four component panels
080            protected ComponentPanel[] panels = new ComponentPanel[4];
081            protected RunPanel runPanel;
082            private int currentPanelIndex = 0;
083            
084    //      protected KnowledgeSourcePanel tab0;
085    //      protected ReasonerPanel tab1;
086    //      protected LearningProblemPanel tab2;
087    //      protected LearningAlgorithmPanel tab3;
088    
089            private JMenuBar menuBar = new JMenuBar();
090            private JMenu menuFile = new JMenu("File");
091            private JMenuItem openItem = new JMenuItem("Open Conf File ...");
092            private JMenuItem saveItem = new JMenuItem("Save As Conf File ...");
093            private JMenuItem exitItem = new JMenuItem("Exit");
094            private JMenu menuHelp = new JMenu("Help");
095            private JMenuItem aboutItem = new JMenuItem("About");
096            private JMenuItem tutorialItem = new JMenuItem("Quick Tutorial");
097    
098            private StatusPanel statusPanel = new StatusPanel();
099            
100            public StartGUI() {
101                    this(null);
102            }
103    
104            public StartGUI(File file) {
105                    this.setTitle("DL-Learner GUI");
106                    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
107    //              this.setLocationByPlatform(true);
108                    this.setSize(800, 600);
109    
110                    // center frame
111                    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
112                    Dimension size = getSize();
113                    screenSize.height = screenSize.height/2;
114                    screenSize.width = screenSize.width/2;
115                    size.height = size.height/2;
116                    size.width = size.width/2;
117                    int y = screenSize.height - size.height;
118                    int x = screenSize.width - size.width;
119                    setLocation(x, y);
120    
121                    // set icon
122                    if (this.getClass().getResource("icon.gif") != null)
123                            setIconImage(java.awt.Toolkit.getDefaultToolkit().getImage(
124                                            this.getClass().getResource("icon.gif")));
125    
126                    // create panels
127                    List<Class<? extends Component>> ignoredKnowledgeSources = new LinkedList<Class<? extends Component>>();
128                    ignoredKnowledgeSources.add(OWLAPIOntology.class);
129                    panels[0] = new ComponentPanel(config, this, KnowledgeSource.class, OWLFile.class, ignoredKnowledgeSources);
130                    panels[1] = new ComponentPanel(config, this, ReasonerComponent.class, FastInstanceChecker.class);
131                    panels[2] = new ComponentPanel(config, this, LearningProblem.class, PosNegLPStandard.class);
132                    panels[3] = new ComponentPanel(config, this, LearningAlgorithm.class, ROLComponent2.class);
133                    runPanel = new RunPanel(config, this);          
134                    
135                    // add tabs for panels
136                    tabPane.addTab("Knowledge Source", panels[0]);
137                    tabPane.addTab("Reasoner", panels[1]);
138                    tabPane.addTab("Learning Problem", panels[2]);
139                    tabPane.addTab("Learning Algorithm", panels[3]);
140                    tabPane.addTab("Run", runPanel);
141                    
142                    /*
143                    tab0 = new KnowledgeSourcePanel(config, this);
144                    tab1 = new ReasonerPanel(config, this);
145                    tab2 = new LearningProblemPanel(config, this);
146                    tab3 = new LearningAlgorithmPanel(config, this);
147                    tab4 = new RunPanel(config, this);
148                    tabPane.addTab("Knowledge Source", tab0);
149                    tabPane.addTab("Reasoner", tab1);
150                    tabPane.addTab("Learning Problem", tab2);
151                    tabPane.addTab("Learning Algorithm", tab3);
152                    tabPane.addTab("Run", tab4);
153                    */
154    
155                    setJMenuBar(menuBar);
156                    menuBar.add(menuFile);
157                    menuFile.add(openItem);
158                    openItem.addActionListener(this);
159                    menuFile.add(saveItem);
160                    saveItem.addActionListener(this);
161                    menuFile.add(exitItem);
162                    exitItem.addActionListener(this);
163                    menuBar.add(menuHelp);
164                    menuHelp.add(tutorialItem);
165                    tutorialItem.addActionListener(this);
166                    menuHelp.add(aboutItem);
167                    aboutItem.addActionListener(this);
168    
169                    add(tabPane, BorderLayout.CENTER);
170                    add(statusPanel, BorderLayout.SOUTH);
171                    setVisible(true);
172                    updateTabs();
173    
174                    // load file
175                    if(file != null) {
176                            config.loadFile(file);
177                    }
178                    
179                    // Register a change listener
180                    tabPane.addChangeListener(new ChangeListener() {
181                            // This method is called whenever the selected tab changes
182                            public void stateChanged(ChangeEvent evt) {
183                                    if (evt.getSource().equals(tabPane)) {
184    
185                                            int index = tabPane.getSelectedIndex();
186    //                                      System.out.println(index);
187                                            
188                                            // a list of all components (0 = knowledge source,
189                                            // 1 = reasoner etc.) which have to be initialised;
190                                            // the user can init several components at once
191                                            List<Integer> componentsToInit = new LinkedList<Integer>();
192                                            // check whether we need to initialise components
193                                            if (index != 0 && config.tabNeedsInit(index - 1)) {
194                                                    for (int i = 0; i < index; i++) {
195                                                            if(config.tabNeedsInit(i)) {
196                                                                    componentsToInit.add(i);
197                                                            }
198                                                    }
199                                            }
200                                            config.init(componentsToInit);
201    
202                                            currentPanelIndex = index;
203                                            updateTabs();
204                                            updateStatusPanel();
205                                            
206                                            // send signals to panels
207                                            switch(index) {
208                                            case 0: panels[0].panelActivated(); break;
209                                            case 1: panels[1].panelActivated(); break;
210                                            case 2: panels[2].panelActivated(); break;
211                                            case 3: panels[3].panelActivated(); break;
212                                            }
213    
214                                            
215                                            
216                                    }
217                            }
218                    });
219    
220    //              if (file != null) {
221    //                      configLoad.openFile(file);
222    //                      configLoad.startParser();
223    //              }
224            }
225    
226            /*
227            public void init() {
228                    tab0.init();
229                    tab1.init();
230                    tab2.init();
231                    tab3.init();
232                    updateTabColors();
233            }*/
234    
235            public void updateStatusPanel() {
236                    // new tab selected => generate an appropriate status message
237                    // (e.g. user has to fill in values)
238                    if(currentPanelIndex == 4) {
239                            statusPanel.setRunPanelMessage();
240                    } else {
241                            if(config.mandatoryOptionsSpecified(panels[currentPanelIndex].getCurrentComponent())) {
242                                    statusPanel.setTabCompleteMessage();
243                            } else {
244                                    statusPanel.setTabInitMessage();
245                            }
246                    }               
247            }
248            
249            public static void main(String[] args) {
250                    // create GUI logger
251                    SimpleLayout layout = new SimpleLayout();
252                    ConsoleAppender consoleAppender = new ConsoleAppender(layout);
253                    Logger rootLogger = Logger.getRootLogger();
254                    rootLogger.removeAllAppenders();
255                    rootLogger.addAppender(consoleAppender);
256                    rootLogger.setLevel(Level.DEBUG);
257    
258                    File file = null;
259                    if (args.length > 0)
260                            file = new File(args[args.length - 1]);
261    
262                    // force platform look and feel
263                    try {
264                            UIManager.setLookAndFeel(
265                                            UIManager.getCrossPlatformLookAndFeelClassName());
266    //                       "com.sun.java.swing.plaf.motif.MotifLookAndFeel");
267    //                                      UIManager.getSystemLookAndFeelClassName());
268                            // TODO: currently everything is in bold on Linux (and Win?)
269                    } catch (ClassNotFoundException e) {
270                            e.printStackTrace();
271                    } catch (InstantiationException e) {
272                            e.printStackTrace();
273                    } catch (IllegalAccessException e) {
274                            e.printStackTrace();
275                    } catch (UnsupportedLookAndFeelException e) {
276                            e.printStackTrace();
277                    }
278    
279                    new StartGUI(file);
280            }
281    
282            public void actionPerformed(ActionEvent e) {
283                    // open config file
284                    if (e.getSource() == openItem) {
285                            // file dialog
286                            JFileChooser fc = new ExampleFileChooser("conf");
287                            if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
288                                    logger.info("Loading file " + fc.getSelectedFile() + ".");
289                                    config.loadFile(fc.getSelectedFile());
290    //                              configLoad.openFile(fc.getSelectedFile());
291    //                              configLoad.startParser();
292                            }
293                            // save as config file
294                    } else if (e.getSource() == saveItem) {
295                            JFileChooser fc = new JFileChooser(new File("examples/"));
296                            // FileFilter only *.conf
297                            fc.addChoosableFileFilter(new FileFilter() {
298                                    @Override
299                                    public boolean accept(File f) {
300                                            if (f.isDirectory())
301                                                    return true;
302                                            return f.getName().toLowerCase().endsWith(".conf");
303                                    }
304    
305                                    @Override
306                                    public String getDescription() {
307                                            return "*.conf"; // name for filter
308                                    }
309                            });
310                            if (fc.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
311                                    File file = fc.getSelectedFile();
312                                    // returns name without path to it
313                                    String name= file.getName();
314                                    // if there is no extension, we append .conf
315                                    if(!name.contains(".")) {
316                                            file = new File(file.getAbsolutePath() + ".conf");
317                                    }
318                                    logger.info("Saving current configuration to " + file + ".");
319                                    ConfigSave save = new ConfigSave(config);
320                                    try {
321                                            save.saveFile(file);
322                                    } catch (IOException e1) {
323                                            // TODO Auto-generated catch block
324                                            e1.printStackTrace();
325                                    }
326                            }
327                            // exit
328                    } else if (e.getSource() == exitItem) {
329                            dispose();
330                            // tutorial
331                    } else if (e.getSource() == tutorialItem) {
332                            TutorialWindow window = new TutorialWindow();
333                            window.setLocationRelativeTo(this);
334                            // about
335                    } else if (e.getSource() == aboutItem) {
336                            AboutWindow window = new AboutWindow();
337                            window.setLocationRelativeTo(this);
338                    }
339            }
340    
341            /**
342             * Update colors of tabulators; red should be clicked, black for OK.
343             */
344            public void updateTabs() {
345                    for(int i=0; i<4; i++) {
346                            // red = needs init, black = initialised
347                            if(config.tabNeedsInit(i)) {
348                                    tabPane.setForegroundAt(i, Color.RED);
349                            } else {
350                                    tabPane.setForegroundAt(i, Color.BLACK);
351                            }
352                            
353                            // only enable tabs, which can be selected
354                            // (note the i+1: knowledge source always enabled)
355                            tabPane.setEnabledAt(i+1, config.isEnabled(i));                 
356                    }
357                    
358                    // run panel is enabled if all mandatory algorithm parameters have been set 
359    //              tabPane.setEnabledAt(4, config.isEnabled(4));
360                    
361    //              if (config.needsInitKnowledgeSource())
362    //                      tabPane.setForegroundAt(0, Color.RED);
363    //              else
364    //                      tabPane.setForegroundAt(0, Color.BLACK);
365    //              if (config.needsInitReasoner())
366    //                      tabPane.setForegroundAt(1, Color.RED);
367    //              else
368    //                      tabPane.setForegroundAt(1, Color.BLACK);
369    //              if (config.needsInitLearningProblem())
370    //                      tabPane.setForegroundAt(2, Color.RED);
371    //              else
372    //                      tabPane.setForegroundAt(2, Color.BLACK);
373    //              if (config.needsInitLearningAlgorithm()) {
374    //                      tabPane.setForegroundAt(3, Color.RED);
375    //                      tabPane.setForegroundAt(4, Color.RED);
376    //              } else {
377    //                      tabPane.setForegroundAt(3, Color.BLACK);
378    //                      tabPane.setForegroundAt(4, Color.BLACK);
379    //              }
380    
381                    // commented out as I do not see any reason why the method should update
382                    // everything
383                    // (it costs performance to update everything when the user only sees
384                    // one panel)
385                    // tab0.updateAll();
386                    // tab1.updateAll();
387                    // tab2.updateAll();
388                    // tab3.updateAll();
389    
390            }
391            
392            // freeze tab
393            public void disableTabbedPane() {
394                    tabPane.setEnabled(false);
395            }
396            
397            public void enableTabbedPane() {
398                    tabPane.setEnabled(true);
399            }
400            
401            public void setStatusMessage(String message) {
402                    statusPanel.setStatus(message);
403            }
404    
405            /**
406             * @return the statusPanel
407             */
408            public StatusPanel getStatusPanel() {
409                    return statusPanel;
410            }
411    }