package nl.utwente.viskell.ui.components;
import com.google.common.collect.ImmutableMap;
import javafx.geometry.Point2D;
import javafx.scene.layout.Region;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import nl.utwente.viskell.haskell.type.Type;
import nl.utwente.viskell.haskell.type.TypeScope;
import nl.utwente.viskell.ui.BlockContainer;
import nl.utwente.viskell.ui.serialize.Bundleable;
import java.util.Map;
import java.util.Optional;
public class ApplyAnchor extends InputAnchor implements FunctionReference {
private int baseArity;
public ApplyAnchor(int baseArity) {
super(); // block is to be set in initializeBlock
this.baseArity = baseArity;
this.setMinSize(60, 24);
this.setMaxSize(60, 24);
this.setPickOnBounds(false);
this.invisibleAnchor = new Rectangle(40, 40);
this.invisibleAnchor.getStyleClass().add("invisTouchZone");
this.invisibleAnchor.setTranslateX(-10);
this.invisibleAnchor.setTranslateY(-20);
this.visibleAnchor = new Rectangle(48, 12);
this.visibleAnchor.setTranslateY(3);
this.visibleAnchor.getStyleClass().add("anchorPoint");
this.visibleAnchor.setMouseTransparent(true);
this.openWire = new Line(0, 0, 0, 8);
this.openWire.setTranslateX(-8);
this.openWire.setTranslateY(-8);
this.openWire.setStrokeWidth(6);
this.getChildren().addAll(this.invisibleAnchor, this.visibleAnchor, this.openWire);
this.refreshedType(baseArity, new TypeScope());
}
public Map<String, Object> toBundleFragment() {
return ImmutableMap.of(
Bundleable.KIND, this.getClass().getSimpleName(),
"arity", this.baseArity
);
}
public static ApplyAnchor fromBundleFragment(Map<String, Object> bundleFragment) {
int arity = ((Double)bundleFragment.get("arity")).intValue();
return new ApplyAnchor(arity);
}
@Override
public void initializeBlock(Block funBlock) {
this.block = funBlock;
}
@Override
public Optional<InputAnchor> getInputAnchor() {
return Optional.of(this);
}
@Override
public Point2D getAttachmentPoint() {
return this.getPane().sceneToLocal(this.localToScene(new Point2D(22, 8)));
}
@Override
public int requiredArguments() {
if (this.hasConnection()) {
return this.getType().countArguments();
} else {
return this.baseArity;
}
}
@Override
public Type refreshedType(int argCount, TypeScope scope) {
if (argCount < 1) {
return scope.getVar("xr");
}
Type res = Type.fun(scope.getVar("a_0"), scope.getVar("xr"));
for (int i = argCount-1; i > 0 ; i--) {
res = Type.fun(scope.getVar("a_"+i), res);
}
this.setFreshRequiredType(res, scope);
return res;
}
@Override
public Region asRegion() {
return this;
}
@Override
public FunctionReference getNewCopy() {
return new ApplyAnchor(this.requiredArguments());
}
@Override
public String getName() {
return "@pply_" + this.hashCode();
}
@Override
public boolean isScopeCorrectIn(BlockContainer container) {
return true; // don't care for now, scope errors are already shown on the anchor itself
}
@Override
public void deleteLinks() {
this.removeConnections();
}
}