From 7a514009855636f0b92e7a92ca6ce0c42a50a805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Thu, 25 Aug 2022 12:17:44 +0200 Subject: [PATCH] Create *GridOptionChoice components --- .../base/lib/gui/HGridLayout.java | 2 +- .../base/lib/gui/HGridOptionChoice.java | 174 ++++++++++++++++++ .../base/lib/gui/HOptionChoice.java | 31 ++-- .../base/lib/gui/VGridLayout.java | 3 +- .../base/lib/gui/VGridOptionChoice.java | 174 ++++++++++++++++++ .../base/lib/gui/VOptionChoice.java | 31 ++-- 6 files changed, 385 insertions(+), 30 deletions(-) create mode 100644 api/src/main/java/com/bartlomiejpluta/base/lib/gui/HGridOptionChoice.java create mode 100644 api/src/main/java/com/bartlomiejpluta/base/lib/gui/VGridOptionChoice.java diff --git a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HGridLayout.java b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HGridLayout.java index d3953fcd..10cdb89e 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HGridLayout.java +++ b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HGridLayout.java @@ -8,7 +8,7 @@ import lombok.NonNull; public class HGridLayout extends BaseContainer { protected float offsetX = 0.0f; protected float offsetY = 0.0f; - private int rows = 2; + protected int rows = 2; private float[] heights = new float[rows]; public HGridLayout(Context context, GUI gui) { diff --git a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HGridOptionChoice.java b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HGridOptionChoice.java new file mode 100644 index 00000000..ca04f7e5 --- /dev/null +++ b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HGridOptionChoice.java @@ -0,0 +1,174 @@ +package com.bartlomiejpluta.base.lib.gui; + +import com.bartlomiejpluta.base.api.context.Context; +import com.bartlomiejpluta.base.api.event.Event; +import com.bartlomiejpluta.base.api.gui.Component; +import com.bartlomiejpluta.base.api.gui.GUI; +import com.bartlomiejpluta.base.api.input.Key; +import com.bartlomiejpluta.base.api.input.KeyAction; +import com.bartlomiejpluta.base.api.input.KeyEvent; +import com.bartlomiejpluta.base.api.screen.Screen; +import com.bartlomiejpluta.base.util.math.MathUtil; +import lombok.Getter; +import lombok.NonNull; + +import java.util.EnumSet; + +public class HGridOptionChoice extends HGridLayout { + private static final EnumSet ACTIONS = EnumSet.of(KeyAction.PRESS, KeyAction.REPEAT); + private int selectedRow = 0; + private int selectedColumn = 0; + private float scrollX = 0; + private float scrollY = 0; + private float scrollSpeedX = 1f; + private float scrollSpeedY = 1f; + + @Getter + private Component selectedComponent = null; + + public HGridOptionChoice(Context context, GUI gui) { + super(context, gui); + addEventListener(KeyEvent.TYPE, this::switchOption); + } + + public void setScrollSpeed(@NonNull Float scrollSpeed) { + var coerced = MathUtil.clamp(scrollSpeed, 0f, 1f); + this.scrollSpeedX = coerced; + this.scrollSpeedY = coerced; + } + + public void setScrollSpeedX(@NonNull Float scrollSpeedX) { + this.scrollSpeedX = MathUtil.clamp(scrollSpeedX, 0f, 1f); + } + + public void setScrollSpeedY(@NonNull Float scrollSpeedY) { + this.scrollSpeedY = MathUtil.clamp(scrollSpeedY, 0f, 1f); + } + + @Override + public void focus() { + super.focus(); + + if (!children.isEmpty()) { + selectedComponent = children.get(rows * selectedColumn + selectedRow); + selectedComponent.focus(); + } + } + + @Override + public void handleEvent(E event) { + var index = rows * selectedColumn + selectedRow; + if (index < children.size()) { + selectedComponent = children.get(index); + selectedComponent.handleEvent(event); + } + + if (!event.isConsumed()) { + eventHandler.handleEvent(event); + } + } + + private void blurAll() { + for (var child : children) { + child.blur(); + } + } + + private void switchOption(KeyEvent event) { + if (children.isEmpty()) { + return; + } + + if (event.getKey() == Key.KEY_DOWN && ACTIONS.contains(event.getAction())) { + blurAll(); + + int size = 0; + for (int i = 0; i < children.size(); ++i) { + if (i / rows == selectedColumn) ++size; + } + + if (size == 0) return; + + selectedRow = (++selectedRow) % size; + selectedComponent = children.get(rows * selectedColumn + selectedRow); + selectedComponent.focus(); + event.consume(); + } else if (event.getKey() == Key.KEY_UP && ACTIONS.contains(event.getAction())) { + blurAll(); + + int size = 0; + for (int i = 0; i < children.size(); ++i) { + if (i / rows == selectedColumn) ++size; + } + + if (size == 0) return; + + selectedRow = ((--selectedRow) + size) % size; + selectedComponent = children.get(rows * selectedColumn + selectedRow); + selectedComponent.focus(); + event.consume(); + } else if (event.getKey() == Key.KEY_RIGHT && ACTIONS.contains(event.getAction())) { + blurAll(); + + int size = 0; + for (int i = 0; i < children.size(); ++i) { + if (i % rows == selectedRow) ++size; + } + + if (size == 0) return; + + selectedColumn = (++selectedColumn) % size; + selectedComponent = children.get(rows * selectedColumn + selectedRow); + selectedComponent.focus(); + event.consume(); + } else if (event.getKey() == Key.KEY_LEFT && ACTIONS.contains(event.getAction())) { + blurAll(); + + int size = 0; + for (int i = 0; i < children.size(); ++i) { + if (i % rows == selectedRow) ++size; + } + + if (size == 0) return; + + selectedColumn = ((--selectedColumn) + size) % size; + selectedComponent = children.get(rows * selectedColumn + selectedRow); + selectedComponent.focus(); + event.consume(); + } + } + + @Override + public void update(float dt) { + super.update(dt); + + if (selectedComponent != null) { + if (selectedComponent.getX() + selectedComponent.getWidth() > getWidth() + getX()) { + scrollX += (selectedComponent.getWidth() + selectedComponent.getX() - (getWidth() + getX())) * scrollSpeedX; + } else if (selectedComponent.getX() < getX()) { + scrollX += (selectedComponent.getX() - getX()) * scrollSpeedX; + } + } + + if (selectedComponent != null) { + if (selectedComponent.getY() + selectedComponent.getHeight() > getHeight() + getY()) { + scrollY += (selectedComponent.getHeight() + selectedComponent.getY() - (getHeight() + getY())) * scrollSpeedY; + } else if (selectedComponent.getY() < getY()) { + scrollY += (selectedComponent.getY() - getY()) * scrollSpeedY; + } + } + } + + + @Override + public void draw(Screen screen, GUI gui) { + gui.clip(x, y, getWidth(), getHeight()); + + offsetX = -scrollX; + offsetY = -scrollY; + + super.draw(screen, gui); + + gui.resetClip(); + } +} \ No newline at end of file diff --git a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HOptionChoice.java b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HOptionChoice.java index 27af12a0..210e15dd 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HOptionChoice.java +++ b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/HOptionChoice.java @@ -9,6 +9,7 @@ import com.bartlomiejpluta.base.api.input.KeyAction; import com.bartlomiejpluta.base.api.input.KeyEvent; import com.bartlomiejpluta.base.api.screen.Screen; import com.bartlomiejpluta.base.util.math.MathUtil; +import lombok.Getter; import lombok.NonNull; import java.util.EnumSet; @@ -17,9 +18,11 @@ public class HOptionChoice extends HLayout { private static final EnumSet ACTIONS = EnumSet.of(KeyAction.PRESS, KeyAction.REPEAT); private int selected = 0; private float scroll = 0; - private Component component = null; private float scrollSpeed = 1f; + @Getter + private Component selectedComponent = null; + public HOptionChoice(Context context, GUI gui) { super(context, gui); addEventListener(KeyEvent.TYPE, this::switchOption); @@ -34,16 +37,16 @@ public class HOptionChoice extends HLayout { super.focus(); if (!children.isEmpty()) { - component = children.get(selected); - component.focus(); + selectedComponent = children.get(selected); + selectedComponent.focus(); } } @Override public void handleEvent(E event) { if (selected < children.size()) { - component = children.get(selected); - component.handleEvent(event); + selectedComponent = children.get(selected); + selectedComponent.handleEvent(event); } if (!event.isConsumed()) { @@ -59,15 +62,15 @@ public class HOptionChoice extends HLayout { if (event.getKey() == Key.KEY_RIGHT && ACTIONS.contains(event.getAction())) { blurAll(); selected = (++selected) % children.size(); - component = children.get(selected); - component.focus(); + selectedComponent = children.get(selected); + selectedComponent.focus(); event.consume(); } else if (event.getKey() == Key.KEY_LEFT && ACTIONS.contains(event.getAction())) { blurAll(); var size = children.size(); selected = (((--selected) % size) + size) % size; - component = children.get(selected); - component.focus(); + selectedComponent = children.get(selected); + selectedComponent.focus(); event.consume(); } } @@ -81,11 +84,11 @@ public class HOptionChoice extends HLayout { @Override public void update(float dt) { super.update(dt); - if (component != null) { - if (component.getX() + component.getWidth() > getWidth() + getX()) { - scroll += (component.getWidth() + component.getX() - (getWidth() + getX())) * scrollSpeed; - } else if (component.getX() < getX()) { - scroll += (component.getX() - getX()) * scrollSpeed; + if (selectedComponent != null) { + if (selectedComponent.getX() + selectedComponent.getWidth() > getWidth() + getX()) { + scroll += (selectedComponent.getWidth() + selectedComponent.getX() - (getWidth() + getX())) * scrollSpeed; + } else if (selectedComponent.getX() < getX()) { + scroll += (selectedComponent.getX() - getX()) * scrollSpeed; } } } diff --git a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VGridLayout.java b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VGridLayout.java index 59518157..13465dfb 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VGridLayout.java +++ b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VGridLayout.java @@ -3,12 +3,13 @@ package com.bartlomiejpluta.base.lib.gui; import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.gui.GUI; import com.bartlomiejpluta.base.api.screen.Screen; +import lombok.Getter; import lombok.NonNull; public class VGridLayout extends BaseContainer { protected float offsetX = 0.0f; protected float offsetY = 0.0f; - private int columns = 2; + protected int columns = 2; private float[] widths = new float[columns]; public VGridLayout(Context context, GUI gui) { diff --git a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VGridOptionChoice.java b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VGridOptionChoice.java new file mode 100644 index 00000000..946a31c2 --- /dev/null +++ b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VGridOptionChoice.java @@ -0,0 +1,174 @@ +package com.bartlomiejpluta.base.lib.gui; + +import com.bartlomiejpluta.base.api.context.Context; +import com.bartlomiejpluta.base.api.event.Event; +import com.bartlomiejpluta.base.api.gui.Component; +import com.bartlomiejpluta.base.api.gui.GUI; +import com.bartlomiejpluta.base.api.input.Key; +import com.bartlomiejpluta.base.api.input.KeyAction; +import com.bartlomiejpluta.base.api.input.KeyEvent; +import com.bartlomiejpluta.base.api.screen.Screen; +import com.bartlomiejpluta.base.util.math.MathUtil; +import lombok.Getter; +import lombok.NonNull; + +import java.util.EnumSet; + +public class VGridOptionChoice extends VGridLayout { + private static final EnumSet ACTIONS = EnumSet.of(KeyAction.PRESS, KeyAction.REPEAT); + private int selectedRow = 0; + private int selectedColumn = 0; + private float scrollX = 0; + private float scrollY = 0; + private float scrollSpeedX = 1f; + private float scrollSpeedY = 1f; + + @Getter + private Component selectedComponent = null; + + public VGridOptionChoice(Context context, GUI gui) { + super(context, gui); + addEventListener(KeyEvent.TYPE, this::switchOption); + } + + public void setScrollSpeed(@NonNull Float scrollSpeed) { + var coerced = MathUtil.clamp(scrollSpeed, 0f, 1f); + this.scrollSpeedX = coerced; + this.scrollSpeedY = coerced; + } + + public void setScrollSpeedX(@NonNull Float scrollSpeedX) { + this.scrollSpeedX = MathUtil.clamp(scrollSpeedX, 0f, 1f); + } + + public void setScrollSpeedY(@NonNull Float scrollSpeedY) { + this.scrollSpeedY = MathUtil.clamp(scrollSpeedY, 0f, 1f); + } + + @Override + public void focus() { + super.focus(); + + if (!children.isEmpty()) { + selectedComponent = children.get(columns * selectedRow + selectedColumn); + selectedComponent.focus(); + } + } + + @Override + public void handleEvent(E event) { + var index = columns * selectedRow + selectedColumn; + if (index < children.size()) { + selectedComponent = children.get(index); + selectedComponent.handleEvent(event); + } + + if (!event.isConsumed()) { + eventHandler.handleEvent(event); + } + } + + private void blurAll() { + for (var child : children) { + child.blur(); + } + } + + private void switchOption(KeyEvent event) { + if (children.isEmpty()) { + return; + } + + if (event.getKey() == Key.KEY_DOWN && ACTIONS.contains(event.getAction())) { + blurAll(); + + int size = 0; + for (int i = 0; i < children.size(); ++i) { + if (i % columns == selectedColumn) ++size; + } + + if (size == 0) return; + + selectedRow = (++selectedRow) % size; + selectedComponent = children.get(columns * selectedRow + selectedColumn); + selectedComponent.focus(); + event.consume(); + } else if (event.getKey() == Key.KEY_UP && ACTIONS.contains(event.getAction())) { + blurAll(); + + int size = 0; + for (int i = 0; i < children.size(); ++i) { + if (i % columns == selectedColumn) ++size; + } + + if (size == 0) return; + + selectedRow = ((--selectedRow) + size) % size; + selectedComponent = children.get(columns * selectedRow + selectedColumn); + selectedComponent.focus(); + event.consume(); + } else if (event.getKey() == Key.KEY_RIGHT && ACTIONS.contains(event.getAction())) { + blurAll(); + + int size = 0; + for (int i = 0; i < children.size(); ++i) { + if (i / columns == selectedRow) ++size; + } + + if (size == 0) return; + + selectedColumn = (++selectedColumn) % size; + selectedComponent = children.get(columns * selectedRow + selectedColumn); + selectedComponent.focus(); + event.consume(); + } else if (event.getKey() == Key.KEY_LEFT && ACTIONS.contains(event.getAction())) { + blurAll(); + + int size = 0; + for (int i = 0; i < children.size(); ++i) { + if (i / columns == selectedRow) ++size; + } + + if (size == 0) return; + + selectedColumn = ((--selectedColumn) + size) % size; + selectedComponent = children.get(columns * selectedRow + selectedColumn); + selectedComponent.focus(); + event.consume(); + } + } + + @Override + public void update(float dt) { + super.update(dt); + + if (selectedComponent != null) { + if (selectedComponent.getY() + selectedComponent.getHeight() > getHeight() + getY()) { + scrollY += (selectedComponent.getHeight() + selectedComponent.getY() - (getHeight() + getY())) * scrollSpeedY; + } else if (selectedComponent.getY() < getY()) { + scrollY += (selectedComponent.getY() - getY()) * scrollSpeedY; + } + } + + if (selectedComponent != null) { + if (selectedComponent.getX() + selectedComponent.getWidth() > getWidth() + getX()) { + scrollX += (selectedComponent.getWidth() + selectedComponent.getX() - (getWidth() + getX())) * scrollSpeedX; + } else if (selectedComponent.getX() < getX()) { + scrollX += (selectedComponent.getX() - getX()) * scrollSpeedX; + } + } + } + + + @Override + public void draw(Screen screen, GUI gui) { + gui.clip(x, y, getWidth(), getHeight()); + + offsetY = -scrollY; + offsetX = -scrollX; + + super.draw(screen, gui); + + gui.resetClip(); + } +} diff --git a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VOptionChoice.java b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VOptionChoice.java index 4a26eb68..4d6d21c5 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VOptionChoice.java +++ b/api/src/main/java/com/bartlomiejpluta/base/lib/gui/VOptionChoice.java @@ -9,6 +9,7 @@ import com.bartlomiejpluta.base.api.input.KeyAction; import com.bartlomiejpluta.base.api.input.KeyEvent; import com.bartlomiejpluta.base.api.screen.Screen; import com.bartlomiejpluta.base.util.math.MathUtil; +import lombok.Getter; import lombok.NonNull; import java.util.EnumSet; @@ -17,9 +18,11 @@ public class VOptionChoice extends VLayout { private static final EnumSet ACTIONS = EnumSet.of(KeyAction.PRESS, KeyAction.REPEAT); private int selected = 0; private float scroll = 0; - private Component component = null; private float scrollSpeed = 1f; + @Getter + private Component selectedComponent = null; + public VOptionChoice(Context context, GUI gui) { super(context, gui); addEventListener(KeyEvent.TYPE, this::switchOption); @@ -34,16 +37,16 @@ public class VOptionChoice extends VLayout { super.focus(); if (!children.isEmpty()) { - component = children.get(selected); - component.focus(); + selectedComponent = children.get(selected); + selectedComponent.focus(); } } @Override public void handleEvent(E event) { if (selected < children.size()) { - component = children.get(selected); - component.handleEvent(event); + selectedComponent = children.get(selected); + selectedComponent.handleEvent(event); } if (!event.isConsumed()) { @@ -59,15 +62,15 @@ public class VOptionChoice extends VLayout { if (event.getKey() == Key.KEY_DOWN && ACTIONS.contains(event.getAction())) { blurAll(); selected = (++selected) % children.size(); - component = children.get(selected); - component.focus(); + selectedComponent = children.get(selected); + selectedComponent.focus(); event.consume(); } else if (event.getKey() == Key.KEY_UP && ACTIONS.contains(event.getAction())) { blurAll(); var size = children.size(); selected = (((--selected) % size) + size) % size; - component = children.get(selected); - component.focus(); + selectedComponent = children.get(selected); + selectedComponent.focus(); event.consume(); } } @@ -81,11 +84,11 @@ public class VOptionChoice extends VLayout { @Override public void update(float dt) { super.update(dt); - if (component != null) { - if (component.getY() + component.getHeight() > getHeight() + getY()) { - scroll += (component.getHeight() + component.getY() - (getHeight() + getY())) * scrollSpeed; - } else if (component.getY() < getY()) { - scroll += (component.getY() - getY()) * scrollSpeed; + if (selectedComponent != null) { + if (selectedComponent.getY() + selectedComponent.getHeight() > getHeight() + getY()) { + scroll += (selectedComponent.getHeight() + selectedComponent.getY() - (getHeight() + getY())) * scrollSpeed; + } else if (selectedComponent.getY() < getY()) { + scroll += (selectedComponent.getY() - getY()) * scrollSpeed; } } }