package net.sf.openrocket.gui.customexpression;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.gui.util.Icons;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.simulation.customexpression.CustomExpression;
import net.sf.openrocket.startup.Application;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Dialog box for making a custom expression
* @author Richard Graham
*
*/
public class ExpressionBuilderDialog extends JDialog {
private static final Translator trans = Application.getTranslator();
private static final Logger log = LoggerFactory.getLogger(ExpressionBuilderDialog.class);
private static final ImageIcon GreenIcon = Icons.loadImageIcon("pix/spheres/green-16x16.png", "OK");
private static final ImageIcon RedIcon = Icons.loadImageIcon("pix/spheres/red-16x16.png", "Bad");
private CustomExpression expression;
private CustomExpression previousExpressionCopy;
@SuppressWarnings("unused")
private final Window parentWindow;
@SuppressWarnings("unused")
private final OpenRocketDocument doc;
// Define these check indicators to show if fields are OK
private final JLabel nameCheck = new JLabel(RedIcon);
private final JLabel expressionCheck = new JLabel(RedIcon);
private final JLabel unitCheck = new JLabel(RedIcon);
private final JButton okButton = new JButton(trans.get("dlg.but.ok"));
private final JTextField expressionField = new JTextField(20);
public ExpressionBuilderDialog(Window parent, OpenRocketDocument doc){
this(parent, doc, new CustomExpression(doc));
}
public ExpressionBuilderDialog(Window parent, final OpenRocketDocument doc, final CustomExpression previousExpression){
super(parent, trans.get("ExpressionBuilderDialog.title"), JDialog.ModalityType.DOCUMENT_MODAL);
this.doc = doc;
this.parentWindow = parent;
this.previousExpressionCopy = (CustomExpression) previousExpression.clone();
this.expression = previousExpression;
//// Name box -- Check input when focus changes and transfer focus to next box on enter key
JLabel nameLabel = new JLabel(trans.get("customExpression.Name"));
final JTextField nameField = new JTextField(20);
nameField.setText(expression.getName());
nameField.setFocusTraversalKeysEnabled(true);
nameField.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) { }
@Override
public void focusLost(FocusEvent e) {
expression.setName(nameField.getText());
ExpressionBuilderDialog.this.updateOK();
}
});
nameField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
nameField.transferFocus();
}
});
//// Expression box -- for this one we check after each keypress using a keyListener. Enter transfers to next field
JLabel expressionLabel = new JLabel(trans.get("customExpression.Expression"));
expressionField.setText(expression.getExpressionString());
expressionField.addKeyListener(new KeyListener() {
@Override
public void keyReleased(KeyEvent arg0) {
expression.setExpression( expressionField.getText() );
ExpressionBuilderDialog.this.updateOK();
}
@Override
public void keyPressed(KeyEvent e) {}
@Override
public void keyTyped(KeyEvent e) {}
});
expressionField.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
expressionField.transferFocus();
}
});
//// Units box -- with action listeners checking input after change in focus or enter press
JLabel unitLabel = new JLabel(trans.get("customExpression.Units"));
final JTextField unitField = new JTextField(5);
unitField.setText(expression.getUnit());
unitField.addFocusListener(new FocusListener(){
@Override
public void focusLost(FocusEvent arg0) {
expression.setUnit(unitField.getText()) ;
ExpressionBuilderDialog.this.updateOK();
}
@Override
public void focusGained(FocusEvent arg0) {}
});
unitField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
unitField.transferFocus();
}
});
//// Symbol box
JLabel symbolLabel = new JLabel(trans.get("customExpression.Symbol"));
final JTextField symbolField = new JTextField(5);
symbolField.setText(expression.getSymbol());
symbolField.addFocusListener(new FocusListener(){
@Override
public void focusLost(FocusEvent arg0) {
expression.setSymbol(symbolField.getText()) ;
ExpressionBuilderDialog.this.updateOK();
}
@Override
public void focusGained(FocusEvent arg0) {}
});
symbolField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
symbolField.transferFocus();
}
});
//// Insert variable button
final JButton insertVariableButton = new JButton(trans.get("ExpressionBuilderDialog.InsertVariable"));
insertVariableButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
log.debug("Opening insert variable window");
Window myParentWindow = SwingUtilities.getWindowAncestor(ExpressionBuilderDialog.this);
new VariableSelector(myParentWindow, ExpressionBuilderDialog.this, doc).setVisible(true);
}
});
//// Insert operator button
final JButton insertOperatorButton = new JButton(trans.get("ExpressionBuilderDialog.InsertOperator"));
insertOperatorButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
log.debug("Opening insert operator window");
Window myParentWindow = SwingUtilities.getWindowAncestor(ExpressionBuilderDialog.this);
new OperatorSelector(myParentWindow, ExpressionBuilderDialog.this).setVisible(true);
}
});
//// OK Button
okButton.setEnabled(false);
okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// add to this simulation
expression.addToDocument();
// close window
ExpressionBuilderDialog.this.dispose();
}
});
//// Cancel button
final JButton cancelButton = new JButton(trans.get("dlg.but.cancel"));
cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
expression.overwrite(previousExpressionCopy);
ExpressionBuilderDialog.this.dispose();
}
});
//// Set to tips
nameCheck.setToolTipText(trans.get("ExpressionBuilderDialog.led.ttip.Name"));
unitCheck.setToolTipText(trans.get("ExpressionBuilderDialog.led.ttip.Symbol"));
expressionCheck.setToolTipText(trans.get("ExpressionBuilderDialog.led.ttip.Expression"));
//// Do the layout
JPanel mainPanel = new JPanel(new MigLayout());
mainPanel.add(nameLabel);
mainPanel.add(nameField);
mainPanel.add(nameCheck, "wrap, center");
mainPanel.add(symbolLabel);
mainPanel.add(symbolField, "split 4, growx");
mainPanel.add(new JPanel());
mainPanel.add(unitLabel, "right");
mainPanel.add(unitField, "right, growx");
mainPanel.add(unitCheck, "wrap, center");
mainPanel.add(expressionLabel);
mainPanel.add(expressionField);
mainPanel.add(expressionCheck, "wrap, center");
mainPanel.add(insertOperatorButton, "span 2, right, split 2");
mainPanel.add(insertVariableButton, "right, wrap");
mainPanel.add(cancelButton, "span 2, right, width :50:100");
mainPanel.add(okButton, "right, width :50:100, wrap");
this.add(mainPanel);
this.validate();
this.pack();
this.setLocationByPlatform(true);
this.updateOK();
}
/**
* Enable OK button only if all the fields are ok
* @param okButton
*/
protected void updateOK() {
boolean nameOK = expression.checkName();
boolean unitOK = expression.checkUnit();
boolean symbolOK = expression.checkSymbol();
boolean expressionOK = expression.checkExpression();
if (nameOK) { nameCheck.setIcon(GreenIcon); } else { nameCheck.setIcon(RedIcon); }
if (unitOK && symbolOK) { unitCheck.setIcon(GreenIcon); } else { unitCheck.setIcon(RedIcon); }
if (expressionOK) { expressionCheck.setIcon(GreenIcon); } else { expressionCheck.setIcon(RedIcon); }
okButton.setEnabled( nameOK && unitOK && symbolOK && expressionOK );
}
/**
* Inserts a string into the expression box at the position of the cursor.
* String will be padded with spaces either side
* Expression box will be focused after this is called.
* For strings containing an ( , cursor will be moved to the point after that, otherwise, cursor will move to the end of the inserted string.
* @param str
*/
public void pasteIntoExpression(String str) {
int pos = expressionField.getCaretPosition();
String current = expressionField.getText();
expressionField.setText(current.subSequence(0, pos) + " " + str + " " + current.subSequence(pos, current.length()));
expressionField.requestFocus();
int bracketPos = str.indexOf("(");
if (bracketPos != -1){
expressionField.setCaretPosition(pos+2+bracketPos);
}
else {
expressionField.setCaretPosition(pos+2+str.length());
}
}
}