aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJuuz <6596629+Juuxel@users.noreply.github.com>2021-08-18 23:27:13 +0300
committerJuuz <6596629+Juuxel@users.noreply.github.com>2021-08-18 23:27:13 +0300
commitbbe3c8e84eea77451b0c6ebbc84c6fb2571ca311 (patch)
tree2b579f9b1062c1c7a383e3ef487f4539803e264d /src
parent8ec04838e2739a3bdcab12da3d97397fde25b96d (diff)
parentbad398cd1114b181f768c1cc3000903e39929e9e (diff)
downloadLibGui-bbe3c8e84eea77451b0c6ebbc84c6fb2571ca311.tar.gz
LibGui-bbe3c8e84eea77451b0c6ebbc84c6fb2571ca311.tar.bz2
LibGui-bbe3c8e84eea77451b0c6ebbc84c6fb2571ca311.zip
Merge branch 'feature/hover' into feature/narration
Diffstat (limited to 'src')
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java15
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java19
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/CottonScreenImpl.java3
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/MouseInputHandler.java42
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java8
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/data/ObservableProperty.java109
6 files changed, 173 insertions, 23 deletions
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java
index 8fed347..331f68b 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonClientScreen.java
@@ -38,6 +38,8 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
@Nullable
protected WWidget lastResponder = null;
+
+ private final MouseInputHandler<CottonClientScreen> mouseInputHandler = new MouseInputHandler<>(this);
public CottonClientScreen(GuiDescription description) {
this(new LiteralText(""), description);
@@ -48,7 +50,8 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
this.description = description;
description.getRootPanel().validate(description);
}
-
+
+ @Override
public GuiDescription getDescription() {
return description;
}
@@ -178,7 +181,7 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
if (containerX<0 || containerY<0 || containerX>=width || containerY>=height) return true;
- MouseInputHandler.onMouseDown(description, this, containerX, containerY, mouseButton);
+ mouseInputHandler.onMouseDown(containerX, containerY, mouseButton);
return true;
}
@@ -189,7 +192,7 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
super.mouseReleased(mouseX, mouseY, mouseButton);
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
- MouseInputHandler.onMouseUp(description, this, containerX, containerY, mouseButton);
+ mouseInputHandler.onMouseUp(containerX, containerY, mouseButton);
return true;
}
@@ -201,7 +204,7 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
- MouseInputHandler.onMouseDrag(description, this, containerX, containerY, mouseButton, deltaX, deltaY);
+ mouseInputHandler.onMouseDrag(containerX, containerY, mouseButton, deltaX, deltaY);
return true;
}
@@ -212,7 +215,7 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
- MouseInputHandler.onMouseScroll(description, containerX, containerY, amount);
+ mouseInputHandler.onMouseScroll(containerX, containerY, amount);
return true;
}
@@ -223,7 +226,7 @@ public class CottonClientScreen extends Screen implements CottonScreenImpl {
int containerX = (int)mouseX-left;
int containerY = (int)mouseY-top;
- MouseInputHandler.onMouseMove(description, containerX, containerY);
+ mouseInputHandler.onMouseMove(containerX, containerY);
}
@Override
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java
index 0a1a3f4..953563c 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/client/CottonInventoryScreen.java
@@ -9,6 +9,7 @@ import net.minecraft.text.LiteralText;
import net.minecraft.text.Style;
import net.minecraft.text.Text;
+import io.github.cottonmc.cotton.gui.GuiDescription;
import io.github.cottonmc.cotton.gui.SyncedGuiDescription;
import io.github.cottonmc.cotton.gui.impl.VisualLogger;
import io.github.cottonmc.cotton.gui.impl.client.CottonScreenImpl;
@@ -16,6 +17,7 @@ import io.github.cottonmc.cotton.gui.impl.client.MouseInputHandler;
import io.github.cottonmc.cotton.gui.impl.client.NarrationHelper;
import io.github.cottonmc.cotton.gui.widget.WPanel;
import io.github.cottonmc.cotton.gui.widget.WWidget;
+import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL11;
@@ -28,6 +30,7 @@ import org.lwjgl.opengl.GL11;
public class CottonInventoryScreen<T extends SyncedGuiDescription> extends HandledScreen<T> implements CottonScreenImpl {
protected SyncedGuiDescription description;
@Nullable protected WWidget lastResponder = null;
+ private final MouseInputHandler<CottonInventoryScreen<T>> mouseInputHandler = new MouseInputHandler<>(this);
/**
* Constructs a new screen without a title.
@@ -85,6 +88,12 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
VisualLogger.reset();
}
+ @ApiStatus.Internal
+ @Override
+ public GuiDescription getDescription() {
+ return description;
+ }
+
@Nullable
@Override
public WWidget getLastResponder() {
@@ -189,7 +198,7 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
if (containerX<0 || containerY<0 || containerX>=width || containerY>=height) return result;
- MouseInputHandler.onMouseDown(description, this, containerX, containerY, mouseButton);
+ mouseInputHandler.onMouseDown(containerX, containerY, mouseButton);
return true;
}
@@ -199,7 +208,7 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
super.mouseReleased(mouseX, mouseY, mouseButton);
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
- MouseInputHandler.onMouseUp(description, this, containerX, containerY, mouseButton);
+ mouseInputHandler.onMouseUp(containerX, containerY, mouseButton);
return true;
}
@@ -210,7 +219,7 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
- MouseInputHandler.onMouseDrag(description, this, containerX, containerY, mouseButton, deltaX, deltaY);
+ mouseInputHandler.onMouseDrag(containerX, containerY, mouseButton, deltaX, deltaY);
return true;
}
@@ -221,7 +230,7 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
- MouseInputHandler.onMouseScroll(description, containerX, containerY, amount);
+ mouseInputHandler.onMouseScroll(containerX, containerY, amount);
return true;
}
@@ -232,7 +241,7 @@ public class CottonInventoryScreen<T extends SyncedGuiDescription> extends Handl
int containerX = (int)mouseX-x;
int containerY = (int)mouseY-y;
- MouseInputHandler.onMouseMove(description, containerX, containerY);
+ mouseInputHandler.onMouseMove(containerX, containerY);
}
@Override
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/CottonScreenImpl.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/CottonScreenImpl.java
index 2ef9632..cd215b3 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/CottonScreenImpl.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/CottonScreenImpl.java
@@ -5,11 +5,14 @@ import net.fabricmc.api.Environment;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.Style;
+import io.github.cottonmc.cotton.gui.GuiDescription;
import io.github.cottonmc.cotton.gui.widget.WWidget;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public interface CottonScreenImpl {
+ GuiDescription getDescription();
+
@Nullable
WWidget getLastResponder();
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/MouseInputHandler.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/MouseInputHandler.java
index 45fc17f..4791c39 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/MouseInputHandler.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/MouseInputHandler.java
@@ -2,7 +2,6 @@ package io.github.cottonmc.cotton.gui.impl.client;
import net.minecraft.client.gui.screen.Screen;
-import io.github.cottonmc.cotton.gui.GuiDescription;
import io.github.cottonmc.cotton.gui.widget.WWidget;
import io.github.cottonmc.cotton.gui.widget.data.InputResult;
import org.jetbrains.annotations.Nullable;
@@ -12,10 +11,17 @@ import java.util.function.Function;
/**
* The implementation for mouse inputs.
*/
-public final class MouseInputHandler {
- public static void onMouseDown(GuiDescription description, CottonScreenImpl screen, int containerX, int containerY, int mouseButton) {
+public final class MouseInputHandler<S extends Screen & CottonScreenImpl> {
+ private final S screen;
+ private @Nullable WWidget hovered;
+
+ public MouseInputHandler(S screen) {
+ this.screen = screen;
+ }
+
+ public void onMouseDown(int containerX, int containerY, int mouseButton) {
if (screen.getLastResponder() == null) {
- WWidget lastResponder = description.getRootPanel().hit(containerX, containerY);
+ WWidget lastResponder = screen.getDescription().getRootPanel().hit(containerX, containerY);
screen.setLastResponder(lastResponder);
if (lastResponder != null) {
runTree(
@@ -28,7 +34,7 @@ public final class MouseInputHandler {
}
}
- public static <S extends Screen & CottonScreenImpl> void onMouseUp(GuiDescription description, S screen, int containerX, int containerY, int mouseButton) {
+ public void onMouseUp(int containerX, int containerY, int mouseButton) {
WWidget lastResponder = screen.getLastResponder();
if (lastResponder != null) {
@@ -48,7 +54,7 @@ public final class MouseInputHandler {
}
} else {
runTree(
- description.getRootPanel().hit(containerX, containerY),
+ screen.getDescription().getRootPanel().hit(containerX, containerY),
widget -> widget.onMouseUp(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY(), mouseButton)
);
}
@@ -56,7 +62,7 @@ public final class MouseInputHandler {
screen.setLastResponder(null);
}
- public static <S extends Screen & CottonScreenImpl> void onMouseDrag(GuiDescription description, S screen, int containerX, int containerY, int mouseButton, double deltaX, double deltaY) {
+ public void onMouseDrag(int containerX, int containerY, int mouseButton, double deltaX, double deltaY) {
WWidget lastResponder = screen.getLastResponder();
if (lastResponder != null) {
@@ -68,22 +74,34 @@ public final class MouseInputHandler {
if (containerX < 0 || containerY < 0 || containerX >= width || containerY >= height) return;
runTree(
- description.getRootPanel().hit(containerX, containerY),
+ screen.getDescription().getRootPanel().hit(containerX, containerY),
widget -> widget.onMouseDrag(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY(), mouseButton, deltaX, deltaY)
);
}
}
- public static void onMouseScroll(GuiDescription description, int containerX, int containerY, double amount) {
+ public void onMouseScroll(int containerX, int containerY, double amount) {
runTree(
- description.getRootPanel().hit(containerX, containerY),
+ screen.getDescription().getRootPanel().hit(containerX, containerY),
widget -> widget.onMouseScroll(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY(), amount)
);
}
- public static void onMouseMove(GuiDescription description, int containerX, int containerY) {
+ public void onMouseMove(int containerX, int containerY) {
+ WWidget hit = screen.getDescription().getRootPanel().hit(containerX, containerY);
+
+ // TODO: Some sort of canHover?
+ if (hit != hovered) {
+ if (hovered != null) {
+ hovered.getHovered().set(false);
+ }
+
+ hovered = hit;
+ hit.getHovered().set(true);
+ }
+
runTree(
- description.getRootPanel().hit(containerX, containerY),
+ hit,
widget -> widget.onMouseMove(containerX - widget.getAbsoluteX(), containerY - widget.getAbsoluteY())
);
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java
index e6f314f..3beacee 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java
@@ -1,5 +1,7 @@
package io.github.cottonmc.cotton.gui.widget;
+import io.github.cottonmc.cotton.gui.widget.data.ObservableProperty;
+
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
@@ -42,6 +44,8 @@ public class WWidget {
@Nullable
protected GuiDescription host;
+ private final ObservableProperty<Boolean> hovered = ObservableProperty.of(false).nonnullValues();
+
/**
* Sets the location of this widget relative to its parent.
*
@@ -457,6 +461,10 @@ public class WWidget {
public void addPainters() {
}
+ public ObservableProperty<Boolean> getHovered() {
+ return hovered;
+ }
+
/**
* {@return whether this widget can be narrated}
*
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/data/ObservableProperty.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/data/ObservableProperty.java
new file mode 100644
index 0000000..723cf60
--- /dev/null
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/data/ObservableProperty.java
@@ -0,0 +1,109 @@
+package io.github.cottonmc.cotton.gui.widget.data;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Supplier;
+
+public final class ObservableProperty<T> {
+ private Supplier<? extends T> value;
+ private final List<ChangeListener<? super T>> listeners = new ArrayList<>();
+ private boolean allowNull = true;
+
+ private ObservableProperty() {
+ }
+
+ private ObservableProperty(Supplier<? extends T> value) {
+ this.value = value;
+ }
+
+ public static <T> ObservableProperty<T> lateinit() {
+ return new ObservableProperty<>();
+ }
+
+ public static <T> ObservableProperty<T> of(T initialValue) {
+ return new ObservableProperty<>(() -> initialValue);
+ }
+
+ public static <T> ObservableProperty<T> bound(Supplier<? extends T> initialValue) {
+ return new ObservableProperty<>(initialValue);
+ }
+
+ /**
+ * {@return the value of this property}
+ * @throws IllegalStateException if not initialized
+ * @throws NullPointerException if the value is null and null values aren't allowed
+ */
+ public T get() {
+ if (value == null) {
+ throw new IllegalStateException("Property not initialized!");
+ }
+
+ T ret = value.get();
+ if (ret == null && !allowNull) throw new NullPointerException("Null value for nonnull property!");
+ return ret;
+ }
+
+ /**
+ * Sets this property to a constant value.
+ *
+ * @param value the new value
+ * @throws NullPointerException if the value is null and nulls aren't allowed
+ */
+ public void set(T value) {
+ if (value == null && !allowNull) throw new NullPointerException("value");
+ bind(() -> value);
+ }
+
+ /**
+ * Binds this property to a supplier.
+ *
+ * @param value the new value supplier
+ */
+ public void bind(Supplier<? extends T> value) {
+ Objects.requireNonNull(value, "value");
+ T oldValue = this.value != null ? this.value.get() : null;
+ this.value = value;
+
+ for (ChangeListener<? super T> listener : listeners) {
+ listener.onPropertyChange(this, oldValue, value.get());
+ }
+ }
+
+ /**
+ * Clears the current value, if any, from this property.
+ */
+ public void clear() {
+ T oldValue = this.value != null ? this.value.get() : null;
+ value = null;
+
+ for (ChangeListener<? super T> listener : listeners) {
+ listener.onPropertyChange(this, oldValue, null);
+ }
+ }
+
+ /**
+ * Prevents this property from accepting null values.
+ *
+ * @return this property
+ */
+ public ObservableProperty<T> nonnullValues() {
+ allowNull = false;
+ return this;
+ }
+
+ public void addListener(ChangeListener<? super T> listener) {
+ listeners.add(listener);
+ }
+
+ public void removeListener(ChangeListener<? super T> listener) {
+ listeners.remove(listener);
+ }
+
+ @FunctionalInterface
+ public interface ChangeListener<T> {
+ void onPropertyChange(ObservableProperty<? extends T> property, @Nullable T from, @Nullable T to);
+ }
+}