From 1a511db789eb4245ec54aa6b50ac882dbdea87b1 Mon Sep 17 00:00:00 2001 From: Juuz <6596629+Juuxel@users.noreply.github.com> Date: Sun, 19 Mar 2023 13:18:40 +0200 Subject: Add simple focus model implementation --- .../cotton/gui/widget/focus/FocusModel.java | 2 + .../gui/widget/focus/SimpleKeyedFocusModel.java | 140 +++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 src/main/java/io/github/cottonmc/cotton/gui/widget/focus/SimpleKeyedFocusModel.java diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/focus/FocusModel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/focus/FocusModel.java index 615f686..c3a5204 100644 --- a/src/main/java/io/github/cottonmc/cotton/gui/widget/focus/FocusModel.java +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/focus/FocusModel.java @@ -11,6 +11,8 @@ import java.util.stream.Stream; * * @param the focus key type * @since 7.0.0 + * @see #simple(WWidget) FocusModel.simple() + * @see SimpleKeyedFocusModel */ public interface FocusModel { /** diff --git a/src/main/java/io/github/cottonmc/cotton/gui/widget/focus/SimpleKeyedFocusModel.java b/src/main/java/io/github/cottonmc/cotton/gui/widget/focus/SimpleKeyedFocusModel.java new file mode 100644 index 0000000..491f4db --- /dev/null +++ b/src/main/java/io/github/cottonmc/cotton/gui/widget/focus/SimpleKeyedFocusModel.java @@ -0,0 +1,140 @@ +package io.github.cottonmc.cotton.gui.widget.focus; + +import io.github.cottonmc.cotton.gui.widget.data.Rect2i; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Stream; + +/** + * A {@link FocusModel} implementation that wraps a {@link List} of foci. + * New instances can be created with the constructor or the {@linkplain Builder builder}. + * + * @param the focus key type + * @since 7.0.0 + */ +public final class SimpleKeyedFocusModel implements FocusModel { + private final List> foci; + private @Nullable K focused; + + /** + * Constructs a keyed focus model. + * + * @param foci the foci + * @throws IllegalArgumentException if there are duplicate keys + */ + public SimpleKeyedFocusModel(List> foci) { + this.foci = Objects.requireNonNull(foci, "foci"); + + Set keys = new HashSet<>(); + for (Focus focus : foci) { + if (!keys.add(focus.key())) { + throw new IllegalArgumentException("Duplicate focus key: " + focus.key()); + } + } + } + + /** + * {@return the focused key, or {@code null} if not available} + */ + public @Nullable K getFocusedKey() { + return focused; + } + + @Override + public boolean isFocused(Focus focus) { + return Objects.equals(focus.key(), focused); + } + + @Override + public void setFocused(Focus focus) { + focused = focus.key(); + } + + @Override + public Stream> foci() { + return foci.stream(); + } + + /** + * Creates a builder for {@code SimpleKeyedFocusModel}. + * + * @param the focus key type + * @return the builder + */ + @Contract("-> new") + public static Builder builder() { + return new Builder<>(); + } + + /** + * A builder for {@code SimpleKeyedFocusModel}. + * New instances can be obtained using {@link #builder()}. + * + *

This builder class is reusable – created instances are not + * affected by data added to this builder afterwards. + * + * @param the focus key type + */ + public static final class Builder { + private final List> foci = new ArrayList<>(); + + private Builder() { + } + + /** + * Adds a focus to this builder. + * + * @param focus the focus to add + * @return this builder + */ + @Contract("null -> fail; _ -> this") + public Builder add(Focus focus) { + Objects.requireNonNull(focus, "Focus cannot be null"); + foci.add(focus); + return this; + } + + /** + * Adds a focus to this builder. + * + * @param key the focus key + * @param area the focus area + * @return this builder + */ + @Contract("_, null -> fail; _, _ -> this") + public Builder add(K key, Rect2i area) { + Objects.requireNonNull(area, "Focus area cannot be null"); + return add(new Focus<>(key, area)); + } + + /** + * Adds foci from a collection to this builder. + * + * @param foci the foci to add + * @return this builder + */ + @Contract("null -> fail; _ -> this") + public Builder addAll(Collection> foci) { + Objects.requireNonNull(foci, "Foci cannot be null"); + this.foci.addAll(foci); + return this; + } + + /** + * Builds a new {@code SimpleKeyedFocusModel} from the data in this builder. + * + * @return the created model + */ + @Contract("-> new") + public SimpleKeyedFocusModel build() { + return new SimpleKeyedFocusModel<>(List.copyOf(foci)); + } + } +} -- cgit