package aima.gui.swing.applications;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintStream;
import java.lang.reflect.Method;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import aima.gui.swing.framework.MessageLoggerPanel;
/**
* Provides a simple frame for starting agent applications and command line demos.
*
* @author Ruediger Lunde
*/
public class AimaDemoFrame extends JFrame {
private static final long serialVersionUID = 1L;
protected JMenuBar menubar = new JMenuBar();
JMenu appsMenu = new JMenu("Apps");
JMenu demosMenu = new JMenu("Demos");
MessageLoggerPanel textPanel = new MessageLoggerPanel();
JComponent currPanel;
PrintStream outStream;
/** Standard constructor. */
public AimaDemoFrame() {
setTitle("Artificial Intelligence a Modern Approach 3rd ed. Java Demos (AIMA3e-Java)");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setJMenuBar(menubar);
menubar.add(appsMenu);
menubar.add(demosMenu);
outStream = System.out;
}
/**
* Adds a new agent application to the menu. The class is expected to be
* part of a package and to provide a <code>constructApplicationFrame</code>
* method.
*/
public void addApp(Class<?> appClass) {
JMenuItem item = addDemoToMenu(appsMenu, appClass);
item.addActionListener(new AppStarter(appClass));
}
/**
* Adds a new command line demo to the menu. The class is expected to be
* part of a package and to provide a static main method.
*/
public void addDemo(Class<?> demoClass) {
JMenuItem item = addDemoToMenu(demosMenu, demoClass);
item.addActionListener(new DemoStarter(demoClass));
}
/**
* Adds a new program (agent application or command line demo) to the specified
* menu.
*/
private JMenuItem addDemoToMenu(JMenu menu, Class<?> progClass) {
JMenuItem item = new JMenuItem(progClass.getSimpleName());
JMenu subMenu = null;
String packageName = progClass.getPackage().getName();
Component[] menuComps = menu.getMenuComponents();
int i;
for (i = 0; i < menuComps.length; i++) {
JMenu comp = (JMenu) menuComps[i];
if (comp.getText().equals(packageName))
subMenu = comp;
else if (comp.getText().compareTo(packageName) > 0)
break;
}
if (subMenu == null) {
subMenu = new JMenu(packageName);
menu.add(subMenu, i);
}
subMenu.add(item);
return item;
}
// ///////////////////////////////////////////////////////////////
// inner classes
/**
* Implements an action listener which starts an agent application.
*
* @author Ruediger Lunde
*/
protected class AppStarter implements ActionListener {
Class<?> appClass;
AppStarter(Class<?> ac) {
appClass = ac;
}
@Override
public void actionPerformed(ActionEvent ev) {
try {
if (currPanel != null)
getContentPane().remove(currPanel);
System.setOut(outStream);
Object instance = appClass.newInstance();
Method m = appClass.getMethod("constructApplicationFrame",
new Class[0]);
JFrame af = (JFrame) m.invoke(instance, (Object[]) null);
currPanel = (JComponent) af.getContentPane().getComponent(0);
af.getContentPane().remove(currPanel);
getContentPane().add(currPanel, BorderLayout.CENTER);
validate();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Implements an action listener which starts a command line demo.
*
* @author Ruediger Lunde
*/
protected class DemoStarter implements ActionListener {
Class<?> demoClass;
DemoStarter(Class<?> dc) {
demoClass = dc;
}
@Override
public void actionPerformed(ActionEvent arg0) {
try {
if (currPanel == textPanel)
textPanel.clear();
else {
if (currPanel != null)
getContentPane().remove(currPanel);
getContentPane().add(textPanel, BorderLayout.CENTER);
// redirect the standard output into the text area
System.setOut(textPanel.getPrintStream());
// System.setErr(panel.getPrintStream());
validate();
currPanel = textPanel;
}
Method m = demoClass.getMethod("main", String[].class);
m.invoke(null, (Object) new String[] {});
} catch (Exception e) {
e.printStackTrace();
}
}
}
}