/**
* @file .java
* @author Anderson Antunes <anderson.utf@gmail.com>
* *seu nome* <*seu email*>
* @version 1.0
*
* @section LICENSE
*
* Copyright (C) 2013 by Anderson Antunes <anderson.utf@gmail.com>
* *seu nome* <*seu email*>
*
* RobotInterface 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.
*
* RobotInterface 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
* RobotInterface. If not, see <http://www.gnu.org/licenses/>.
*
*/
package robotinterface.algorithm.procedure;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JTextField;
import robotinterface.algorithm.Command;
import static robotinterface.algorithm.Command.identChar;
import robotinterface.algorithm.GraphicFlowchart;
import robotinterface.algorithm.parser.parameterparser.Argument;
import static robotinterface.algorithm.procedure.DummyBlock.createSimpleBlock;
import robotinterface.drawable.swing.DrawableProcedureBlock;
import robotinterface.drawable.GraphicObject;
import robotinterface.drawable.swing.MutableWidgetContainer;
import robotinterface.drawable.swing.component.WidgetLine;
import robotinterface.drawable.swing.component.TextLabel;
import robotinterface.drawable.swing.component.Widget;
import robotinterface.drawable.graphicresource.GraphicResource;
import robotinterface.drawable.swing.component.Component;
import robotinterface.gui.GUI;
import robotinterface.interpreter.ExecutionException;
import robotinterface.interpreter.Interpreter;
import robotinterface.interpreter.ResourceManager;
/**
* Função com *futuro* suporte a argumentos. <### EM DESENVOLVIMENTO ###>
*/
public class Function extends Block {
public class FunctionEnd extends BlockEnd {
protected FunctionEnd() {
}
private GraphicObject resource = null;
@Override
public GraphicObject getDrawableResource() {
if (resource == null) {
resource = createSimpleBlock(this, " END ", Color.black, Color.decode("#631864"));
}
return resource;
}
@Override
public Command step(ResourceManager rm) {
return null;
}
@Override
public void toString(String ident, StringBuilder sb) {
}
}
private String name = "prog";
private ArrayList<String> args;
public Function() {
super.setEnd(new FunctionEnd());
//super(new FunctionEnd());
args = new ArrayList<>();
}
public Function(String name, String args) {
this();
this.name = name;
updateFunction(name, args, this);
}
private static void updateFunction(String name, String args, Function f) {
f.setName(name);
f.getArgs().clear();
if (args != null) {
for (String arg : args.split(",")) {
arg = arg.replace("var", "").trim();
// f.getArgs().add(arg);
}
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// public Collection<String> getArgs() {
// return args;
// }
public void addArgs(Collection<String> args) {
this.args.addAll(args);
}
public void removeArg(String arg) {
args.remove(arg);
}
@Override
public boolean addBefore(Command c) {
return true;
//return super.addBegin(c);
}
@Override
public boolean addAfter(Command c) {
return true;
//return super.addBegin(c);
}
public static final int ARR_SIZE = 7;
public static void drawArrow(Graphics2D g, int x1, int y1, int x2, int y2) {
// g.setStroke(new BasicStroke(2));
double dx = x2 - x1, dy = y2 - y1;
double angle = Math.atan2(dy, dx);
int len = (int) Math.sqrt(dx * dx + dy * dy);
AffineTransform o = (AffineTransform) g.getTransform().clone();
AffineTransform at = AffineTransform.getTranslateInstance(x1, y1);
at.concatenate(AffineTransform.getRotateInstance(angle));
g.transform(at);
// Draw horizontal arrow starting in (0, 0)
// g.backDraw(0, 0, len - ARR_SIZE, 0);
g.fillPolygon(new int[]{len, len - ARR_SIZE, len - ARR_SIZE, len},
new int[]{0, (int) (-ARR_SIZE * .5), (int) (ARR_SIZE * .5), 0}, 4);
at.setToIdentity();
g.setTransform(o);
}
public static void drawArrow(Graphics2D g, Line2D l, boolean drawLine) {
double dx = l.getX2() - l.getX1();
double dy = l.getY2() - l.getY1();
double angle = Math.atan2(dy, dx);
int len = (int) Math.sqrt(dx * dx + dy * dy);
AffineTransform o = (AffineTransform) g.getTransform().clone();
AffineTransform at = AffineTransform.getTranslateInstance(l.getX1(), l.getY1());
at.concatenate(AffineTransform.getRotateInstance(angle));
g.transform(at);
// Draw horizontal arrow starting in (0, 0)
if (drawLine) {
g.drawLine(0, 0, len - ARR_SIZE, 0);
}
g.fillPolygon(new int[]{len, len - ARR_SIZE, len - ARR_SIZE, len},
new int[]{0, (int) (-ARR_SIZE * .5), (int) (ARR_SIZE * .5), 0}, 4);
at.setToIdentity();
g.setTransform(o);
}
private static Command boundaryTest(Point2D p, Command it) {
if (it.getBounds(null, GraphicFlowchart.GF_J, GraphicFlowchart.GF_K).contains(p)) {
return it;
}
return null;
}
public static Command find(Point2D p, Block b) {
Command it = b.start;
while (it != null) {
if (it instanceof GraphicResource) {
GraphicObject d = ((GraphicResource) it).getDrawableResource();
if (d != null) {
if (d.getObjectShape().contains(p)) {
return it;
}
}
}
if (it instanceof Block) {
Command c = find(p, (Block) it);
if (c != null) {
return c;
}
//TESTE
//c = boundaryTest(p, it);
if (c != null) {
return c;
}
} else if (it instanceof If) {
Command c = find(p, ((If) it).getBlockTrue());
if (c != null) {
return c;
}
c = find(p, ((If) it).getBlockFalse());
if (c != null) {
return c;
}
//TESTE
//c = boundaryTest(p, it);
if (c != null) {
return c;
}
}
it = it.getNext();
}
return null;
}
public Command find(Point2D p) {
if (getDrawableResource().getObjectShape().contains(p)) {
return this;
}
return Function.find(p, this);
}
Rectangle2D.Double shape = new Rectangle2D.Double();
static ArrayList<Rectangle2D.Double> tmpBounds = new ArrayList<>();
static ArrayList<String> tmpBoundsName = new ArrayList<>();
public static Shape smothConer(Line2D.Double l1, Line2D.Double l2, double i) {
GeneralPath gp = new GeneralPath();
double s1 = Math.sqrt((l1.x2 - l1.x1) * (l1.x2 - l1.x1) + (l1.y2 - l1.y1) * (l1.y2 - l1.y1));
double s2 = Math.sqrt((l2.x2 - l2.x1) * (l2.x2 - l2.x1) + (l2.y2 - l2.y1) * (l2.y2 - l2.y1));
if (s1 > s2) {
double t = s1;
s1 = s2;
s2 = t;
}
gp.moveTo(l1.x1, l1.y1);
gp.lineTo((1 - i) * l1.x1 + i * l1.x2, (1 - i) * l1.y1 + i * l1.y2);
i = ((s2 - s1) / s2) * (1 - i) + i;
gp.quadTo(l1.x2, l1.y2, (1 - i) * l2.x2 + i * l2.x1, (1 - i) * l2.y2 + i * l2.y1);
gp.lineTo(l2.x2, l2.y2);
return gp;
}
@Override
public Procedure copy(Procedure copy) {
Procedure p = super.copy(copy);
if (copy instanceof Function) {
((Function) copy).name = name;
//TODO: copiar argumentos e etc
} else {
System.out.println("Erro ao copiar: ");
print();
}
return p;
}
public Function copy() {
return (Function) copy((Procedure) new Function());
}
@Override
public void toString(String ident, StringBuilder sb) {
sb.append(ident).append("func ").append(name).append("(").append("").append(") {\n");
Command it = start;
while (it != null) {
it.toString(ident + identChar, sb);
it = it.getNext();
}
sb.append(ident).append("}\n");
}
public static MutableWidgetContainer createDrawableFunction(final Function f) {
final JTextField tfName = new JTextField();
final int TEXTFIELD_WIDTH = 100;
final int TEXTFIELD_HEIGHT = 25;
final int BUTTON_WIDTH = 25;
//HEADER LINE
final WidgetLine headerLine = new WidgetLine() {
@Override
public void createRow(Collection<Component> components, final MutableWidgetContainer container, int index) {
components.add(new TextLabel("Função:", true));
components.add(new TextLabel("Nome:"));
tfName.setText(f.name);
components.add(new Widget(tfName, TEXTFIELD_WIDTH + 20, TEXTFIELD_HEIGHT));
}
@Override
public void toString(StringBuilder sb, ArrayList<Argument> arguments, MutableWidgetContainer container) {
f.name = tfName.getText();
f.args.clear();
sb.append(f.name).append(" (");
}
};
//LINES
final WidgetLine argumentLine = new WidgetLine() {
private int argN = 0;
@Override
public void createRow(Collection<Component> components, final MutableWidgetContainer container, int index) {
JTextField txArg = new JTextField();
argN++;
components.add(new TextLabel(argN + ":"));
components.add(new Widget(txArg, TEXTFIELD_WIDTH, TEXTFIELD_HEIGHT));
}
@Override
public void toString(StringBuilder sb, ArrayList<Argument> arguments, MutableWidgetContainer container) {
// if (widgets.size() > 0) {
// try {
// StringBuilder sb = new StringBuilder();
// Iterator<Widget> iterator = widgets.iterator();
// String str;
// Widget tmpWidget;
// JComponent jComponent;
// //JTextField 1
// tmpWidget = iterator.next();
// jComponent = tmpWidget.getJComponent();
// if (jComponent instanceof JTextField) {
// str = ((JTextField) jComponent).getText();
// if (!str.isEmpty()) {
// if (!f.args.isEmpty()) {
// sb.append(", ");
// }
//
// sb.append("var ");
// sb.append(str);
// f.args.add(str);
// }
// }
// return sb.toString();
// } catch (NoSuchElementException e) {
// e.printStackTrace();
// }
// }
// return "";
}
};
//END LINE
final WidgetLine endLine = new WidgetLine(true) {
private Widget addButton;
private Widget remButton;
@Override
public void createRow(Collection<Component> components, final MutableWidgetContainer container, int index) {
JButton bTmp = new JButton("+");
bTmp.setEnabled(false); //temporario
bTmp.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
container.addLine(argumentLine);
//desconta headerLine e endLine
int size = container.getSize() - 2;
if (size > 1) {
JButton btn = (JButton) remButton.getJComponent();
btn.setEnabled(true);
}
}
});
addButton = new Widget(bTmp, BUTTON_WIDTH, TEXTFIELD_HEIGHT);
bTmp = new JButton("-");
bTmp.setEnabled(false);
bTmp.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//desconta headerLine e endLine
int size = container.getSize() - 2;
if (size > 1) {
container.removeLine(size);
}
if (size - 1 == 1) {
JButton btn = (JButton) remButton.getJComponent();
btn.setEnabled(false);
}
}
});
remButton = new Widget(bTmp, BUTTON_WIDTH, TEXTFIELD_HEIGHT);
components.add(addButton);
components.add(remButton);
}
};
final WidgetLine nullLine = new WidgetLine() {
@Override
public void createRow(Collection<Component> components, final MutableWidgetContainer container, int index) {
components.add(new TextLabel("Argumentos:"));
}
};
DrawableProcedureBlock dcb = new DrawableProcedureBlock(f, Color.decode("#E6A82E")) {
public static final int EXTENDED_HEIGHT = 15;
public static final int SIMPLE_HEIGHT = 20;
public static final int SIMPLE_WIDTH = 20;
{
updateStructure();
center = true;
}
@Override
public void updateStructure() {
//exclui todas as linhas
clear();
//adiciona cabeçalho
addLine(headerLine);
//adiciona uma nova linha sem dados
addLine(nullLine);
for (String arg : f.args) {
addLine(argumentLine);
}
addLine(endLine);
boxLabel = getBoxLabel();
//CUIDADO
GUI.getInstance().updateTabNames();
}
public void splitBoxLabel(String original, Collection<String> splitted) {
splitted.add(original);
}
@Override
public String getBoxLabel() {
String str = super.getBoxLabel();
//CUIDADO
GUI.getInstance().updateTabNames();
return "func " + str.trim() + ") : ";
}
};
return dcb;
}
private GraphicObject resource = null;
@Override
public GraphicObject getDrawableResource() {
if (resource == null) {
//resource = createDrawableFunction(this);
resource = createSimpleBlock(this, " BEGIN ", Color.black, Color.decode("#631864"));
}
return resource;
}
@Override
public void drawLines(Graphics2D g) {
GraphicObject resource = getDrawableResource();
if (resource != null) {
Command c = super.start;
if (c instanceof GraphicResource) {
GraphicObject d = ((GraphicResource) c).getDrawableResource();
if (d != null) {
Rectangle2D.Double bThis = resource.getObjectBouds();
Rectangle2D.Double bStart = d.getObjectBouds();
Line2D.Double l = new Line2D.Double(bThis.getCenterX(), bThis.getMaxY(), bStart.getCenterX(), bStart.getMinY());
g.draw(l);
}
}
}
}
}