/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.foundation.bindings;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;
import org.openflexo.antar.expr.BinaryOperator;
import org.openflexo.antar.expr.BinaryOperatorExpression;
import org.openflexo.antar.expr.Constant;
import org.openflexo.antar.expr.Expression;
import org.openflexo.antar.expr.OperatorNotSupportedException;
import org.openflexo.antar.expr.UnaryOperator;
import org.openflexo.antar.expr.Variable;
import org.openflexo.antar.expr.parser.ParseException;
import org.openflexo.antar.java.JavaExpressionParser;
import org.openflexo.antar.java.JavaExpressionPrettyPrinter;
import org.openflexo.antar.java.JavaGrammar;
public class BindingExpressionPanelQuiMarche extends JPanel implements FocusListener {
Expression _expression;
public BindingExpressionPanelQuiMarche(Expression expression) {
super();
setLayout(new BorderLayout());
_expression = expression;
init();
}
private JTextArea expressionTA;
private JPanel controls;
private ExpressionInnerPanel rootExpressionPanel;
void expressionEdited() {
try {
Expression newExpression = parser.parse(expressionTA.getText(), null);
_expression = newExpression;
rootExpressionPanel.setRepresentedExpression(_expression);
update();
} catch (ParseException e) {
System.out.println("ERROR: cannot parse " + expressionTA.getText());
}
}
private void init() {
expressionTA = new JTextArea(3, 50);
expressionTA.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
expressionEdited();
}
if (e.getKeyChar() == KeyEvent.VK_ENTER) {
expressionEdited();
}
}
});
expressionTA.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
expressionEdited();
}
});
add(expressionTA, BorderLayout.NORTH);
rootExpressionPanel = new ExpressionInnerPanel(_expression) {
@Override
public void representedExpressionChanged(Expression newExpression) {
_expression = newExpression;
update();
}
};
focusReceiver = rootExpressionPanel;
add(rootExpressionPanel, BorderLayout.CENTER);
controls = new JPanel();
controls.setLayout(new FlowLayout());
for (final BinaryOperator o : grammar.getAllSupportedBinaryOperators()) {
JButton b;
try {
b = new JButton(grammar.getSymbol(o));
} catch (OperatorNotSupportedException e1) {
b = new JButton("?");
}
controls.add(b);
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
appendBinaryOperator(o);
}
});
}
for (final UnaryOperator o : grammar.getAllSupportedUnaryOperators()) {
JButton b;
try {
b = new JButton(grammar.getSymbol(o));
} catch (OperatorNotSupportedException e1) {
b = new JButton("?");
}
controls.add(b);
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
appendUnaryOperator(o);
}
});
}
add(controls, BorderLayout.SOUTH);
update();
}
private JavaExpressionPrettyPrinter pp = new JavaExpressionPrettyPrinter();
JavaExpressionParser parser = new JavaExpressionParser();
void update() {
updateExpressionTA();
revalidate();
repaint();
}
void updateExpressionTA() {
expressionTA.setText(pp.getStringRepresentation(_expression));
}
protected static enum KindOfExpression {
BASIC, BINARY_OPERATOR, UNARY_OPERATOR
};
protected abstract class ExpressionInnerPanel extends JPanel {
Expression _representedExpression;
private JTextField variableOrConstantTextField;
JComboBox currentOperatorCB;
// private int depth;
protected ExpressionInnerPanel(Expression expression/*, int depth*/) {
super();
// this.depth = depth;
_representedExpression = expression;
update();
addFocusListeners();
}
/*protected Color getDepthColor()
{
int grayLevel = 255-depth*10;
return new Color(grayLevel,grayLevel,grayLevel);
}*/
private void addFocusListeners() {
addFocusListenersToAllComponentsOf(this);
}
private void addFocusListenersToAllComponentsOf(Component c) {
c.addFocusListener(BindingExpressionPanelQuiMarche.this);
if (c instanceof Container) {
Container container = (Container) c;
for (Component c2 : container.getComponents())
addFocusListenersToAllComponentsOf(c2);
}
}
void textChanged() {
System.out.println("Text has changed for " + variableOrConstantTextField.getText());
try {
Expression newExpression = parser.parse(variableOrConstantTextField.getText(), null);
setRepresentedExpression(newExpression);
} catch (ParseException e) {
System.out.println("ERROR: cannot parse " + variableOrConstantTextField.getText());
}
}
private void addBinaryExpressionVerticalLayout() {
setLayout(new BorderLayout());
BinaryOperatorExpression exp = (BinaryOperatorExpression) _representedExpression;
JPanel operatorPanel = new JPanel();
operatorPanel.setLayout(new BorderLayout());
// operatorPanel.setOpaque(true);
// operatorPanel.setBackground(getDepthColor());
// System.out.println("Color is "+getDepthColor());
currentOperatorCB = new JComboBox(grammar.getAllSupportedBinaryOperators());
currentOperatorCB.setSelectedItem(exp.getOperator());
currentOperatorCB.setRenderer(new ListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
try {
return new JLabel(grammar.getSymbol((BinaryOperator) value));
} catch (OperatorNotSupportedException e) {
return new JLabel("?");
}
}
});
currentOperatorCB.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
BinaryOperatorExpression exp = (BinaryOperatorExpression) _representedExpression;
exp.setOperator((BinaryOperator) currentOperatorCB.getSelectedItem());
BindingExpressionPanelQuiMarche.this.update();
}
});
operatorPanel.add(currentOperatorCB, BorderLayout.CENTER);
add(operatorPanel, BorderLayout.WEST);
operatorPanel.setBorder(BorderFactory.createEtchedBorder());
JPanel argsPanel = new JPanel();
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
argsPanel.setLayout(gridbag);
ExpressionInnerPanel leftArg = new ExpressionInnerPanel(exp.getLeftArgument()/*,depth+1*/) {
@Override
public void representedExpressionChanged(Expression newExpression) {
if (_representedExpression instanceof BinaryOperatorExpression) {
((BinaryOperatorExpression) _representedExpression).setLeftArgument(newExpression);
}
}
};
c.weightx = 1.0;
c.weighty = 1.0;
// c.gridwidth = 1;
// c.gridheight = 1;
c.anchor = GridBagConstraints.NORTH;
c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
gridbag.setConstraints(leftArg, c);
argsPanel.add(leftArg);
ExpressionInnerPanel rightArg = new ExpressionInnerPanel(exp.getRightArgument()/*,depth+1*/) {
@Override
public void representedExpressionChanged(Expression newExpression) {
if (_representedExpression instanceof BinaryOperatorExpression) {
((BinaryOperatorExpression) _representedExpression).setRightArgument(newExpression);
}
}
};
c.weightx = 1.0;
c.weighty = 1.0;
// c.gridwidth = 1;
// c.gridheight = 1;
c.anchor = GridBagConstraints.NORTH;
c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
gridbag.setConstraints(rightArg, c);
argsPanel.add(rightArg);
add(argsPanel, BorderLayout.CENTER);
isHorizontal = false;
}
private boolean isHorizontal = true;
private void addBinaryExpressionHorizontalLayout() {
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridbag);
BinaryOperatorExpression exp = (BinaryOperatorExpression) _representedExpression;
currentOperatorCB = new JComboBox(grammar.getAllSupportedBinaryOperators());
currentOperatorCB.setSelectedItem(exp.getOperator());
currentOperatorCB.setRenderer(new ListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
try {
return new JLabel(grammar.getSymbol((BinaryOperator) value));
} catch (OperatorNotSupportedException e) {
return new JLabel("?");
}
}
});
currentOperatorCB.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
BinaryOperatorExpression exp = (BinaryOperatorExpression) _representedExpression;
exp.setOperator((BinaryOperator) currentOperatorCB.getSelectedItem());
BindingExpressionPanelQuiMarche.this.update();
}
});
ExpressionInnerPanel leftArg = new ExpressionInnerPanel(exp.getLeftArgument()) {
@Override
public void representedExpressionChanged(Expression newExpression) {
if (_representedExpression instanceof BinaryOperatorExpression) {
((BinaryOperatorExpression) _representedExpression).setLeftArgument(newExpression);
}
}
};
c.weightx = 1.0;
c.weighty = 1.0;
// c.gridwidth = 1;
// c.gridheight = 1;
c.anchor = GridBagConstraints.NORTH;
c.fill = GridBagConstraints.BOTH;
gridbag.setConstraints(leftArg, c);
add(leftArg);
c.weightx = 0.0;
c.weighty = 1.0;
// c.gridwidth = 1;
// c.gridheight = 1;
c.anchor = GridBagConstraints.NORTH;
c.fill = GridBagConstraints.VERTICAL;
gridbag.setConstraints(currentOperatorCB, c);
add(currentOperatorCB);
ExpressionInnerPanel rightArg = new ExpressionInnerPanel(exp.getRightArgument()) {
@Override
public void representedExpressionChanged(Expression newExpression) {
if (_representedExpression instanceof BinaryOperatorExpression) {
((BinaryOperatorExpression) _representedExpression).setRightArgument(newExpression);
}
}
};
c.weightx = 1.0;
c.weighty = 1.0;
// c.gridwidth = 1;
// c.gridheight = 1;
c.anchor = GridBagConstraints.NORTH;
c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
gridbag.setConstraints(rightArg, c);
add(rightArg);
}
private void update() {
ExpressionInnerPanel parent = (ExpressionInnerPanel) SwingUtilities.getAncestorOfClass(ExpressionInnerPanel.class, this);
if (parent != null && parent.isHorizontal && parent._representedExpression.getDepth() > 1) {
System.out.println("Le parent doit etre remis bien");
parent.update();
return;
}
removeAll();
if (_representedExpression instanceof Variable || _representedExpression instanceof Constant) {
setLayout(new BorderLayout());
variableOrConstantTextField = new JTextField();
variableOrConstantTextField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
textChanged();
}
});
variableOrConstantTextField.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
textChanged();
}
});
add(variableOrConstantTextField, BorderLayout.CENTER);
if (_representedExpression instanceof Variable) {
variableOrConstantTextField.setText(((Variable) _representedExpression).getName());
} else if (_representedExpression instanceof Constant) {
variableOrConstantTextField.setText(((Constant) _representedExpression).toString());
}
} else if (_representedExpression instanceof BinaryOperatorExpression) {
if (_representedExpression.getDepth() > 1) {
addBinaryExpressionVerticalLayout();
/*BinaryOperatorExpression exp = (BinaryOperatorExpression)_representedExpression;
JPanel operatorPanel = new JPanel();
operatorPanel.setLayout(new BorderLayout());
//operatorPanel.setOpaque(true);
//operatorPanel.setBackground(getDepthColor());
//System.out.println("Color is "+getDepthColor());
currentOperatorCB = new JComboBox(grammar.getAllSupportedBinaryOperators());
currentOperatorCB.setSelectedItem(exp.getOperator());
currentOperatorCB.setRenderer(new ListCellRenderer() {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
try {
return new JLabel(grammar.getSymbol((BinaryOperator)value));
} catch (OperatorNotSupportedException e) {
return new JLabel("?");
}
}
});
currentOperatorCB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
BinaryOperatorExpression exp = (BinaryOperatorExpression)_representedExpression;
exp.setOperator((BinaryOperator)currentOperatorCB.getSelectedItem());
}
});
operatorPanel.add(currentOperatorCB,BorderLayout.CENTER);
add(operatorPanel,BorderLayout.WEST);
operatorPanel.setBorder(BorderFactory.createEtchedBorder());
JPanel argsPanel = new JPanel();
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
argsPanel.setLayout(gridbag);
ExpressionInnerPanel leftArg = new ExpressionInnerPanel(exp.getLeftArgument()){
public void representedExpressionChanged(Expression newExpression) {
if (_representedExpression instanceof BinaryOperatorExpression) {
((BinaryOperatorExpression)_representedExpression).setLeftArgument(newExpression);
}
}
};
c.weightx = 1.0;
c.weighty = 1.0;
//c.gridwidth = 1;
//c.gridheight = 1;
c.anchor = GridBagConstraints.NORTH;
c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
gridbag.setConstraints(leftArg, c);
argsPanel.add(leftArg);
ExpressionInnerPanel rightArg = new ExpressionInnerPanel(exp.getRightArgument()){
public void representedExpressionChanged(Expression newExpression) {
if (_representedExpression instanceof BinaryOperatorExpression) {
((BinaryOperatorExpression)_representedExpression).setRightArgument(newExpression);
}
}
};
c.weightx = 1.0;
c.weighty = 1.0;
//c.gridwidth = 1;
//c.gridheight = 1;
c.anchor = GridBagConstraints.NORTH;
c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
gridbag.setConstraints(rightArg, c);
argsPanel.add(rightArg);
add(argsPanel,BorderLayout.CENTER);*/
} else {
addBinaryExpressionHorizontalLayout();
/*
BinaryOperatorExpression exp = (BinaryOperatorExpression)_representedExpression;
currentOperatorCB = new JComboBox(grammar.getAllSupportedBinaryOperators());
currentOperatorCB.setSelectedItem(exp.getOperator());
currentOperatorCB.setRenderer(new ListCellRenderer() {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
try {
return new JLabel(grammar.getSymbol((BinaryOperator)value));
} catch (OperatorNotSupportedException e) {
return new JLabel("?");
}
}
});
currentOperatorCB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
BinaryOperatorExpression exp = (BinaryOperatorExpression)_representedExpression;
exp.setOperator((BinaryOperator)currentOperatorCB.getSelectedItem());
}
});
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridbag);
ExpressionInnerPanel leftArg = new ExpressionInnerPanel(exp.getLeftArgument()){
public void representedExpressionChanged(Expression newExpression) {
if (_representedExpression instanceof BinaryOperatorExpression) {
((BinaryOperatorExpression)_representedExpression).setLeftArgument(newExpression);
}
}
};
c.weightx = 1.0;
c.weighty = 1.0;
//c.gridwidth = 1;
//c.gridheight = 1;
c.anchor = GridBagConstraints.NORTH;
c.fill = GridBagConstraints.BOTH;
gridbag.setConstraints(leftArg, c);
add(leftArg);
c.weightx = 0.0;
c.weighty = 1.0;
//c.gridwidth = 1;
//c.gridheight = 1;
c.anchor = GridBagConstraints.NORTH;
c.fill = GridBagConstraints.VERTICAL;
gridbag.setConstraints(currentOperatorCB, c);
add(currentOperatorCB);
ExpressionInnerPanel rightArg = new ExpressionInnerPanel(exp.getRightArgument()){
public void representedExpressionChanged(Expression newExpression) {
if (_representedExpression instanceof BinaryOperatorExpression) {
((BinaryOperatorExpression)_representedExpression).setRightArgument(newExpression);
}
}
};
c.weightx = 1.0;
c.weighty = 1.0;
//c.gridwidth = 1;
//c.gridheight = 1;
c.anchor = GridBagConstraints.NORTH;
c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
gridbag.setConstraints(rightArg, c);
add(rightArg);
*/
}
}
revalidate();
repaint();
}
public Expression getRepresentedExpression() {
return _representedExpression;
}
public void setRepresentedExpression(Expression representedExpression) {
_representedExpression = representedExpression;
representedExpressionChanged(representedExpression);
update();
BindingExpressionPanelQuiMarche.this.updateExpressionTA();
}
public abstract void representedExpressionChanged(Expression newExpression);
}
// private JTextField variableOrConstantTextField;
// private JPanel operatorControl;
// private JComboBox binaryOperatorsCB;
// private JComboBox unaryOperatorsCB;
// private JButton deleteButton;
JavaGrammar grammar = new JavaGrammar();
/*private void update()
{
removeAll();
if (_expression instanceof Variable) {
variableOrConstantTextField = new JTextField(((Variable)_expression).getName());
add(variableOrConstantTextField,BorderLayout.CENTER);
}
else if (_expression instanceof Constant) {
variableOrConstantTextField = new JTextField(((Constant)_expression).toString());
add(variableOrConstantTextField,BorderLayout.CENTER);
}
else if (_expression instanceof BinaryOperatorExpression) {
BinaryOperatorExpression exp = (BinaryOperatorExpression)_expression;
JPanel operatorPanel = new JPanel();
operatorPanel.setLayout(new BorderLayout());
JComboBox currentOperatorCB = new JComboBox(grammar.getAllSupportedBinaryOperators());
currentOperatorCB.setSelectedItem(exp.getOperator());
currentOperatorCB.setRenderer(new ListCellRenderer() {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
try {
return new JLabel(grammar.getSymbol((BinaryOperator)value));
} catch (OperatorNotSupportedException e) {
return new JLabel("?");
}
}
});
currentOperatorCB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
}
});
add(currentOperatorCB,BorderLayout.WEST);
JPanel argsPanel = new JPanel();
argsPanel.setLayout(new GridLayout(2,1));
argsPanel.add(new BindingExpressionPanel(exp.getLeftArgument()));
argsPanel.add(new BindingExpressionPanel(exp.getRightArgument()));
add(argsPanel,BorderLayout.CENTER);
}
operatorControl = new JPanel(new FlowLayout());
binaryOperatorsCB = new JComboBox(grammar.getAllSupportedBinaryOperators());
binaryOperatorsCB.setRenderer(new ListCellRenderer() {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
try {
return new JLabel(grammar.getSymbol((BinaryOperator)value));
} catch (OperatorNotSupportedException e) {
return new JLabel("?");
}
}
});
binaryOperatorsCB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
appendBinaryOperator((BinaryOperator)binaryOperatorsCB.getSelectedItem());
}
});
unaryOperatorsCB = new JComboBox(grammar.getAllSupportedUnaryOperators());
unaryOperatorsCB.setRenderer(new ListCellRenderer() {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
try {
return new JLabel(grammar.getSymbol((UnaryOperator)value));
} catch (OperatorNotSupportedException e) {
return new JLabel("?");
}
}
});
unaryOperatorsCB.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
appendUnaryOperator((UnaryOperator)binaryOperatorsCB.getSelectedItem());
}
});
deleteButton = new JButton("X");
operatorControl.add(binaryOperatorsCB);
operatorControl.add(unaryOperatorsCB);
operatorControl.add(deleteButton);
add(operatorControl,BorderLayout.EAST);
revalidate();
repaint();
}*/
void appendBinaryOperator(BinaryOperator operator) {
System.out.println("appendBinaryOperator " + operator);
if (focusReceiver != null) {
Expression newExpression = new BinaryOperatorExpression(operator, focusReceiver.getRepresentedExpression(), new Variable(""));
focusReceiver.setRepresentedExpression(newExpression);
}
}
void appendUnaryOperator(UnaryOperator operator) {
}
private ExpressionInnerPanel focusReceiver = null;
@Override
public void focusGained(FocusEvent e) {
focusReceiver = (ExpressionInnerPanel) SwingUtilities.getAncestorOfClass(ExpressionInnerPanel.class, (Component) e.getSource());
System.out.println("Focus gained by expression " + focusReceiver.getRepresentedExpression());
}
@Override
public void focusLost(FocusEvent e) {
// Dont care
}
}