package electrosphere.renderer.ui.elements; import java.util.LinkedList; import java.util.List; import org.joml.Vector3f; import electrosphere.engine.Globals; import electrosphere.renderer.OpenGLState; import electrosphere.renderer.RenderPipelineState; import electrosphere.renderer.debug.DebugRendering; import electrosphere.renderer.ui.elementtypes.ClickableElement; import electrosphere.renderer.ui.elementtypes.ContainerElement; import electrosphere.renderer.ui.elementtypes.DraggableElement; import electrosphere.renderer.ui.elementtypes.DrawableElement; import electrosphere.renderer.ui.elementtypes.Element; import electrosphere.renderer.ui.elementtypes.FocusableElement; import electrosphere.renderer.ui.elementtypes.NavigableElement; import electrosphere.renderer.ui.events.ClickEvent; import electrosphere.renderer.ui.events.DragEvent; import electrosphere.renderer.ui.events.DragEvent.DragEventType; import electrosphere.renderer.ui.events.Event; import electrosphere.renderer.ui.events.FocusEvent; import electrosphere.renderer.ui.events.NavigationEvent; public class Div implements ClickableElement,ContainerElement,DraggableElement,FocusableElement,DrawableElement,NavigableElement { ClickEventCallback onClick; FocusEventCallback onFocus; FocusEventCallback onLoseFocus; DragEventCallback onDragStart; DragEventCallback onDrag; DragEventCallback onDragRelease; NavigationEventCallback onNavigate; boolean focused = false; List childList = new LinkedList(); public int width = -1; public int height = -1; public int positionX = -1; public int positionY = -1; public int parentWidth = 1; public int parentHeight = 1; public boolean visible = false; static final Vector3f windowDrawDebugColor = new Vector3f(1.0f,1.0f,1.0f); @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.getPositionX(); } else if(child.getPositionX() < minX){ minX = child.getPositionX(); } if(maxX == -1){ maxX = child.getPositionX() + child.getWidth(); } else if(child.getPositionX() + child.getWidth() > maxX){ maxX = child.getPositionX() + 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.getPositionY(); } else if(child.getPositionY() < minY){ minY = child.getPositionY(); } if(maxY == -1){ maxY = child.getPositionY() + child.getHeight(); } else if(child.getPositionY() + child.getHeight() > maxY){ maxY = child.getPositionY() + child.getHeight(); } } if(minY == -1){ minY = 0; } if(maxY == -1){ maxY = 0; } return maxY - minY; } else { return 1; } } else { return height; } } @Override public int getPositionX() { if(positionX == -1){ if(childList.size() > 0){ int minX = -1; for(Element child : childList){ if(minX == -1){ minX = child.getPositionX(); } else if(child.getPositionX() < minX){ minX = child.getPositionX(); } } if(minX == -1){ minX = 0; } return minX; } else { return 0; } } else { return positionX; } } @Override public int getPositionY() { if(positionY == -1){ if(childList.size() > 0){ int minY = -1; for(Element child : childList){ if(minY == -1){ minY = child.getPositionY(); } else if(child.getPositionY() < minY){ minY = child.getPositionY(); } } if(minY == -1){ minY = 0; } return minY; } else { return 0; } } else { return positionY; } } @Override public void setWidth(int width) { this.width = width; } @Override public void setHeight(int height) { this.height = height; } @Override public void setPositionX(int posX) { int deltaX = posX - getPositionX(); this.positionX = posX; for(Element child : childList){ child.setPositionX(child.getPositionX() + deltaX); } } @Override public void setPositionY(int posY) { int deltaY = posY - getPositionY(); this.positionY = posY; for(Element child : childList){ child.setPositionY(child.getPositionY() + deltaY); } } @Override public void setParentWidth(int width) { this.parentWidth = width; } @Override public void setParentHeight(int height) { this.parentHeight = height; } @Override public void addChild(Element child) { childList.add(child); if(child instanceof DrawableElement){ DrawableElement drawableChild = (DrawableElement) child; drawableChild.setParentWidth(width); drawableChild.setParentHeight(height); drawableChild.setVisible(false); } } @Override public List getChildren() { return childList; } @Override public void removeChild(Element child) { childList.remove(child); } public void setFocus(boolean focus){ this.focused = focus; } @Override public boolean isFocused() { return focused; } @Override public void setOnFocus(FocusEventCallback callback) { this.onFocus = callback; } @Override public void setOnLoseFocus(FocusEventCallback callback) { this.onLoseFocus = callback; } @Override public void setOnDragStart(DragEventCallback callback) { this.onDragStart = callback; } @Override public void setOnDrag(DragEventCallback callback) { this.onDrag = callback; } @Override public void setOnDragRelease(DragEventCallback callback) { this.onDragRelease = callback; } @Override public void setOnClick(ClickEventCallback callback) { this.onClick = callback; } @Override public boolean handleEvent(Event event) { boolean propagate = true; if(onClick != null){ if(event instanceof ClickEvent){ if(!onClick.execute((ClickEvent)event)){ propagate = false; } } } if(onFocus != null){ if(event instanceof FocusEvent){ if(!onFocus.execute((FocusEvent)event)){ propagate = false; } } } if(onLoseFocus != null){ if(event instanceof FocusEvent){ if(!onLoseFocus.execute((FocusEvent)event)){ propagate = false; } } } if(event instanceof DragEvent){ if(onDragStart != null && ((DragEvent)event).getType() == DragEventType.START){ if(!onDragStart.execute((DragEvent)event)){ propagate = false; } } if(onDrag != null && ((DragEvent)event).getType() == DragEventType.DRAG){ if(!onDrag.execute((DragEvent)event)){ propagate = false; } } if(onDragRelease != null && ((DragEvent)event).getType() == DragEventType.RELEASE){ if(!onDragRelease.execute((DragEvent)event)){ propagate = false; } } } if(event instanceof NavigationEvent){ if(onNavigate != null){ if(onNavigate.execute((NavigationEvent)event)){ propagate = false; } } } return propagate; } @Override public boolean getVisible() { return false; } @Override public void setVisible(boolean draw) { this.visible = draw; } @Override public void draw(RenderPipelineState renderPipelineState, OpenGLState openGLState, int parentFramebufferPointer, int parentWidth, int parentHeight) { for(Element child : childList){ if(child instanceof DrawableElement){ DrawableElement drawableChild = (DrawableElement) child; drawableChild.draw(renderPipelineState,openGLState,parentFramebufferPointer,parentWidth,parentHeight); } } if(Globals.RENDER_FLAG_RENDER_UI_BOUNDS && DebugRendering.RENDER_DEBUG_OUTLINE_DIV){ float ndcX = (float)positionX/parentWidth; float ndcY = (float)positionY/parentHeight; float ndcWidth = (float)getWidth()/parentWidth; float ndcHeight = (float)getHeight()/parentHeight; Vector3f boxPosition = new Vector3f(ndcX,ndcY,0); Vector3f boxDimensions = new Vector3f(ndcWidth,ndcHeight,0); DebugRendering.drawUIBounds(parentFramebufferPointer, boxPosition, boxDimensions, windowDrawDebugColor); } } @Override public void setOnNavigationCallback(NavigationEventCallback callback) { onNavigate = callback; } }