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 }