package electrosphere.renderer.ui.elements; import java.util.LinkedList; import java.util.List; import org.lwjgl.util.yoga.Yoga; import electrosphere.engine.Globals; import electrosphere.engine.signal.Signal.SignalType; import electrosphere.logger.LoggerInterface; import electrosphere.renderer.ui.elementtypes.ContainerElement; import electrosphere.renderer.ui.elementtypes.DrawableElement; import electrosphere.renderer.ui.elementtypes.Element; /** * An element that contains other elements */ public class StandardContainerElement extends StandardElement implements ContainerElement { List childList = new LinkedList(); public StandardContainerElement(){ super(); } @Override public int getWidth() { if(width == -1){ if(childList.size() > 0){ int minX = -1; int maxX = -1; for(Element child : childList){ if(minX == -1){ minX = child.getRelativeX(); } else if(child.getRelativeX() < minX){ minX = child.getRelativeX(); } if(maxX == -1){ maxX = child.getRelativeX() + child.getWidth(); } else if(child.getRelativeX() + child.getWidth() > maxX){ maxX = child.getRelativeX() + child.getWidth(); } } if(minX == -1){ minX = 0; } if(maxX == -1){ maxX = 0; } return maxX - minX; } else { return 1; } } else { return width; } } @Override public int getHeight() { if(height == -1){ if(childList.size() > 0){ int minY = -1; int maxY = -1; for(Element child : childList){ if(minY == -1){ minY = child.getRelativeY(); } else if(child.getRelativeY() < minY){ minY = child.getRelativeY(); } if(maxY == -1){ maxY = child.getRelativeY() + child.getHeight(); } else if(child.getRelativeY() + child.getHeight() > maxY){ maxY = child.getRelativeY() + child.getHeight(); } } if(minY == -1){ minY = 0; } if(maxY == -1){ maxY = 0; } return maxY - minY; } else { return 1; } } else { return height; } } @Override public int getRelativeX() { if(internalPositionX == -1){ if(childList.size() > 0){ int minX = -1; for(Element child : childList){ if(minX == -1){ minX = child.getRelativeX(); } else if(child.getRelativeX() < minX){ minX = child.getRelativeX(); } } if(minX == -1){ minX = 0; } return minX; } else { return internalPositionX; } } else { return internalPositionX; } } @Override public int getRelativeY() { if(internalPositionY == -1){ if(childList.size() > 0){ int minY = -1; for(Element child : childList){ if(minY == -1){ minY = child.getRelativeY(); } else if(child.getRelativeY() < minY){ minY = child.getRelativeY(); } } if(minY == -1){ minY = 0; } return minY; } else { return internalPositionY; } } else { return internalPositionY; } } @Override public void setPositionX(int posX) { internalPositionX = posX; absoluteX = posX; } @Override public void setPositionY(int posY) { internalPositionY = posY; absoluteY = posY; } @Override public void setDirection(int layout) { Yoga.YGNodeStyleSetDirection(yogaNode, layout); } @Override public void setFlexDirection(YogaFlexDirection layout){ int directionInteger = Yoga.YGFlexDirectionColumn; switch(layout){ case Column: directionInteger = Yoga.YGFlexDirectionColumn; break; case Column_Reverse: directionInteger = Yoga.YGFlexDirectionColumnReverse; break; case Row: directionInteger = Yoga.YGFlexDirectionRow; break; case Row_Reverse: directionInteger = Yoga.YGFlexDirectionRowReverse; break; } Yoga.YGNodeStyleSetFlexDirection(yogaNode, directionInteger); } @Override public void addChild(Element child) { childList.add(child); child.setParent(this); if(child instanceof DrawableElement){ DrawableElement drawableChild = (DrawableElement) child; drawableChild.setParentWidth(width); drawableChild.setParentHeight(height); drawableChild.setVisible(true); Yoga.YGNodeInsertChild(yogaNode, drawableChild.getYogaNode(), childList.size() - 1); } } @Override public List getChildren() { return childList; } @Override public void removeChild(Element child) { childList.remove(child); child.setParent(null); Yoga.YGNodeRemoveChild(this.yogaNode, child.getYogaNode()); } @Override public void clearChildren(){ Yoga.YGNodeRemoveAllChildren(yogaNode); childList.clear(); } @Override public int getChildOffsetX(){ return 0; } @Override public int getChildOffsetY(){ return 0; } @Override public float getChildScaleX(){ return 1; } @Override public float getChildScaleY(){ return 1; } @Override public void destroy(){ for(Element child : childList){ Globals.signalSystem.post(SignalType.YOGA_DESTROY, child); } if(this.yogaNode != Element.NULL_YOGA_ELEMENT){ Yoga.YGNodeFree(this.yogaNode); this.yogaNode = Element.NULL_YOGA_ELEMENT; } } @Override public void applyYoga(int parentX, int parentY) { if(this.yogaNode != Element.NULL_YOGA_ELEMENT){ //get the values from yoga float leftRaw = Yoga.YGNodeLayoutGetLeft(yogaNode); float topRaw = Yoga.YGNodeLayoutGetTop(yogaNode); float widthRaw = Yoga.YGNodeLayoutGetWidth(yogaNode); if(!Float.isFinite(widthRaw)){ widthRaw = 0; } float heightRaw = Yoga.YGNodeLayoutGetHeight(yogaNode); if(!Float.isFinite(heightRaw)){ heightRaw = 0; } LoggerInterface.loggerUI.DEBUG("" + this); LoggerInterface.loggerUI.DEBUG("pos(" + leftRaw + "," + topRaw + ") dim(" + widthRaw + "," + heightRaw + ")"); //apply the values to this component if(!useAbsolutePosition){ this.internalPositionX = (int)leftRaw; this.internalPositionY = (int)topRaw; this.internalWidth = (int)widthRaw; this.internalHeight = (int)heightRaw; //calculate absolute values this.absoluteX = parentX + internalPositionX; this.absoluteY = parentY + internalPositionY; } //apply yoga values to all children for(Element child : this.getChildren()){ child.applyYoga(parentX + internalPositionX,parentY + internalPositionY); } } } @Override public void setJustifyContent(YogaJustification justification){ int justificationInteger = Yoga.YGJustifyFlexStart; switch(justification){ case Center: justificationInteger = Yoga.YGJustifyCenter; break; case Start: justificationInteger = Yoga.YGJustifyFlexStart; break; case End: justificationInteger = Yoga.YGJustifyFlexEnd; break; case Around: justificationInteger = Yoga.YGJustifySpaceAround; break; case Between: justificationInteger = Yoga.YGJustifySpaceBetween; break; case Evenly: justificationInteger = Yoga.YGJustifySpaceEvenly; break; } Yoga.YGNodeStyleSetJustifyContent(this.yogaNode, justificationInteger); } @Override public void setAlignItems(YogaAlignment alignment){ int alignmentInteger = Yoga.YGAlignAuto; switch(alignment){ case Auto: alignmentInteger = Yoga.YGAlignAuto; break; case Start: alignmentInteger = Yoga.YGAlignFlexStart; break; case End: alignmentInteger = Yoga.YGAlignFlexEnd; break; case Around: alignmentInteger = Yoga.YGAlignSpaceAround; break; case Between: alignmentInteger = Yoga.YGAlignSpaceBetween; break; case Stretch: alignmentInteger = Yoga.YGAlignStretch; break; case Baseline: alignmentInteger = Yoga.YGAlignBaseline; break; case Center: alignmentInteger = Yoga.YGAlignCenter; break; } Yoga.YGNodeStyleSetAlignItems(this.yogaNode, alignmentInteger); } @Override public void setAlignContent(YogaAlignment alignment){ int alignmentInteger = Yoga.YGAlignAuto; switch(alignment){ case Auto: alignmentInteger = Yoga.YGAlignAuto; break; case Start: alignmentInteger = Yoga.YGAlignFlexStart; break; case End: alignmentInteger = Yoga.YGAlignFlexEnd; break; case Around: alignmentInteger = Yoga.YGAlignSpaceAround; break; case Between: alignmentInteger = Yoga.YGAlignSpaceBetween; break; case Stretch: alignmentInteger = Yoga.YGAlignStretch; break; case Baseline: alignmentInteger = Yoga.YGAlignBaseline; break; case Center: alignmentInteger = Yoga.YGAlignCenter; break; } Yoga.YGNodeStyleSetAlignContent(this.yogaNode, alignmentInteger); } @Override public void setWrap(YogaWrap wrap) { switch(wrap){ case WRAP: Yoga.YGNodeStyleSetFlexWrap(yogaNode, Yoga.YGWrapWrap); break; case NO_WRAP: Yoga.YGNodeStyleSetFlexWrap(yogaNode, Yoga.YGWrapNoWrap); break; case REVERSE: Yoga.YGNodeStyleSetFlexWrap(yogaNode, Yoga.YGWrapReverse); break; } } @Override public void setOverflow(YogaOverflow overflow){ switch(overflow){ case Visible: Yoga.YGNodeStyleSetOverflow(yogaNode, Yoga.YGOverflowVisible); break; case Hidden: Yoga.YGNodeStyleSetOverflow(yogaNode, Yoga.YGOverflowHidden); break; case Scroll: Yoga.YGNodeStyleSetOverflow(yogaNode, Yoga.YGOverflowScroll); break; } } }