From 8eda347bcc51266b42d64c135cc05ec3d83848f7 Mon Sep 17 00:00:00 2001 From: Victorious3 Date: Wed, 4 Feb 2015 22:49:20 +0100 Subject: [PATCH] First implementation try on the border layout. --- src/main/java/nova/core/gui/GuiComponent.java | 8 +- src/main/java/nova/core/gui/Outline.java | 24 +++++- .../core/gui/layout/AbstractGuiLayout.java | 34 +++++++- .../nova/core/gui/layout/BorderLayout.java | 84 ++++++++++++++++--- .../nova/core/util/transform/Vector2i.java | 9 +- 5 files changed, 139 insertions(+), 20 deletions(-) diff --git a/src/main/java/nova/core/gui/GuiComponent.java b/src/main/java/nova/core/gui/GuiComponent.java index 9fdb78758..882d39723 100644 --- a/src/main/java/nova/core/gui/GuiComponent.java +++ b/src/main/java/nova/core/gui/GuiComponent.java @@ -27,7 +27,7 @@ public abstract class GuiComponent, T extends Nativ protected String qualifiedName; private T nativeElement; - private SidedEventListenerList eventListenerList = new SidedEventListenerList(this::dispatchNetworkEvent); + private SidedEventListenerList> eventListenerList = new SidedEventListenerList>(this::dispatchNetworkEvent); private EventListenerList listenerList = new EventListenerList(); protected Optional preferredSize = Optional.empty(); @@ -58,6 +58,10 @@ public GuiComponent(String uniqueID) { this.qualifiedName = uniqueID; } + public Optional> getParentContainer() { + return parentContainer; + } + /** * @return Outline of this component. * @see Outline @@ -74,7 +78,7 @@ public Outline getOutline() { * @param outline {@link Outline} to use as outline */ @Deprecated - protected void setOutlineNative(Outline outline) { + public void setOutlineNative(Outline outline) { nativeElement.setOutline(outline); } diff --git a/src/main/java/nova/core/gui/Outline.java b/src/main/java/nova/core/gui/Outline.java index e1c1b3262..c026b8636 100644 --- a/src/main/java/nova/core/gui/Outline.java +++ b/src/main/java/nova/core/gui/Outline.java @@ -11,10 +11,6 @@ */ public class Outline extends Rectangle { - private Outline(Vector2i min, Vector2i max) { - super(min, max); - } - /** * Creates a new Outline with the specified position and dimension. * @@ -27,6 +23,10 @@ public Outline(int x, int y, int width, int height) { super(new Vector2i(x, y), new Vector2i(x + width, y + height)); } + public Outline(Vector2i position, Vector2i dimension) { + super(position, position.add(dimension)); + } + public int getWidth() { return x2i() - x1i(); } @@ -42,4 +42,20 @@ public Outline setHeight(int height) { public Outline setWidth(int width) { return new Outline(new Vector2i(x1i(), x1i() + width), max); } + + public Vector2i getDimension() { + return new Vector2i(getWidth(), getHeight()); + } + + public Outline setDimension(Vector2i dimension) { + return new Outline(min, min.add(dimension)); + } + + public Vector2i getPosition() { + return getMin(); + } + + public Outline setPosition(Vector2i position) { + return new Outline(position, position.add(getMax())); + } } diff --git a/src/main/java/nova/core/gui/layout/AbstractGuiLayout.java b/src/main/java/nova/core/gui/layout/AbstractGuiLayout.java index 721779622..b9bad8dee 100644 --- a/src/main/java/nova/core/gui/layout/AbstractGuiLayout.java +++ b/src/main/java/nova/core/gui/layout/AbstractGuiLayout.java @@ -2,6 +2,8 @@ import nova.core.gui.AbstractGuiContainer; import nova.core.gui.GuiComponent; +import nova.core.gui.Outline; +import nova.core.util.transform.Vector2i; public abstract class AbstractGuiLayout> implements GuiLayout { @@ -38,7 +40,37 @@ public final void add(GuiComponent component, AbstractGuiContainer p addImpl(component, parent, LayoutConstraints.createConstraints(constraintsClass, parameters)); } - protected abstract void addImpl(GuiComponent element, AbstractGuiContainer parent, T constraints); + protected abstract void addImpl(GuiComponent component, AbstractGuiContainer parent, T constraints); + + // TODO Document as needed by possible custom layouts. + protected final Vector2i getPreferredSizeOf(GuiComponent component) { + return component != null ? component.getPreferredSize().orElse(component.getMinimumSize().orElse(Vector2i.zero)) : Vector2i.zero; + } + + protected final Vector2i getMaximumSizeOf(GuiComponent component) { + return component != null ? component.getPreferredSize().orElse(component.getMaximumSize().orElse(Vector2i.max)) : Vector2i.max; + } + + @SuppressWarnings("deprecation") + protected final void setSizeOf(GuiComponent component, Vector2i size) { + if (component != null) { + component.setOutlineNative(component.getOutline().setDimension(size)); + } + } + + @SuppressWarnings("deprecation") + protected final void setPositionOf(GuiComponent component, Vector2i position) { + if (component != null) { + component.setOutlineNative(component.getOutline().setPosition(position)); + } + }; + + @SuppressWarnings("deprecation") + protected final void setOutlineOf(GuiComponent component, Outline outline) { + if (component != null) { + component.setOutlineNative(outline); + } + } public abstract T constraints(); } diff --git a/src/main/java/nova/core/gui/layout/BorderLayout.java b/src/main/java/nova/core/gui/layout/BorderLayout.java index 22f8a4436..748f84c86 100644 --- a/src/main/java/nova/core/gui/layout/BorderLayout.java +++ b/src/main/java/nova/core/gui/layout/BorderLayout.java @@ -4,7 +4,9 @@ import nova.core.gui.AbstractGuiContainer; import nova.core.gui.GuiComponent; +import nova.core.gui.Outline; import nova.core.gui.layout.LayoutConstraints.BorderLayoutConstraints; +import nova.core.util.transform.Vector2i; /** * A basic layout that splits the parent's container up into multiple regions. @@ -22,11 +24,81 @@ public BorderLayout() { private final HashMap> components = new HashMap<>(); + // TODO HIGHLY untested @Override public void revalidate(AbstractGuiContainer parent) { - for (EnumBorderRegion region : components.keySet()) { + Outline outline = parent.getOutline(); + Vector2i dimension = outline.getDimension(); + GuiComponent cComp = components.get(EnumBorderRegion.CENTER); + GuiComponent wComp = components.get(EnumBorderRegion.WEST); + GuiComponent eComp = components.get(EnumBorderRegion.EAST); + GuiComponent nComp = components.get(EnumBorderRegion.NORTH); + GuiComponent sComp = components.get(EnumBorderRegion.SOUTH); + + Vector2i wDim = getPreferredSizeOf(wComp); + Vector2i eDim = getPreferredSizeOf(eComp); + Vector2i nDim = getPreferredSizeOf(nComp); + Vector2i sDim = getPreferredSizeOf(sComp); + Vector2i cDim = Vector2i.zero; + + Vector2i overAllocated = Vector2i.zero; + Vector2i space = dimension; + + if (cComp != null) { + Vector2i pref = new Vector2i(dimension.x - wDim.x - nDim.x, dimension.y - nDim.y - sDim.y); + cDim = pref.min(getMaximumSizeOf(cComp)); + Vector2i cOver = pref.subtract(cDim).divide(2); + + if (cOver.x > 0) { + if (wComp != null) + wDim = wDim.add(new Vector2i(cOver.x, 0)); + if (eComp != null) + eDim = eDim.add(new Vector2i(cOver.x, 0)); + } + if (cOver.y > 0) { + if (nComp != null) + nDim = nDim.add(new Vector2i(0, cOver.y)); + if (sComp != null) + sDim = sDim.add(new Vector2i(0, cOver.y)); + } + + Vector2i v1 = dimension.subtract(cDim); + overAllocated = v1.subtract(wDim).subtract(nDim).subtract(eDim).subtract(sDim).inverse().max(Vector2i.zero); + space = space.subtract(cDim); + + } else { + overAllocated = dimension.subtract(wDim).subtract(nDim).subtract(eDim).subtract(sDim).inverse().max(Vector2i.zero); + } + + Vector2i v2 = space.divide(2); + + if (overAllocated.x > 0) { + Vector2i v3 = wComp != null && eComp != null ? v2 : space; + wDim = new Vector2i(v3.x, eDim.y); + eDim = new Vector2i(v3.x, wDim.y); } + if (overAllocated.y > 0) { + Vector2i v3 = nComp != null && sComp != null ? v2 : space; + wDim = new Vector2i(eDim.x, v3.y); + eDim = new Vector2i(wDim.x, v3.y); + } + + if (cComp != null) { + cDim = cDim.min(dimension.subtract(wDim).subtract(nDim).subtract(eDim).subtract(sDim)); + } + + // Centers the border components + int wOffset = (int) ((dimension.y + wDim.y) / 2D); + int eOffset = (int) ((dimension.y + eDim.y) / 2D); + int nOffset = (int) ((dimension.x + nDim.x) / 2D); + int sOffset = (int) ((dimension.x + sDim.x) / 2D); + + setOutlineOf(cComp, new Outline(new Vector2i(wDim.x, nDim.y), dimension)); + setOutlineOf(wComp, new Outline(new Vector2i(0, wOffset), wDim)); + setOutlineOf(eComp, new Outline(new Vector2i(dimension.x - wDim.x, eOffset), wDim)); + setOutlineOf(nComp, new Outline(new Vector2i(nOffset, 0), eDim)); + setOutlineOf(sComp, new Outline(new Vector2i(sOffset, dimension.y - sDim.y), sDim)); } @Override @@ -42,15 +114,7 @@ public void remove(GuiComponent component) { } public static enum EnumBorderRegion { - CENTER(2, 2), NORTH(1, 1), EAST(1, 2), SOUTH(1, 1), WEST(1, 2); - - public final int priority; - public final int axis; - - private EnumBorderRegion(int priority, int axis) { - this.priority = priority; - this.axis = axis; - } + CENTER, NORTH, EAST, SOUTH, WEST; } @Override diff --git a/src/main/java/nova/core/util/transform/Vector2i.java b/src/main/java/nova/core/util/transform/Vector2i.java index 9366e0c01..e72420eb4 100644 --- a/src/main/java/nova/core/util/transform/Vector2i.java +++ b/src/main/java/nova/core/util/transform/Vector2i.java @@ -1,7 +1,9 @@ package nova.core.util.transform; /** - * A double implementation of Vector2. Vector2 is an immutable quantity that holds an x, y and z value. + * A double implementation of Vector2. Vector2 is an immutable quantity that + * holds an x, y and z value. + * * @author Calclavia */ @SuppressWarnings("rawtypes") @@ -10,6 +12,7 @@ public class Vector2i extends Vector2 { public static final Vector2i one = new Vector2i(1, 1); public static final Vector2i xAxis = new Vector2i(1, 0); public static final Vector2i yAxis = new Vector2i(0, 1); + public static final Vector2i max = new Vector2i(Integer.MAX_VALUE, Integer.MAX_VALUE); public final int x, y; @@ -68,12 +71,12 @@ public int hashCode() { @Override public int xi() { - return (int) x; + return x; } @Override public int yi() { - return (int) y; + return y; } @Override