package xapi.jre.ui.impl; import javafx.collections.ObservableList; import javafx.scene.Group; import javafx.scene.Node; import javafx.scene.Parent; import javafx.scene.layout.Pane; import xapi.ui.api.ElementPosition; import xapi.ui.impl.AbstractUiElement; import xapi.util.X_Debug; /** * Created by james on 6/7/16. */ public class UiElementJavaFx<N extends Node> extends AbstractUiElement<Node, N, UiElementJavaFx<?>> { private final Class<N> elementType; public <Ui extends UiElementJavaFx<N>> UiElementJavaFx(Class<N> elType, Class<Ui> cls) { super(cls); this.elementType = elType; } @Override public N element() { return (N)super.element(); } protected ObservableList<Node> getInsertionPoint() { final N node = element(); assert node instanceof Pane : "Cannot insert into " + this + " as element " + node + " is not a Pane subclass"; return getChildren(node); } @Override public void insertAdjacent(ElementPosition pos, UiElementJavaFx child) { final Node node = element(); final ObservableList<Node> children; switch (pos) { // See https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement for API we are emulating // These two cases insert the new node before/after this element. // Thus, we must be attached to a parent, and insert into it's children nodes case BEFORE_BEGIN: case AFTER_END: final UiElementJavaFx parent = getParent(); children = parent.getInsertionPoint(); final int myPos = children.indexOf(node); assert myPos != -1 : "Trying to insert a child adjacent to a node that is not in its parent's insertion point"; if (pos == ElementPosition.BEFORE_BEGIN) { children.add(myPos, child.element()); } else { children.add(myPos+1, child.element()); } child.setParent(parent); break; case AFTER_BEGIN: case BEFORE_END: children = getInsertionPoint(); if (pos == ElementPosition.AFTER_BEGIN) { children.add(0, child.element()); } else { children.add(children.size(), child.element()); } child.setParent(ui()); break; default: throw new IllegalStateException("Unhandled injection position " + pos + " in " + this); } } @Override public void appendChild(UiElementJavaFx newChild) { getInsertionPoint().add(newChild.element()); newChild.setParent(ui()); } @Override public void removeChild(UiElementJavaFx child) { getInsertionPoint().remove(child.element()); child.setParent(null); } @Override public boolean removeFromParent() { final Parent par = element().getParent(); if (par == null) { return false; } if (getChildren(par).remove(element())) { setParent(null); return true; } return false; } protected ObservableList<Node> getChildren(Node parent) { return getChildList(parent); } public static ObservableList<Node> getChildList(Node parent) { if (parent instanceof Pane) { return ((Pane)parent).getChildren(); } else if (parent instanceof Group) { return ((Group)parent).getChildren(); } else { throw new IllegalArgumentException("Cannot get children of parent " + parent); } } @Override public N initialize() { try { return elementType.newInstance(); } catch (Exception e) { throw X_Debug.rethrow(e); } } public boolean addStyleName(String name) { return element().getStyleClass().add(name); } public boolean removeStyleName(String name) { return element().getStyleClass().remove(name); } }