aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuuz <6596629+Juuxel@users.noreply.github.com>2021-09-10 11:33:30 +0300
committerJuuz <6596629+Juuxel@users.noreply.github.com>2021-09-10 11:33:30 +0300
commit24697f732d64aba10a164794a4a0bee32bf5cbb6 (patch)
treedf1bd7c9c6923665dce3d3ccd930e8006844c9db
parentbbe3c8e84eea77451b0c6ebbc84c6fb2571ca311 (diff)
downloadLibGui-24697f732d64aba10a164794a4a0bee32bf5cbb6.tar.gz
LibGui-24697f732d64aba10a164794a4a0bee32bf5cbb6.tar.bz2
LibGui-24697f732d64aba10a164794a4a0bee32bf5cbb6.zip
More work on hovering and observables
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/MouseInputHandler.java18
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/impl/client/NarrationHelper.java4
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java3
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java2
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java8
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java8
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java3
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/WWidget.java32
-rw-r--r--src/main/java/io/github/cottonmc/cotton/gui/widget/data/ObservableProperty.java50
9 files changed, 102 insertions, 26 deletions
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 4791c39..055df75 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
@@ -4,6 +4,7 @@ import net.minecraft.client.gui.screen.Screen;
import io.github.cottonmc.cotton.gui.widget.WWidget;
import io.github.cottonmc.cotton.gui.widget.data.InputResult;
+import io.github.cottonmc.cotton.gui.widget.data.ObservableProperty;
import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
@@ -13,10 +14,14 @@ import java.util.function.Function;
*/
public final class MouseInputHandler<S extends Screen & CottonScreenImpl> {
private final S screen;
- private @Nullable WWidget hovered;
+ private final ObservableProperty<WWidget> hovered = ObservableProperty.of(null);
public MouseInputHandler(S screen) {
this.screen = screen;
+ hovered.addListener((property, from, to) -> {
+ if (from != null) from.setHovered(false);
+ if (to != null) to.setHovered(true);
+ });
}
public void onMouseDown(int containerX, int containerY, int mouseButton) {
@@ -89,16 +94,7 @@ public final class MouseInputHandler<S extends Screen & CottonScreenImpl> {
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);
- }
+ hovered.set(hit);
runTree(
hit,
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NarrationHelper.java b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NarrationHelper.java
index 9b44210..55095a3 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NarrationHelper.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/impl/client/NarrationHelper.java
@@ -18,7 +18,7 @@ public final class NarrationHelper {
public static void addNarrations(WPanel rootPanel, NarrationMessageBuilder builder) {
List<WWidget> narratableWidgets = getAllWidgets(rootPanel)
.filter(WWidget::isNarratable)
- .filter(WWidget::isFocused) // TODO: || isHovered
+ .filter(widget -> widget.isFocused() || widget.isHovered())
.collect(Collectors.toList());
for (int i = 0, childCount = narratableWidgets.size(); i < childCount; i++) {
@@ -28,7 +28,7 @@ public final class NarrationHelper {
if (narratableWidgets.size() > 1) {
builder.put(NarrationPart.POSITION, new TranslatableText(NarrationMessages.Vanilla.SCREEN_POSITION_KEY, i + 1, childCount));
- if (child.isFocused()) { // TODO: this check is currently useless but will be used with hovering
+ if (child.isFocused()) {
builder.put(NarrationPart.USAGE, NarrationMessages.Vanilla.COMPONENT_LIST_USAGE);
}
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java
index c6fdfc2..533e436 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WButton.java
@@ -230,8 +230,7 @@ public class WButton extends WWidget {
if (isEnabled()) {
if (isFocused()) {
builder.put(NarrationPart.USAGE, NarrationMessages.Vanilla.BUTTON_USAGE_FOCUSED);
- } else {
- // TODO: hovering, again
+ } else if (isHovered()) {
builder.put(NarrationPart.USAGE, NarrationMessages.Vanilla.BUTTON_USAGE_HOVERED);
}
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java
index 18c812d..a4788a7 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WItemSlot.java
@@ -450,6 +450,8 @@ public class WItemSlot extends WWidget {
parts.add(new TranslatableText(NarrationMessages.ITEM_SLOT_TITLE_KEY, focusedSlot + 1, slotsWide * slotsHigh));
builder.put(NarrationPart.TITLE, parts.toArray(new Text[0]));
}
+
+ // TODO: hovered slot
}
@Nullable
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java
index 5c6b2da..83f0700 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WLabel.java
@@ -5,6 +5,8 @@ import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.screen.Screen;
+import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
+import net.minecraft.client.gui.screen.narration.NarrationPart;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Style;
@@ -261,4 +263,10 @@ public class WLabel extends WWidget {
this.verticalAlignment = align;
return this;
}
+
+ @Environment(EnvType.CLIENT)
+ @Override
+ public void addNarrations(NarrationMessageBuilder builder) {
+ builder.put(NarrationPart.TITLE, text);
+ }
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java
index 96f78ed..8a4f03e 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WText.java
@@ -4,6 +4,8 @@ import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer;
+import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
+import net.minecraft.client.gui.screen.narration.NarrationPart;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.OrderedText;
import net.minecraft.text.Style;
@@ -253,4 +255,10 @@ public class WText extends WWidget {
this.verticalAlignment = verticalAlignment;
return this;
}
+
+ @Environment(EnvType.CLIENT)
+ @Override
+ public void addNarrations(NarrationMessageBuilder builder) {
+ builder.put(NarrationPart.TITLE, text);
+ }
}
diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java
index d4fb728..ca0285f 100644
--- a/src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java
+++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/WToggleButton.java
@@ -223,8 +223,7 @@ public class WToggleButton extends WWidget {
if (isFocused()) {
builder.put(NarrationPart.USAGE, NarrationMessages.Vanilla.BUTTON_USAGE_FOCUSED);
- } else {
- // TODO: hovering, again
+ } else if (isHovered()) {
builder.put(NarrationPart.USAGE, NarrationMessages.Vanilla.BUTTON_USAGE_HOVERED);
}
}
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 3beacee..ac08ae6 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
@@ -44,7 +44,7 @@ public class WWidget {
@Nullable
protected GuiDescription host;
- private final ObservableProperty<Boolean> hovered = ObservableProperty.of(false).nonnullValues();
+ private final ObservableProperty<Boolean> hovered = ObservableProperty.of(false).nonnullValues().setName("WWidget.hovered");
/**
* Sets the location of this widget relative to its parent.
@@ -461,11 +461,39 @@ public class WWidget {
public void addPainters() {
}
- public ObservableProperty<Boolean> getHovered() {
+ /**
+ * Returns whether the user is hovering over this widget.
+ * The result is an <i>observable property</i> that can be modified and listened to.
+ *
+ * @return the {@code hovered} property
+ * @since 4.2.0
+ */
+ public ObservableProperty<Boolean> hoveredProperty() {
return hovered;
}
/**
+ * Returns whether the user is hovering over this widget.
+ * This is equivalent to calling <code>{@link #hoveredProperty()}.get()</code>.
+ *
+ * @return true if this widget is hovered, false otherwise
+ * @since 4.2.0
+ */
+ public final boolean isHovered() {
+ return hoveredProperty().get();
+ }
+
+ /**
+ * Sets the {@link ##hoveredProperty()} hovered} property.
+ *
+ * @param hovered the new value; true if hovered, false otherwise
+ * @since 4.2.0
+ */
+ public final void setHovered(boolean hovered) {
+ hoveredProperty().set(hovered);
+ }
+
+ /**
* {@return whether this widget can be narrated}
*
* @see #addNarrations(NarrationMessageBuilder)
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
index 723cf60..3b0205e 100644
--- 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
@@ -7,10 +7,22 @@ import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;
-public final class ObservableProperty<T> {
+/**
+ * An observable mutable property. Observable properties are containers for values
+ * that can be modified, listened to and bound to other suppliers.
+ *
+ * <p>The naming convention for {@code ObservableProperty} getters follows the convention
+ * {@code <property name>Property}. For example, the {@code WWidget.hovered} property can be retrieved with
+ * {@link io.github.cottonmc.cotton.gui.widget.WWidget#hoveredProperty() hoveredProperty()}.
+ *
+ * @param <T> the contained value type
+ * @since 4.2.0
+ */
+public final class ObservableProperty<T> implements Supplier<T> {
private Supplier<? extends T> value;
private final List<ChangeListener<? super T>> listeners = new ArrayList<>();
private boolean allowNull = true;
+ private String name = "<unnamed>";
private ObservableProperty() {
}
@@ -36,13 +48,14 @@ public final class ObservableProperty<T> {
* @throws IllegalStateException if not initialized
* @throws NullPointerException if the value is null and null values aren't allowed
*/
+ @Override
public T get() {
if (value == null) {
- throw new IllegalStateException("Property not initialized!");
+ throw new IllegalStateException("Property " + name + " not initialized!");
}
T ret = value.get();
- if (ret == null && !allowNull) throw new NullPointerException("Null value for nonnull property!");
+ if (ret == null && !allowNull) throw new NullPointerException("Null value for nonnull property " + name + "!");
return ret;
}
@@ -66,9 +79,12 @@ public final class ObservableProperty<T> {
Objects.requireNonNull(value, "value");
T oldValue = this.value != null ? this.value.get() : null;
this.value = value;
+ T newValue = value.get();
- for (ChangeListener<? super T> listener : listeners) {
- listener.onPropertyChange(this, oldValue, value.get());
+ if (oldValue != newValue) {
+ for (ChangeListener<? super T> listener : listeners) {
+ listener.onPropertyChange(this, oldValue, newValue);
+ }
}
}
@@ -79,8 +95,10 @@ public final class ObservableProperty<T> {
T oldValue = this.value != null ? this.value.get() : null;
value = null;
- for (ChangeListener<? super T> listener : listeners) {
- listener.onPropertyChange(this, oldValue, null);
+ if (oldValue != null) {
+ for (ChangeListener<? super T> listener : listeners) {
+ listener.onPropertyChange(this, oldValue, null);
+ }
}
}
@@ -94,6 +112,24 @@ public final class ObservableProperty<T> {
return this;
}
+ /**
+ * {@return the name of this property}
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the name of this property, which is used in debug messages.
+ *
+ * @param name the new name
+ * @return this property
+ */
+ public ObservableProperty<T> setName(String name) {
+ this.name = Objects.requireNonNull(name, "name");
+ return this;
+ }
+
public void addListener(ChangeListener<? super T> listener) {
listeners.add(listener);
}