2017-07-25 14:52:57 -07:00
|
|
|
package org.nwapw.abacus.window;
|
|
|
|
|
2017-07-26 13:31:05 -07:00
|
|
|
import org.nwapw.abacus.plugin.PluginManager;
|
|
|
|
import org.nwapw.abacus.tree.NumberReducer;
|
|
|
|
import org.nwapw.abacus.tree.TreeNode;
|
|
|
|
|
2017-07-25 14:52:57 -07:00
|
|
|
import javax.swing.*;
|
|
|
|
import java.awt.*;
|
2017-07-26 14:48:43 -07:00
|
|
|
import java.awt.datatransfer.StringSelection;
|
2017-07-26 15:22:29 -07:00
|
|
|
import java.awt.event.ActionListener;
|
2017-07-26 14:48:43 -07:00
|
|
|
import java.awt.event.MouseAdapter;
|
|
|
|
import java.awt.event.MouseEvent;
|
2017-07-25 14:52:57 -07:00
|
|
|
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
|
|
|
* The main UI window for the calculator.
|
|
|
|
*/
|
2017-07-25 14:52:57 -07:00
|
|
|
public class Window extends JFrame {
|
2017-07-25 21:13:18 -07:00
|
|
|
|
2017-07-26 13:31:05 -07:00
|
|
|
private static final String CALC_STRING = "Calculate";
|
|
|
|
private static final String SELECT_STRING = "Select";
|
|
|
|
private static final String SYNTAX_ERR_STRING = "Syntax Error";
|
|
|
|
private static final String NUMBER_SYSTEM_LABEL = "Number Type:";
|
|
|
|
private static final String FUNCTION_LABEL = "Functions:";
|
|
|
|
|
2017-07-26 17:17:21 -07:00
|
|
|
private static final String[] BUTTON_NAMES = {
|
|
|
|
CALC_STRING,
|
|
|
|
CALC_STRING
|
|
|
|
};
|
|
|
|
|
|
|
|
private static boolean[] BUTTON_ENABLED = {
|
|
|
|
true,
|
|
|
|
false
|
|
|
|
};
|
|
|
|
|
2017-07-26 13:31:05 -07:00
|
|
|
/**
|
|
|
|
* The plugin manager used to retrieve functions.
|
|
|
|
*/
|
|
|
|
private PluginManager manager;
|
|
|
|
/**
|
|
|
|
* The reducer used to evaluate the tree.
|
|
|
|
*/
|
|
|
|
private NumberReducer reducer;
|
|
|
|
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
|
|
|
* The last output by the calculator.
|
|
|
|
*/
|
2017-07-25 14:52:57 -07:00
|
|
|
private String lastOutput;
|
2017-07-25 21:13:18 -07:00
|
|
|
|
2017-07-26 17:17:21 -07:00
|
|
|
/**
|
|
|
|
* The tabbed pane that separates calculator contexts.
|
|
|
|
*/
|
|
|
|
private JTabbedPane pane;
|
|
|
|
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
|
|
|
* The panel where the output occurs.
|
|
|
|
*/
|
2017-07-26 17:18:40 -07:00
|
|
|
private JPanel calculationPanel;
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
|
|
|
* The text area reserved for the last output.
|
|
|
|
*/
|
2017-07-25 21:13:18 -07:00
|
|
|
private JTextArea lastOutputArea;
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
2017-07-26 14:34:19 -07:00
|
|
|
* The table used for storing history results.
|
2017-07-26 10:10:37 -07:00
|
|
|
*/
|
2017-07-26 14:34:19 -07:00
|
|
|
private JTable historyTable;
|
|
|
|
/**
|
|
|
|
* The table model used for managing history.
|
|
|
|
*/
|
|
|
|
private HistoryTableModel historyModel;
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
|
|
|
* The scroll pane for the history area.
|
|
|
|
*/
|
2017-07-26 14:34:19 -07:00
|
|
|
private JScrollPane historyScroll;
|
2017-07-25 21:13:18 -07:00
|
|
|
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
|
|
|
* The panel where the input occurs.
|
|
|
|
*/
|
2017-07-25 21:13:18 -07:00
|
|
|
private JPanel inputPanel;
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
|
|
|
* The input text field.
|
|
|
|
*/
|
2017-07-25 21:13:18 -07:00
|
|
|
private JTextField inputField;
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
|
|
|
* The "submit" button.
|
|
|
|
*/
|
2017-07-25 21:13:18 -07:00
|
|
|
private JButton inputEnterButton;
|
|
|
|
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
|
|
|
* The side panel for separate configuration.
|
|
|
|
*/
|
2017-07-26 17:18:40 -07:00
|
|
|
private JPanel settingsPanel;
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
|
|
|
* Panel for elements relating to number
|
|
|
|
* system selection.
|
|
|
|
*/
|
2017-07-25 21:13:18 -07:00
|
|
|
private JPanel numberSystemPanel;
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
|
|
|
* The possible list of number systems.
|
|
|
|
*/
|
2017-07-25 21:13:18 -07:00
|
|
|
private JComboBox<String> numberSystemList;
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
|
|
|
* The panel for elements relating to
|
|
|
|
* function selection.
|
|
|
|
*/
|
2017-07-25 21:13:18 -07:00
|
|
|
private JPanel functionSelectPanel;
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
|
|
|
* The list of functions available to the user.
|
|
|
|
*/
|
2017-07-25 21:13:18 -07:00
|
|
|
private JComboBox<String> functionList;
|
2017-07-26 17:17:21 -07:00
|
|
|
|
2017-07-26 10:10:37 -07:00
|
|
|
/**
|
2017-07-26 17:17:21 -07:00
|
|
|
* Action listener that causes the input to be evaluated.
|
2017-07-26 10:10:37 -07:00
|
|
|
*/
|
2017-07-26 17:17:21 -07:00
|
|
|
private ActionListener evaluateListener = (event) -> {
|
|
|
|
TreeNode parsedExpression = TreeNode.fromString(inputField.getText());
|
|
|
|
if(parsedExpression == null){
|
|
|
|
lastOutputArea.setText(SYNTAX_ERR_STRING);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
lastOutput = parsedExpression.reduce(reducer).toString();
|
|
|
|
historyModel.addEntry(new HistoryTableModel.HistoryEntry(inputField.getText(), parsedExpression, lastOutput));
|
|
|
|
historyTable.invalidate();
|
|
|
|
lastOutputArea.setText(lastOutput);
|
|
|
|
inputField.setText("");
|
|
|
|
};
|
|
|
|
|
|
|
|
private ActionListener[] listeners = {
|
|
|
|
evaluateListener,
|
|
|
|
null
|
|
|
|
};
|
2017-07-25 21:13:18 -07:00
|
|
|
|
2017-07-26 13:31:05 -07:00
|
|
|
/**
|
|
|
|
* Creates a new window with the given manager.
|
|
|
|
* @param manager the manager to use.
|
|
|
|
*/
|
|
|
|
public Window(PluginManager manager){
|
|
|
|
this();
|
|
|
|
this.manager = manager;
|
|
|
|
reducer = new NumberReducer(manager);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a new window.
|
|
|
|
*/
|
|
|
|
private Window() {
|
2017-07-25 14:52:57 -07:00
|
|
|
super();
|
2017-07-25 21:13:18 -07:00
|
|
|
|
|
|
|
lastOutput = "";
|
|
|
|
|
2017-07-26 15:23:22 -07:00
|
|
|
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
2017-07-26 17:19:43 -07:00
|
|
|
setSize(320, 480);
|
2017-07-25 21:13:18 -07:00
|
|
|
|
|
|
|
inputField = new JTextField();
|
2017-07-26 13:31:05 -07:00
|
|
|
inputEnterButton = new JButton(CALC_STRING);
|
2017-07-25 21:13:18 -07:00
|
|
|
|
|
|
|
inputPanel = new JPanel();
|
|
|
|
inputPanel.setLayout(new BorderLayout());
|
2017-07-25 22:08:12 -07:00
|
|
|
inputPanel.add(inputField, BorderLayout.CENTER);
|
2017-07-26 15:22:29 -07:00
|
|
|
inputPanel.add(inputEnterButton, BorderLayout.SOUTH);
|
2017-07-25 21:13:18 -07:00
|
|
|
|
2017-07-26 14:34:19 -07:00
|
|
|
historyModel = new HistoryTableModel();
|
|
|
|
historyTable = new JTable(historyModel);
|
|
|
|
historyScroll = new JScrollPane(historyTable);
|
2017-07-25 21:13:18 -07:00
|
|
|
lastOutputArea = new JTextArea(lastOutput);
|
|
|
|
lastOutputArea.setEditable(false);
|
|
|
|
|
2017-07-26 17:18:40 -07:00
|
|
|
calculationPanel = new JPanel();
|
|
|
|
calculationPanel.setLayout(new BorderLayout());
|
|
|
|
calculationPanel.add(historyScroll, BorderLayout.CENTER);
|
|
|
|
calculationPanel.add(lastOutputArea, BorderLayout.SOUTH);
|
2017-07-25 21:13:18 -07:00
|
|
|
|
|
|
|
numberSystemList = new JComboBox<>();
|
|
|
|
|
|
|
|
numberSystemPanel = new JPanel();
|
2017-07-26 17:17:21 -07:00
|
|
|
numberSystemPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
|
|
|
numberSystemPanel.setLayout(new FlowLayout());
|
|
|
|
numberSystemPanel.add(new JLabel(NUMBER_SYSTEM_LABEL));
|
|
|
|
numberSystemPanel.add(numberSystemList);
|
|
|
|
numberSystemPanel.setMaximumSize(numberSystemPanel.getPreferredSize());
|
2017-07-25 21:13:18 -07:00
|
|
|
|
|
|
|
functionList = new JComboBox<>();
|
|
|
|
|
|
|
|
functionSelectPanel = new JPanel();
|
2017-07-26 17:17:21 -07:00
|
|
|
functionSelectPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
|
|
|
functionSelectPanel.setLayout(new FlowLayout());
|
|
|
|
functionSelectPanel.add(new JLabel(FUNCTION_LABEL));
|
|
|
|
functionSelectPanel.add(functionList);
|
|
|
|
functionSelectPanel.setMaximumSize(functionSelectPanel.getPreferredSize());
|
2017-07-25 21:13:18 -07:00
|
|
|
|
2017-07-26 17:18:40 -07:00
|
|
|
settingsPanel = new JPanel();
|
|
|
|
settingsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
|
|
|
settingsPanel.setLayout(new BoxLayout(settingsPanel, BoxLayout.PAGE_AXIS));
|
|
|
|
settingsPanel.add(numberSystemPanel);
|
|
|
|
settingsPanel.add(functionSelectPanel);
|
2017-07-25 21:13:18 -07:00
|
|
|
|
2017-07-26 17:17:21 -07:00
|
|
|
pane = new JTabbedPane();
|
2017-07-26 17:18:40 -07:00
|
|
|
pane.add("Calculator", calculationPanel);
|
|
|
|
pane.add("Settings", settingsPanel);
|
2017-07-26 17:17:21 -07:00
|
|
|
pane.addChangeListener(e -> {
|
|
|
|
int selectionIndex = pane.getSelectedIndex();
|
|
|
|
boolean enabled = BUTTON_ENABLED[selectionIndex];
|
|
|
|
ActionListener listener = listeners[selectionIndex];
|
|
|
|
inputEnterButton.setText(BUTTON_NAMES[selectionIndex]);
|
|
|
|
inputField.setEnabled(enabled);
|
|
|
|
inputEnterButton.setEnabled(enabled);
|
|
|
|
|
|
|
|
for(ActionListener removingListener : inputEnterButton.getActionListeners()){
|
|
|
|
inputEnterButton.removeActionListener(removingListener);
|
|
|
|
inputField.removeActionListener(removingListener);
|
|
|
|
}
|
|
|
|
if(listener != null){
|
|
|
|
inputEnterButton.addActionListener(listener);
|
|
|
|
inputField.addActionListener(listener);
|
|
|
|
}
|
|
|
|
});
|
2017-07-26 15:35:59 -07:00
|
|
|
add(pane, BorderLayout.CENTER);
|
2017-07-25 21:13:18 -07:00
|
|
|
add(inputPanel, BorderLayout.SOUTH);
|
2017-07-26 14:34:19 -07:00
|
|
|
|
2017-07-26 17:17:21 -07:00
|
|
|
inputEnterButton.addActionListener(evaluateListener);
|
|
|
|
inputField.addActionListener(evaluateListener);
|
2017-07-26 14:48:43 -07:00
|
|
|
historyTable.addMouseListener(new MouseAdapter() {
|
|
|
|
@Override
|
|
|
|
public void mouseClicked(MouseEvent e) {
|
|
|
|
Point clickPoint = e.getPoint();
|
|
|
|
if(e.getClickCount() == 2){
|
|
|
|
int row = historyTable.rowAtPoint(clickPoint);
|
|
|
|
int column = historyTable.columnAtPoint(clickPoint);
|
|
|
|
String toCopy = historyTable.getValueAt(row, column).toString();
|
|
|
|
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(toCopy), null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2017-07-25 14:52:57 -07:00
|
|
|
}
|
|
|
|
}
|