package jp.ac.aiit.jointry.models.blocks.expression;
import java.util.HashMap;
import java.util.Map;
import javafx.collections.FXCollections;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import jp.ac.aiit.jointry.controllers.ResizePane;
import jp.ac.aiit.jointry.models.Status;
import jp.ac.aiit.jointry.models.blocks.Block;
import jp.ac.aiit.jointry.models.blocks.Connector;
import jp.ac.aiit.jointry.models.blocks.statement.codeblock.CodeBlock;
import jp.ac.aiit.jointry.models.blocks.statement.codeblock.If;
import jp.ac.aiit.jointry.models.blocks.statement.codeblock.While;
import jp.ac.aiit.jointry.services.broker.app.BlockDialog;
import static jp.ac.aiit.jointry.services.broker.app.JointryCommon.M_BLOCK_ADDEMBRYO;
import static jp.ac.aiit.jointry.services.broker.app.JointryCommon.M_BLOCK_MOVE;
import jp.ac.aiit.jointry.util.BlockUtil;
public class Condition extends Expression {
protected final Rectangle rect;
public CodeBlock mother;
public Condition myBlock;
public Connector topCon;
public Connector bottomCon;
public Connector leftCon;
public Connector rightCon;
public Connector leftVariableCon;
public Connector rightVariableCon;
protected TextField tf1;
protected TextField tf2;
protected ComboBox cb;
public Variable leftVariable;
public Variable rightVariable;
private Map<String, String> operation = new HashMap<>();
public Condition() {
super();
myBlock = this;
operation.put("==", " == ");
operation.put("!=", " != ");
operation.put("<", " < ");
operation.put(">", " >");
operation.put(">=", " >= ");
operation.put("<=", " <= ");
// Use Filter (not Handler) to fire first.
addEventFilter(MouseEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
initializeLink();
// Move
double dx = mouseEvent.getSceneX() + anchorX;
double dy = mouseEvent.getSceneY() + anchorY;
move(dx, dy);
BlockDialog.sendMessage(M_BLOCK_MOVE, myBlock);
if (getCollision() == null) {
return;
}
// 内部の接続
CodeBlock target = (CodeBlock) con.getHolder();
target.accept(myBlock);
BlockDialog.sendMessage(M_BLOCK_ADDEMBRYO, myBlock);
}
});
rect = new Rectangle();
rect.setWidth(200);
rect.setHeight(BASIC_HEIGHT + 10);
rect.setArcWidth(10);
rect.setArcHeight(10);
rect.setStroke(Color.GRAY);
rect.setFill(getColor());
AnchorPane.setTopAnchor(rect, 0.0);
Label lb = this.getLabel();
AnchorPane.setTopAnchor(lb, 5.0);
AnchorPane.setLeftAnchor(lb, 10.0);
tf1 = new TextField();
tf1.setPrefWidth(50.0);
AnchorPane.setTopAnchor(tf1, 22.0);
AnchorPane.setLeftAnchor(tf1, 10.0);
tf2 = new TextField();
tf2.setPrefWidth(50.0);
AnchorPane.setTopAnchor(tf2, 22.0);
AnchorPane.setRightAnchor(tf2, 10.0);
getChildren().addAll(rect, lb, tf1, tf2);
setChangeListener(tf1);
setChangeListener(tf2);
cb = new ComboBox();
cb.setItems(FXCollections.observableArrayList(operation.keySet()));
AnchorPane.setTopAnchor(cb, 22.0);
AnchorPane.setLeftAnchor(cb, 66.0);
cb.setPrefSize(70, 20);
getChildren().addAll(cb);
setChangeListener(cb);
// コネクタを全面に出すために
rect.toBack();
makeConnectors();
}
@Override
public void initializeLink() {
if (mother != null) {
mother.embryo = null;
mother = null;
}
}
public static Color getColor() {
return Color.web("E4CD9E");
}
@Override
public Label getLabel() {
return new Label("じょうけん");
}
public Connector getCollision() {
Connector connector = null;
BorderPane root = (BorderPane) getScene().getRoot();
TabPane tabs = (TabPane) root.getCenter();
for (Tab tab : tabs.getTabs()) {
if (tab == null) {
continue;
}
if (!"scriptContent".equals(tab.getContent().getId())) {
continue;
}
// Inside scriptPane
ResizePane pane = (ResizePane) tab.getContent();
Pane scriptPane = (Pane) pane.getContent();
for (Node node : scriptPane.getChildren()) {
if (node == myBlock) {
continue;
}
if (!(node instanceof If) && !(node instanceof While)) {
continue;
}
// Inside Block
Block target = (Block) node;
for (Node n : target.getChildren()) {
if (n instanceof Connector) {
Connector c = (Connector) n;
c.detouch();
Shape intersect = null;
// 内部の接触
intersect = Shape.intersect(c, myBlock.leftCon);
if (intersect.getBoundsInLocal().getWidth() != -1) {
if (c.getPosition() == Connector.Position.CENTER) {
connector = c;
break;
}
}
}
}
}
}
setConnector(connector);
return connector;
}
private void makeConnectors() {
// Connectors
this.leftCon = new Connector();
leftCon.detouch();
leftCon.setWidth(10);
leftCon.setHeight(50);
leftCon.setHolder(myBlock);
leftCon.setPosition(Connector.Position.LEFT);
AnchorPane.setLeftAnchor(leftCon, 0.0);
// Variable
this.leftVariableCon = new Connector();
leftVariableCon.detouch();
leftVariableCon.setWidth(50);
leftVariableCon.setHeight(2);
leftVariableCon.setHolder(myBlock);
leftVariableCon.setPosition(Connector.Position.INSIDE_LEFT);
AnchorPane.setTopAnchor(leftVariableCon, 22.0);
AnchorPane.setLeftAnchor(leftVariableCon, 10.0);
// Variable
this.rightVariableCon = new Connector();
rightVariableCon.detouch();
rightVariableCon.setWidth(50);
rightVariableCon.setHeight(2);
rightVariableCon.setHolder(myBlock);
rightVariableCon.setPosition(Connector.Position.INSIDE_RIGHT);
AnchorPane.setTopAnchor(rightVariableCon, 22.0);
AnchorPane.setRightAnchor(rightVariableCon, 10.0);
getChildren().addAll(leftCon, leftVariableCon, rightVariableCon);
}
@Override
public String intern() {
StringBuilder sb = new StringBuilder();
// left
if (leftVariable != null) {
sb.append(leftVariable.intern());
} else {
try {
// As number
sb.append(Integer.parseInt(tf1.getText()));
} catch (NumberFormatException nfe) {
// As String
sb.append("\"");
sb.append(tf1.getText());
sb.append("\"");
}
}
// op
sb.append(getOperation());
// right
if (rightVariable != null) {
sb.append(rightVariable.intern());
} else {
try {
// As number
sb.append(Integer.parseInt(tf2.getText()));
} catch (NumberFormatException nfe) {
// As String
sb.append("\"");
sb.append(tf2.getText());
sb.append("\"");
}
}
return sb.toString();
}
public String getOperation() {
String op = (String) cb.getValue();
return operation.get(op);
}
@Override
public Status getStatus() {
Status status = new Status();
status.put("id", this.getUUID());
//left
if (leftVariable != null) {
status.put("left", leftVariable.getStatus());
} else {
status.put("left", tf1.getText());
}
//op
status.put("op", cb.getValue());
//right
if (rightVariable != null) {
status.put("right", rightVariable.getStatus());
} else {
status.put("right", tf2.getText());
}
return status;
}
@Override
public void setStatus(Status status) {
changeable = false; //一時的にリスナーを無効化
this.setUUID((String) status.get("id"));
for (Object key : status.keySet()) {
if (key.equals("left")) {
Object value = status.get(key);
if (value instanceof String) {
tf1.setText((String) value); //テキスト
} else {
//変数ブロック
Variable variable = (Variable) BlockUtil.create("Variable");
variable.setSprite(getSprite());
variable.setStatus(BlockUtil.convertMapToStatus(value));
setLeftVariable(variable);
}
} else if (key.equals("op")) {
cb.setValue(status.get(key));
} else if (key.equals("right")) {
Object value = status.get(key);
if (value instanceof String) {
//テキスト
tf2.setText((String) value);
} else {
//変数ブロック
Variable variable = (Variable) BlockUtil.create("Variable");
variable.setSprite(getSprite());
variable.setStatus(BlockUtil.convertMapToStatus(value));
setRightVariable(variable);
}
}
}
changeable = true;
}
@Override
public void show() {
getSprite().getScriptPane().getChildren().add(this);
if (leftVariable != null) {
leftVariable.show();
}
if (rightVariable != null) {
rightVariable.show();
}
}
public void setLeftVariable(Variable v) {
this.leftVariable = v;
if (v != null) {
v.mother = this;
}
}
public void setRightVariable(Variable v) {
this.rightVariable = v;
if (v != null) {
v.mother = this;
}
}
@Override
public void move(double dx, double dy) {
super.move(dx, dy);
if (leftVariable != null) {
leftVariable.toFront();
leftVariable.move(dx + 10, dy + 22);
}
if (rightVariable != null) {
rightVariable.toFront();
rightVariable.move(dx + 140, dy + 22);
}
}
@Override
public void remove() {
super.remove();
if (mother != null) {
mother.embryo = null;
}
}
@Override
public boolean hasMother() {
return (mother != null);
}
}