/* Copyright (c) 2010, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */
package com.cburch.logisim.analyze.gui;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import com.cburch.logisim.analyze.model.AnalyzerModel;
import com.cburch.logisim.analyze.model.OutputExpressionsEvent;
import com.cburch.logisim.analyze.model.OutputExpressionsListener;
import com.cburch.logisim.analyze.model.Expression;
import com.cburch.logisim.analyze.model.Parser;
import com.cburch.logisim.analyze.model.ParserException;
import com.cburch.logisim.util.StringGetter;
class ExpressionTab extends AnalyzerTab implements TabInterface {
private class MyListener extends AbstractAction
implements DocumentListener,
OutputExpressionsListener, ItemListener {
boolean edited = false;
public void actionPerformed(ActionEvent event) {
Object src = event.getSource();
if (src == clear) {
setError(null);
field.setText("");
field.grabFocus();
} else if (src == revert) {
setError(null);
field.setText(getCurrentString());
field.grabFocus();
} else if ((src == field || src == enter) && enter.isEnabled()) {
try {
String exprString = field.getText();
Expression expr = Parser.parse(field.getText(), model);
setError(null);
model.getOutputExpressions().setExpression(getCurrentVariable(), expr, exprString);
insertUpdate(null);
} catch (ParserException ex) {
setError(ex.getMessageGetter());
field.setCaretPosition(ex.getOffset());
field.moveCaretPosition(ex.getEndOffset());
}
field.grabFocus();
}
}
public void insertUpdate(DocumentEvent event) {
String curText = field.getText();
edited = curText.length() != curExprStringLength
|| !curText.equals(getCurrentString());
boolean enable = (edited && getCurrentVariable() != null);
clear.setEnabled(curText.length() > 0);
revert.setEnabled(enable);
enter.setEnabled(enable);
}
public void removeUpdate(DocumentEvent event) {
insertUpdate(event);
}
public void changedUpdate(DocumentEvent event) {
insertUpdate(event);
}
public void expressionChanged(OutputExpressionsEvent event) {
if (event.getType() == OutputExpressionsEvent.OUTPUT_EXPRESSION) {
String output = event.getVariable();
if (output.equals(getCurrentVariable())) {
prettyView.setExpression(model.getOutputExpressions().getExpression(output));
currentStringChanged();
}
}
}
public void itemStateChanged(ItemEvent event) {
updateTab();
}
private String getCurrentString() {
String output = getCurrentVariable();
return output == null ? ""
: model.getOutputExpressions().getExpressionString(output);
}
private void currentStringChanged() {
String output = getCurrentVariable();
String exprString = model.getOutputExpressions().getExpressionString(output);
curExprStringLength = exprString.length();
if (!edited) {
setError(null);
field.setText(getCurrentString());
} else {
insertUpdate(null);
}
}
}
private OutputSelector selector;
private ExpressionView prettyView = new ExpressionView();
private JTextArea field = new JTextArea(4, 25);
private JButton clear = new JButton();
private JButton revert = new JButton();
private JButton enter = new JButton();
private JLabel error = new JLabel();
private MyListener myListener = new MyListener();
private AnalyzerModel model;
private int curExprStringLength = 0;
private StringGetter errorMessage;
public ExpressionTab(AnalyzerModel model) {
this.model = model;
selector = new OutputSelector(model);
model.getOutputExpressions().addOutputExpressionsListener(myListener);
selector.addItemListener(myListener);
clear.addActionListener(myListener);
revert.addActionListener(myListener);
enter.addActionListener(myListener);
field.setLineWrap(true);
field.setWrapStyleWord(true);
field.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), myListener);
field.getDocument().addDocumentListener(myListener);
field.setFont(new Font("Monospaced", Font.PLAIN, 14));
JPanel buttons = new JPanel();
buttons.add(clear);
buttons.add(revert);
buttons.add(enter);
GridBagLayout gb = new GridBagLayout();
GridBagConstraints gc = new GridBagConstraints();
setLayout(gb);
gc.weightx = 1.0;
gc.gridx = 0;
gc.gridy = GridBagConstraints.RELATIVE;
gc.fill = GridBagConstraints.BOTH;
JPanel selectorPanel = selector.createPanel();
gb.setConstraints(selectorPanel, gc); add(selectorPanel);
gb.setConstraints(prettyView, gc); add(prettyView);
Insets oldInsets = gc.insets;
gc.insets = new Insets(10, 10, 0, 10);
JScrollPane fieldPane = new JScrollPane(field,
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
gb.setConstraints(fieldPane, gc); add(fieldPane);
gc.insets = oldInsets;
gc.fill = GridBagConstraints.NONE;
gc.anchor = GridBagConstraints.LINE_END;
gb.setConstraints(buttons, gc); add(buttons);
gc.fill = GridBagConstraints.BOTH;
gb.setConstraints(error, gc); add(error);
myListener.insertUpdate(null);
setError(null);
}
@Override
void localeChanged() {
selector.localeChanged();
prettyView.localeChanged();
clear.setText(Strings.get("exprClearButton"));
revert.setText(Strings.get("exprRevertButton"));
enter.setText(Strings.get("exprEnterButton"));
if (errorMessage != null) {
error.setText(errorMessage.get());
}
}
@Override
void updateTab() {
String output = getCurrentVariable();
prettyView.setExpression(model.getOutputExpressions().getExpression(output));
myListener.currentStringChanged();
}
void registerDefaultButtons(DefaultRegistry registry) {
registry.registerDefaultButton(field, enter);
}
String getCurrentVariable() {
return selector.getSelectedOutput();
}
private void setError(StringGetter msg) {
if (msg == null) {
errorMessage = null;
error.setText(" ");
} else {
errorMessage = msg;
error.setText(msg.get());
}
}
public void copy() {
field.requestFocus();
field.copy();
}
public void paste() {
field.requestFocus();
field.paste();
}
public void delete() {
field.requestFocus();
field.replaceSelection("");
}
public void selectAll() {
field.requestFocus();
field.selectAll();
}
}