/*
* Created on Feb 6, 2004
*/
package org.jmatlab.swing.ui;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PushbackReader;
import java.io.StringReader;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Observable;
import java.util.Observer;
import java.util.Properties;
import java.util.Stack;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
import org.apache.commons.lang.StringUtils;
import org.jmatlab.compiler.LibraryManager;
import org.jmatlab.compiler.Main;
//import org.jmatlab.graphics.plot.PlplotInit;
import org.jmatlab.lexer.Lexer;
import org.jmatlab.linalg.ICell;
import org.jmatlab.linalg.IMatrix;
import org.jmatlab.node.Node;
import org.jmatlab.parser.Parser;
import org.jmatlab.semantic.DataType;
import org.jmatlab.semantic.Interpreter;
import org.jmatlab.semantic.Symbol;
import org.jmatlab.semantic.SymbolTable;
import org.jmatlab.util.Version;
/**
* @author Ali
*/
public class MainWin extends JFrame implements Observer {
private static final String HISTORY = "--- History ---";
private static final String prompt = ">> ";
private static Pattern p = Pattern.compile("[_0-9a-zA-Z]*");
private JMenuBar menuBar;
private JMenu fileMenu;
private JMenuItem openFileMenuItem;
private JMenuItem saveSessionMenuItem;
private JMenuItem loadSessionMenuItem;
private JMenuItem exitMenuItem;
private JMenu editMenu;
private JMenuItem copyMenuItem;
private JMenuItem pasteMenuItem;
private JMenu toolsMenu;
private JMenuItem jMethodMenuItem;
private JMenuItem mMethodMenuItem;
private JMenuItem executionMenuItem;
private JMenu algebraImplMenuItem;
private JRadioButtonMenuItem[] selectImplClass;
private JMenu actionMenu;
private JMenuItem clearSymbolTableMenuItem;
private JMenuItem executeHistoryMenuItem;
private JMenuItem clearHistoryMenuItem;
private JMenuItem runMenuItem;
private JMenu optionMenu;
private JMenuItem constantsMenuItem;
private JMenu helpMenu;
private JMenuItem aboutMenuItem;
private JFileChooser fileChooser;
private javax.swing.JPanel jContentPane;
private JPanel textPanel;
private InputTextArea inputArea;
private JSplitPane splitPane;
private JSplitPane debugPane;
private Stack execStack = new Stack();
private int lastPosition = 0;
private Properties tProp; /* Java methods in toolbox */
private Properties jProp; /* java methods*/
private Properties mProp; /* m-script methods */
private Properties eProp; /* execution module */
private Properties cProp; /* constants */
private LibraryManager lib;
private static Interpreter interpreter;
private Lexer lexer;
private Parser parser;
private JSplitPane wndPane;
private JTable detailTable;
private JList symbolList;
private DefaultListModel symbolListModel;
private DefaultListModel historyListModel;
private SymbolTable symbolTable;
private MatrixTableModel detailTableModel;
private JToolBar toolbar;
private JPanel statusPanel;
private JLabel lblStatus;
private String status;
public MainWin(SymbolTable symbolTable) {
super();
// PlplotInit.init();
this.symbolTable = symbolTable;
initialize();
}
private void initialize() {
String userDir = System.getProperty("user.home");
String configFileName = "jmethods-jmatlab.properties";
String configFile = userDir + File.separator + configFileName;
File file = new File(configFile);
InputStream in;
jProp = new Properties();
try {
in = new FileInputStream(configFile);
jProp.load(in);
} catch (FileNotFoundException e) {
// in = Main.class.getResourceAsStream(configFileName);
} catch (IOException e1) {
e1.printStackTrace();
}
configFileName = "toolboxes-jmatlab.properties";
file = new File(configFile);
tProp = new Properties();
try {
in = Main.class.getResourceAsStream(configFileName);
tProp.load(in);
} catch (FileNotFoundException e) {
} catch (IOException e1) {
e1.printStackTrace();
}
configFileName = "mmethods-jmatlab.properties";
configFile = userDir + File.separator + configFileName;
file = new File(configFile);
try {
in = new FileInputStream(configFile);
} catch (FileNotFoundException e) {
in = Main.class.getResourceAsStream(configFileName);
}
mProp = new Properties();
try {
mProp.load(in);
} catch (IOException e1) {
e1.printStackTrace();
}
configFileName = "execution-jmatlab.properties";
configFile = userDir + File.separator + configFileName;
file = new File(configFile);
try {
in = new FileInputStream(configFile);
} catch (FileNotFoundException e) {
in = Main.class.getResourceAsStream(configFileName);
}
eProp = new Properties();
try {
eProp.load(in);
} catch (IOException e1) {
e1.printStackTrace();
}
if (eProp.size()==0) {
in = Main.class.getResourceAsStream(configFileName);
try {
eProp.load(in);
} catch (IOException e1) {
e1.printStackTrace();
}
}
Enumeration enum = eProp.elements();
String implClass = null;
if (enum.hasMoreElements()) {
implClass = (String) enum.nextElement();
}
//loading mathematical constants properties
configFileName = "constants-jmatlab.properties";
configFile = userDir + File.separator + configFileName;
file = new File(configFile);
try {
in = new FileInputStream(configFile);
} catch (FileNotFoundException e) {
in = Main.class.getResourceAsStream(configFileName);
}
cProp = new Properties();
try {
cProp.load(in);
} catch(IOException e) {
e.printStackTrace();
}
if (cProp.size()==0) {
in = Main.class.getResourceAsStream(configFileName);
try {
cProp.load(in);
} catch (IOException e1) {
e1.printStackTrace();
}
}
//set constants in symbol table
symbolTable.setConstants(cProp);
URL icon = MainWin.class.getResource("icon.ico");
//TODO setIconImage((new ImageIcon(icon)).getImage());
this.lib = new LibraryManager(jProp, mProp, tProp);
ICell cell = Interpreter.getLinearAlgebraFactory().createCell();
symbolTable.setVariable("VARARGIN", cell);
interpreter = new Interpreter(lib, getInputArea(), symbolTable);
interpreter.setLinearAlgebraImpl(implClass);
this.setTitle("jMATLAB Command Window (Release Date: " + Version.RELEASE_DATE + ")");
this.setState(JFrame.MAXIMIZED_BOTH);
this.setContentPane(getJContentPane());
lastPosition += Version.banner().length();
inputArea.setText(Version.banner());
lastPosition += prompt.length();
inputArea.append(prompt);
inputArea.setCaretPosition(lastPosition);
// historyListModel.addElement(HISTORY);
this.setJMenuBar(getJJMenuBar());
}
private JToolBar getToolBar() {
if (toolbar == null) {
toolbar = new JToolBar();
JButton exitButton = new JButton();
URL imageURL = MainWin.class.getResource("Delete24.gif");
exitButton.setIcon(new ImageIcon(imageURL, "Exit"));
exitButton.setToolTipText("Exit CTRL+X");
exitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
toolbar.add(exitButton);
toolbar.addSeparator();
JButton saveSessionButton = new JButton();
imageURL = MainWin.class.getResource("down_arrow.gif");
saveSessionButton.setIcon(new ImageIcon(imageURL, "Save"));
saveSessionButton.setToolTipText("Save CTRL+S");
saveSessionButton.addActionListener(new SaveSessionActionListener(this));
toolbar.add(saveSessionButton);
JButton loadSessionButton = new JButton();
imageURL = MainWin.class.getResource("up_arrow.gif");
loadSessionButton.setIcon(new ImageIcon(imageURL, "Load"));
loadSessionButton.setToolTipText("Load CTRL+L");
loadSessionButton.addActionListener(new LoadSessionActionListener(this));
toolbar.add(loadSessionButton);
toolbar.addSeparator();
JButton execHistory = new JButton();
imageURL = MainWin.class.getResource("Refresh24.gif");
execHistory.setIcon(new ImageIcon(imageURL, "Execute History"));
execHistory.setToolTipText("Execute History CTRL+E");
execHistory.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
executeHistory();
}
});
toolbar.add(execHistory);
JButton cleanHistory = new JButton();
imageURL = MainWin.class.getResource("Cut24.gif");
cleanHistory.setIcon(new ImageIcon(imageURL, "Clean History"));
cleanHistory.setToolTipText("Clean History CTRL+D");
cleanHistory.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
clearHistory();
}
});
toolbar.add(cleanHistory);
toolbar.addSeparator();
JButton cleanVariables = new JButton();
imageURL = MainWin.class.getResource("Remove24.gif");
cleanVariables.setIcon(new ImageIcon(imageURL, "Clean Memory"));
cleanVariables.setToolTipText("Clean Memory CTRL+M");
cleanVariables.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
symbolTable.clear();
symbolListModel.clear();
}
});
toolbar.add(cleanVariables);
JButton runProgram = new JButton();
imageURL = MainWin.class.getResource("run_24x24.gif");
runProgram.setIcon(new ImageIcon(imageURL, "Run Program"));
runProgram.setToolTipText("Run Program CTRL+R");
runProgram.addActionListener(new RunProgramActionHandler(this));
toolbar.add(runProgram);
toolbar.addSeparator();
JButton helpButton = new JButton();
imageURL = MainWin.class.getResource("Information24.gif");
helpButton.setIcon(new ImageIcon(imageURL, "Help"));
helpButton.setToolTipText("Help CTRL+A");
helpButton.addActionListener(new AboutActionHandler(this));
toolbar.add(helpButton);
}
return toolbar;
}
private JMenuBar getJJMenuBar() {
if (menuBar==null) {
menuBar = new JMenuBar();
menuBar.add(getFileMenu());
menuBar.add(getEditMenu());
menuBar.add(getToolsMenu());
menuBar.add(getActionMenu());
menuBar.add(getOptionMenu());
menuBar.add(getHelpMenu());
}
return menuBar;
}
private JMenu getOptionMenu() {
if (optionMenu == null) {
optionMenu = new JMenu("Option");
optionMenu.setMnemonic(KeyEvent.VK_O);
optionMenu.add(getConstantsMenuItem());
}
return optionMenu;
}
private JMenuItem getConstantsMenuItem() {
if (constantsMenuItem == null) {
constantsMenuItem = new JMenuItem("Constants");
constantsMenuItem.setMnemonic(KeyEvent.VK_C);
constantsMenuItem.addActionListener(new LoadConstantsActionHandler(this));
}
return constantsMenuItem;
}
public class LoadConstantsActionHandler implements ActionListener {
private MainWin frame;
public LoadConstantsActionHandler(MainWin frame) {
this.frame = frame;
}
public void actionPerformed(ActionEvent event) {
String[] columns = {"Name", "Value"};
Object[][] out = TableDialog.showDialog(frame, cProp, "Constants", columns);
cProp.clear();
for (int i=0; i<out.length; i++) {
if (out[i][0]!=null && ((String)out[i][0]).trim().length()!=0 && out[i][1]!=null && ((String)out[i][1]).trim().length()!=0) {
cProp.setProperty(((String)out[i][0]).trim(), ((String)out[i][1]).trim());
}
}
String userDir = System.getProperty("user.home");
String configFileName = "constants-jmatlab.properties";
String configFile = userDir + File.separator + configFileName;
OutputStream ostream = null;
try {
ostream = new FileOutputStream(configFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
cProp.store(ostream, "");
ostream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
private JMenu getActionMenu() {
if (actionMenu==null) {
actionMenu = new JMenu("Action");
actionMenu.setMnemonic(KeyEvent.VK_A);
actionMenu.add(getClearSymbolTable());
actionMenu.addSeparator();
actionMenu.add(getExecuteHistoryMenuItem());
actionMenu.add(getClearHistoryMenuItem());
actionMenu.addSeparator();
actionMenu.add(getRunMenuItem());
}
return actionMenu;
}
private JMenuItem getClearSymbolTable() {
if (clearSymbolTableMenuItem == null) {
clearSymbolTableMenuItem = new JMenuItem("Clean Memory");
clearSymbolTableMenuItem.setMnemonic(KeyEvent.VK_M);
clearSymbolTableMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, KeyEvent.CTRL_MASK));
clearSymbolTableMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
symbolTable.clear();
symbolListModel.clear();
}
});
}
return clearSymbolTableMenuItem;
}
private JMenuItem getExecuteHistoryMenuItem() {
if (executeHistoryMenuItem==null) {
executeHistoryMenuItem = new JMenuItem("Execute History");
executeHistoryMenuItem.setMnemonic(KeyEvent.VK_E);
executeHistoryMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, KeyEvent.CTRL_MASK));
executeHistoryMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
executeHistory();
}
});
}
return executeHistoryMenuItem;
}
private void executeHistory() {
int index = historyList.getSelectedIndex();
if (index == 0) return;
String in = ((String) historyListModel.getElementAt(index)).replaceAll("\n", "");
inputArea.append(in);
executeCode(in);
lastPosition = inputArea.getText().length();
}
private JMenuItem getClearHistoryMenuItem() {
if (clearHistoryMenuItem==null) {
clearHistoryMenuItem = new JMenuItem("Clear History");
clearHistoryMenuItem.setMnemonic(KeyEvent.VK_C);
clearHistoryMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.CTRL_MASK));
clearHistoryMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
clearHistory();
}
});
}
return clearHistoryMenuItem;
}
private void clearHistory() {
historyListModel.removeAllElements();
historyListModel.addElement(HISTORY);
}
private JMenu getHelpMenu() {
if (helpMenu==null) {
helpMenu = new JMenu("Help");
helpMenu.addSeparator();
helpMenu.setMnemonic(KeyEvent.VK_H);
helpMenu.add(getAboutMenuItem());
}
return helpMenu;
}
public class AboutActionHandler implements ActionListener {
private JFrame frame;
AboutActionHandler(JFrame frame) {
this.frame = frame;
}
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(frame, "jMatlab Version 0.1");
}
}
private JMenuItem getAboutMenuItem() {
if (aboutMenuItem==null) {
aboutMenuItem = new JMenuItem("About");
aboutMenuItem.setMnemonic(KeyEvent.VK_A);
aboutMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_MASK));
aboutMenuItem.addActionListener(new AboutActionHandler(this));
}
return aboutMenuItem;
}
private JMenu getToolsMenu() {
if (toolsMenu==null) {
toolsMenu = new JMenu("Tools");
toolsMenu.setMnemonic(KeyEvent.VK_T);
toolsMenu.add(getJMethodMenuItem());
toolsMenu.add(getMMethodMenuItem());
toolsMenu.add(getExecutionMenuItem());
toolsMenu.addSeparator();
toolsMenu.add(getAlgebraMenuItem());
}
return toolsMenu;
}
private Component getMMethodMenuItem() {
if (mMethodMenuItem == null) {
mMethodMenuItem = new JMenuItem("Load m-script Method");
mMethodMenuItem.setMnemonic(KeyEvent.VK_M);
mMethodMenuItem.addActionListener(new LoadMMethodActionHandler(this));
}
return mMethodMenuItem;
}
private Component getJMethodMenuItem() {
if (jMethodMenuItem == null) {
jMethodMenuItem = new JMenuItem("Load Java Method");
jMethodMenuItem.setMnemonic(KeyEvent.VK_J);
jMethodMenuItem.addActionListener(new LoadJMethodActionHandler(this));
}
return jMethodMenuItem;
}
private Component getExecutionMenuItem() {
if (executionMenuItem == null) {
executionMenuItem = new JMenuItem("Load Execution Module");
executionMenuItem.setMnemonic(KeyEvent.VK_E);
executionMenuItem.addActionListener(new LoadExecutionActionHandler(this));
}
return executionMenuItem;
}
private JMenu getAlgebraMenuItem() {
algebraImplMenuItem = new JMenu("Load Impl Class");
algebraImplMenuItem.setMnemonic(KeyEvent.VK_L);
selectImplClass = new JRadioButtonMenuItem[eProp.size()];
Enumeration enum = eProp.propertyNames();
int i = 0;
while (enum.hasMoreElements()) {
String key = (String) enum.nextElement();
String value = eProp.getProperty(key);
selectImplClass[i] = new JRadioButtonMenuItem(key);
selectImplClass[i].setActionCommand(key);
selectImplClass[i].addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event) {
String key = event.getActionCommand();
String implClass = eProp.getProperty(key);
interpreter.setLinearAlgebraImpl(implClass);
}
});
i++;
}
ButtonGroup group = new ButtonGroup();
for (i = 0; i < selectImplClass.length; i++) {
if (i==0) selectImplClass[i].setSelected(true);
group.add(selectImplClass[i]);
algebraImplMenuItem.add(selectImplClass[i]);
}
return algebraImplMenuItem;
}
public JFileChooser getFileChooser() {
if (fileChooser==null) {
fileChooser = new JFileChooser();
//TODO: How to add multiple filters
// ClassFileFilter filter = new ClassFileFilter();
// fileChooser.setFileFilter(filter);
}
return fileChooser;
}
private JMenuItem getRunMenuItem() {
if (runMenuItem==null) {
runMenuItem = new JMenuItem("Run Program");
runMenuItem.setMnemonic(KeyEvent.VK_R);
runMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_MASK));
runMenuItem.addActionListener(new RunProgramActionHandler(this));
}
return runMenuItem;
}
public class LoadMMethodActionHandler implements ActionListener {
private MainWin frame;
public LoadMMethodActionHandler(MainWin frame) {
this.frame = frame;
}
//TODO: nothing
public void actionPerformed(ActionEvent event) {
Object[] out = LibraryDialog.showDialog(frame, mProp, "Load m-methods", " m-methods", " Enter the folder contain m-files: ");
mProp.clear();
for (int i=0; i<out.length; i++) {
mProp.setProperty(LibraryManager.M_METHOD_LOACTION+"."+i, (String)out[i]);
}
lib.setMProperties(mProp);
String userDir = System.getProperty("user.home");
String configFileName = "mmethods-jmatlab.properties";
String configFile = userDir + File.separator + configFileName;
OutputStream ostream = null;
try {
ostream = new FileOutputStream(configFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
mProp.store(ostream, "");
ostream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public class LoadJMethodActionHandler implements ActionListener {
private MainWin frame;
public LoadJMethodActionHandler(MainWin frame) {
this.frame = frame;
}
public void actionPerformed(ActionEvent event) {
Object[] out = LibraryDialog.showDialog(frame, jProp, "Load java-methods", " java classes", " Enter the fully qualified java class names: ");
jProp.clear();
for (int i=0; i<out.length; i++) {
jProp.setProperty(LibraryManager.J_CLASS_NAME+"."+i, (String)out[i]);
}
lib.setJProperties(jProp);
String userDir = System.getProperty("user.home");
String configFileName = "jmethods-jmatlab.properties";
String configFile = userDir + File.separator + configFileName;
OutputStream ostream = null;
try {
ostream = new FileOutputStream(configFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
jProp.store(ostream, "");
ostream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
//TODO
public class LoadExecutionActionHandler implements ActionListener {
private MainWin frame;
LoadExecutionActionHandler(MainWin frame) {
this.frame = frame;
}
public void actionPerformed(ActionEvent event) {
String[] columnNames = {"Name", "Class"};
Object[][] out = TableDialog.showDialog(frame, eProp, "Load Execution Modules", columnNames);
eProp.clear();
for (int i=0; i<out.length; i++) {
if (out[i][0]!=null && ((String)out[i][0]).trim().length()!=0 && out[i][1]!=null && ((String)out[i][1]).trim().length()!=0) {
eProp.setProperty(((String)out[i][0]).trim(), ((String)out[i][1]).trim());
}
}
String userDir = System.getProperty("user.home");
String configFileName = "execution-jmatlab.properties";
String configFile = userDir + File.separator + configFileName;
OutputStream ostream = null;
try {
ostream = new FileOutputStream(configFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
eProp.store(ostream, "");
ostream.close();
} catch (IOException e1) {
e1.printStackTrace();
}
toolsMenu.remove(algebraImplMenuItem);
toolsMenu.add(getAlgebraMenuItem());
}
}
public class RunProgramActionHandler implements ActionListener {
private MainWin frame;
RunProgramActionHandler(MainWin frame) {
this.frame = frame;
}
public void actionPerformed(ActionEvent event) {
int returnVal = getFileChooser().showOpenDialog(frame);
if (returnVal != JFileChooser.APPROVE_OPTION) return;
String fileName = fileChooser.getSelectedFile().getAbsolutePath();
if (fileName == null) return;
try
{
Lexer lexer = new Lexer(
new PushbackReader(
new BufferedReader(
new FileReader(fileName))));
Parser parser = new Parser(lexer);
Node ast = parser.parse();
inputArea.append("run " + fileName);
ast.apply(getInterpreter());
}
catch(Exception e) {
String mesg = e.getMessage();
inputArea.append("\n" + mesg);
e.printStackTrace();
}
writePrompt();
writeHistory("run " + fileName);
lastPosition = inputArea.getText().length();
inputArea.setCaretPosition(lastPosition);
}
}
public static Interpreter getInterpreter() {
return interpreter;
}
private JMenu getFileMenu() {
if (fileMenu==null) {
fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F);
fileMenu.add(getOpenFileMenuItem());
fileMenu.addSeparator();
fileMenu.add(getSaveSessionMenuItem());
fileMenu.add(getLoadSessionMenuItem());
fileMenu.addSeparator();
fileMenu.add(getExitMenuItem());
}
return fileMenu;
}
private JMenuItem getOpenFileMenuItem() {
if (openFileMenuItem==null) {
openFileMenuItem = new JMenuItem("Open");
openFileMenuItem.setMnemonic(KeyEvent.VK_O);
}
return openFileMenuItem;
}
private JMenuItem getSaveSessionMenuItem() {
if (saveSessionMenuItem==null) {
saveSessionMenuItem = new JMenuItem("Save Session");
saveSessionMenuItem.setMnemonic(KeyEvent.VK_S);
saveSessionMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK));
saveSessionMenuItem.addActionListener(new SaveSessionActionListener(this));
}
return saveSessionMenuItem;
}
public class SaveSessionActionListener implements ActionListener {
private JFrame frame;
public SaveSessionActionListener(JFrame frame) {
this.frame = frame;
}
public void actionPerformed(ActionEvent e) {
int returnVal = getFileChooser().showSaveDialog(frame);
if (returnVal == JFileChooser.APPROVE_OPTION) {
String fileName = fileChooser.getSelectedFile().getAbsolutePath();
try {
FileOutputStream fos = new FileOutputStream(fileName);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(symbolTable.getVariables());
oos.writeObject(historyListModel);
oos.close();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
}
}
}
}
private JMenuItem getLoadSessionMenuItem() {
if (loadSessionMenuItem==null) {
loadSessionMenuItem = new JMenuItem("Load Session");
loadSessionMenuItem.setMnemonic(KeyEvent.VK_L);
loadSessionMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, KeyEvent.CTRL_MASK));
loadSessionMenuItem.addActionListener(new LoadSessionActionListener(this));
}
return loadSessionMenuItem;
}
public class LoadSessionActionListener implements ActionListener {
private JFrame frame;
public LoadSessionActionListener(JFrame frame) {
this.frame = frame;
}
public void actionPerformed(ActionEvent e) {
int returnVal = getFileChooser().showOpenDialog(frame);
if (returnVal == JFileChooser.APPROVE_OPTION) {
String fileName = fileChooser.getSelectedFile().getAbsolutePath();
try {
FileInputStream fis = new FileInputStream(fileName);
ObjectInputStream ois = new ObjectInputStream(fis);
Hashtable hashtable = (Hashtable)ois.readObject();
symbolTable.setVariable(hashtable);
symbolListModel.clear();
for (Enumeration enum = hashtable.elements(); enum.hasMoreElements(); ) {
Symbol sym = (Symbol) enum.nextElement();
symbolListModel.addElement(sym.getName());
}
DefaultListModel listModel= (DefaultListModel)ois.readObject();
historyListModel.clear();
for (Enumeration enum = listModel.elements(); enum.hasMoreElements(); ) {
String str = (String) enum.nextElement();
historyListModel.addElement(str);
}
ois.close();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e2) {
e2.printStackTrace();
} catch (ClassNotFoundException e3) {
e3.printStackTrace();
}
}
}
}
private JMenuItem getExitMenuItem() {
if (exitMenuItem==null) {
exitMenuItem = new JMenuItem("Exit");
exitMenuItem.setMnemonic(KeyEvent.VK_X);
exitMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_MASK));
exitMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
}
return exitMenuItem;
}
private JMenu getEditMenu() {
if (editMenu==null) {
editMenu = new JMenu("Edit");
editMenu.setMnemonic(KeyEvent.VK_E);
editMenu.add(getCopyMenuItem());
editMenu.add(getPasteMenuItem());
}
return editMenu;
}
private JMenuItem getCopyMenuItem() {
if (copyMenuItem==null) {
copyMenuItem = new JMenuItem("Copy");
copyMenuItem.setMnemonic(KeyEvent.VK_C);
copyMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK));
copyMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
inputArea.copy();
}
});
}
return copyMenuItem;
}
private JMenuItem getPasteMenuItem() {
if (pasteMenuItem==null) {
pasteMenuItem = new JMenuItem("Paste");
pasteMenuItem.setMnemonic(KeyEvent.VK_P);
pasteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_MASK));
pasteMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
inputArea.paste();
}
});
}
return pasteMenuItem;
}
private javax.swing.JPanel getJContentPane() {
if (jContentPane == null) {
jContentPane = new javax.swing.JPanel();
jContentPane.setLayout(new java.awt.BorderLayout());
jContentPane.add(getToolBar(), BorderLayout.NORTH);
jContentPane.add(getWndPanel(), BorderLayout.CENTER);
jContentPane.add(getStatusPanel(), BorderLayout.SOUTH);
}
return jContentPane;
}
private JPanel getStatusPanel() {
if (statusPanel == null) {
statusPanel = new JPanel();
statusPanel.setLayout(new GridLayout(0,1));
lblStatus = new JLabel(getStatus());
statusPanel.add(lblStatus);
}
return statusPanel;
}
private JLabel getStatusLabel() {
if (lblStatus == null) {
lblStatus = new JLabel(getStatus());
}
return lblStatus;
}
private String getStatus() {
status = "";
return status;
}
private JSplitPane getWndPanel() {
if (wndPane == null) {
wndPane = new JSplitPane();
wndPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
wndPane.setLeftComponent(getSplitPanel());
wndPane.setRightComponent(getDebugPanel());
}
return wndPane;
}
private JSplitPane getDebugPanel() {
if (debugPane == null) {
debugPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, getSymbolPanel(), getDetailPanel());
}
return debugPane;
}
private JSplitPane getSplitPanel() {
if (splitPane == null) {
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, getInputPanel(), getHistoryPanel());
}
return splitPane;
}
private JComponent getSymbolPanel() {
JScrollPane scrollPane = new JScrollPane(getSymbolList(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
return scrollPane;
}
private JList getSymbolList() {
if (symbolList == null) {
symbolList = new JList(getSymbolListModel());
symbolList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
symbolList.setPreferredSize(new Dimension(5, 10));
symbolList.addListSelectionListener(new ListSelectionListener(){
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting() == true) {
String value = (String)symbolList.getSelectedValue();
Symbol symbol = symbolTable.get(value);
int type = symbol.getType();
if (type==DataType.DOUBLE) {
String[][] data = new String[][] {{""+symbol.getDouble().doubleValue()}};
String[] columns = new String[] {""} ;
detailTable.setModel(new DefaultTableModel(data, columns));
} else if (type==DataType.STRING) {
String[][] data = new String[][] {{symbol.getString()}};
String[] columns = new String[] {""} ;
detailTable.setModel(new DefaultTableModel(data, columns));
} else if (type == DataType.BOOLEAN) {
String[][] data = new String[][] {{symbol.getBoolean().toString()}};
String[] columns = new String[] {""} ;
detailTable.setModel(new DefaultTableModel(data, columns));
} else if (type == DataType.COMPLEX) {
String[][] data = new String[][] {{symbol.getComplex().toString()}};
String[] columns = new String[] {""} ;
detailTable.setModel(new DefaultTableModel(data, columns));
} else if (type == DataType.MATRIX) {
IMatrix matrix = symbol.getMatrix();
String[][] data = matrix.getMatrixAsStringArray();
String[] columns = new String[matrix.getCols()] ;
for (int i=0; i<matrix.getCols(); i++) {
columns[i] = "";
}
detailTable.setModel(new DefaultTableModel(data, columns));
}
}
}
});
}
return symbolList;
}
private DefaultListModel getSymbolListModel() {
if (symbolListModel == null) {
symbolListModel = new DefaultListModel();
}
return symbolListModel;
}
private JComponent getDetailPanel() {
JScrollPane scrollPane = new JScrollPane(getDetailTable(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
return scrollPane;
}
private JTable getDetailTable() {
if (detailTable == null) {
detailTable = new JTable(new String[][]{{""}}, new String[]{""});
detailTable.setPreferredScrollableViewportSize(new Dimension(2,10));
detailTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
}
return detailTable;
}
private MatrixTableModel getDetailTableModel() {
if (detailTableModel == null) {
detailTableModel = new MatrixTableModel();
}
return detailTableModel;
}
private JComponent getInputPanel() {
JScrollPane scrollPane = new JScrollPane(getInputArea(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
return scrollPane;
}
private JComponent getHistoryPanel() {
JScrollPane scrollPane = new JScrollPane(getHistoryList(), JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
return scrollPane;
}
private JTextArea getInputArea() {
if (inputArea == null) {
inputArea = new InputTextArea(new SimpleDocument(), 25,100);
inputArea.setEditable(true);
inputArea.addKeyListener(new InputKeyListener(this));
}
return inputArea;
}
private JList getHistoryList() {
if (historyList == null) {
historyList = new JList(getHistoryListModel());
historyList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
return historyList;
}
private DefaultListModel getHistoryListModel() {
if (historyListModel == null) {
historyListModel = new DefaultListModel();
}
return historyListModel;
}
private StringBuffer buffer = new StringBuffer();
private JList historyList;
private int historyPointer = 0;
public class InputKeyListener implements KeyListener {
private MainWin frame;
InputKeyListener(MainWin frame) {
this.frame = frame;
}
public void keyPressed(KeyEvent event) {
int position = inputArea.getCaretPosition();
if (position < lastPosition) {
int start = 0;
int end = 0;
if (!inputArea.getSelectedText().equals("")) {
start = inputArea.getSelectionStart();
end = inputArea.getSelectionEnd();
}
inputArea.setCaretPosition(lastPosition);
inputArea.setSelectionStart(start);
inputArea.setSelectionEnd(end);
}
int ch = event.getKeyCode();
if (ch == KeyEvent.VK_UP || ch == KeyEvent.VK_DOWN) {
event.consume();
return;
}
if (ch == KeyEvent.VK_LEFT) {
int newPosition = inputArea.getCaretPosition();
if (newPosition <= lastPosition) {
event.consume();
return;
}
}
if (ch == KeyEvent.VK_BACK_SPACE) {
int newPosition = inputArea.getCaretPosition();
if (newPosition <= lastPosition) {
event.consume();
//workaround since consume on backspace key does not work
inputArea.insert(" ", lastPosition);
inputArea.setCaretPosition(lastPosition);
return;
}
}
}
public void keyReleased(KeyEvent event) {
int ch = event.getKeyCode();
if (ch == KeyEvent.VK_HOME) {
inputArea.setCaretPosition(lastPosition);
}
if (ch == KeyEvent.VK_UP || ch == KeyEvent.VK_DOWN) {
int historySize = historyListModel.size();
if (ch == KeyEvent.VK_DOWN) {
historyPointer++;
if (historyPointer > historySize-1) {
historyPointer = (historyPointer % historySize);
}
String in = ((String) historyListModel.getElementAt(historyPointer)).trim();
int currentPosition = inputArea.getText().length();
inputArea.replaceRange(in, lastPosition, currentPosition);
}
if (ch == KeyEvent.VK_UP) {
historyPointer--;
if (historyPointer < 0) {
historyPointer = historySize - 1;
}
String in = ((String) historyListModel.getElementAt(historyPointer)).trim();
int currentPosition = inputArea.getText().length();
inputArea.replaceRange(in, lastPosition, currentPosition);
}
event.consume();
return;
}
if (ch == KeyEvent.VK_LEFT) {
int newPosition = inputArea.getCaretPosition();
if (newPosition <= lastPosition) {
event.consume();
return;
}
}
if (ch == KeyEvent.VK_BACK_SPACE) {
int newPosition = inputArea.getCaretPosition();
if (newPosition <= lastPosition) {
event.consume();
//workaround since consume on backspace key does not work
inputArea.setCaretPosition(lastPosition);
return;
}
}
}
public void keyTyped(KeyEvent event) {
int position = inputArea.getCaretPosition();
if (position < lastPosition) {
inputArea.setCaretPosition(inputArea.getText().length());
}
char ch = event.getKeyChar();
int modifier = event.getModifiers();
if (modifier == KeyEvent.VK_CONTROL && (ch == 'c' || ch == 'C')) {
inputArea.copy();
}
if (modifier == KeyEvent.VK_CONTROL && (ch == 'v' || ch == 'V')) {
inputArea.paste();
}
if (ch=='\n') {
String input = inputArea.getText().substring(lastPosition-1);
/* int n = input.indexOf('\n');
buffer.append(input).deleteCharAt(n);
*/
buffer.append(input);
Matcher m = p.matcher(buffer.toString().trim());
if (input.trim().toUpperCase().startsWith("QUIT") || input.trim().toUpperCase().startsWith("EXIT") ) {
System.exit(0);
} else if (input.trim().toUpperCase().startsWith("RUN ")) {
String fileName = input.substring(5).trim();
fileName = StringUtils.replace(fileName, "\\", "\\\\");
//TODO
try
{
Lexer lexer = new Lexer(
new PushbackReader(
new BufferedReader(
new FileReader(fileName))));
Parser parser = new Parser(lexer);
Node ast = parser.parse();
ast.apply(getInterpreter());
}
catch(Exception e) {
String mesg = e.getMessage();
inputArea.append("\n" + mesg);
e.printStackTrace();
}
writePrompt();
writeHistory("run " + fileName);
lastPosition = inputArea.getText().length();
inputArea.setCaretPosition(lastPosition);
} else if (input.trim().toUpperCase().startsWith("IF ") ||
input.trim().toUpperCase().startsWith("FOR ") ||
input.trim().toUpperCase().startsWith("WHILE ") ) {
execStack.push(input);
} else if (input.trim().toUpperCase().endsWith("END") || input.trim().toUpperCase().endsWith("END;")) {
execStack.pop();
} else if (input.trim().equalsIgnoreCase("CLC")) {
inputArea.setText(prompt);
buffer = new StringBuffer();
} else if (input.trim().toUpperCase().startsWith("HELP")) {
String methodName = buffer.toString().substring(6).trim();
String help = lib.getHelp(methodName);
inputArea.append(help);
writePrompt();
buffer = new StringBuffer();
} else if (m.matches()) {
String in = buffer.toString().trim().toUpperCase();
find(in);
buffer = new StringBuffer();
} else if (execStack.size()==0) {
String in = buffer.toString();
buffer = new StringBuffer();
executeCode(in);
}
lastPosition = inputArea.getText().length();
inputArea.setCaretPosition(lastPosition);
}
}
}
private void find(String s) {
Symbol symbol = symbolTable.get(s);
if (symbol != null) {
interpreter.print(symbol);
} else {
Symbol rtn = null;
try {
rtn = interpreter.functionCall(s, new Vector());
} catch(Exception e) {
e.printStackTrace();
}
if (rtn != null) interpreter.print(rtn);
}
writePrompt();
}
public void executeCode(String in) {
System.out.println("input="+in);
lexer = new Lexer(new PushbackReader(new StringReader(in), 1000));
parser = new Parser(lexer);
try {
Node ast = parser.parse();
ast.apply(interpreter);
} catch (Exception e) {
String mesg = e.getMessage();
inputArea.append("\n" + mesg);
e.printStackTrace();
}
writePrompt();
writeHistory(in);
}
private void writeHistory(String in) {
String out = in.replaceAll("\n", " ");
historyListModel.addElement("\n"+out);
historyPointer = historyListModel.size();
}
private void writePrompt() {
inputArea.append("\n");
inputArea.append(prompt);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
SymbolTable symbolTable = new SymbolTable();
final MainWin win = new MainWin(symbolTable);
symbolTable.addObserver(win);
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.pack();
win.setVisible(true);
}
public void update(Observable o, Object arg) {
Symbol symbol = (Symbol)arg;
String string = symbol.getName();
if (symbolListModel.contains(string)) {
symbolListModel.removeElement(string);
}
symbolListModel.addElement(string);
}
class SimpleDocument extends PlainDocument {
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
if (str == null) {
return;
}
super.insertString(offs, str, a);
}
}
}
|