diff --git a/api/src/main/java/net/kyori/adventure/text/AbstractComponentBuilder.java b/api/src/main/java/net/kyori/adventure/text/AbstractComponentBuilder.java index 93f78a058..a6add27c0 100644 --- a/api/src/main/java/net/kyori/adventure/text/AbstractComponentBuilder.java +++ b/api/src/main/java/net/kyori/adventure/text/AbstractComponentBuilder.java @@ -243,6 +243,13 @@ private void prepareChildren() { return (B) this; } + @Override + @SuppressWarnings("unchecked") + public @NotNull B decorationIfAbsent(final @NotNull TextDecoration decoration, final TextDecoration.@NotNull State state) { + this.styleBuilder().decorationIfAbsent(decoration, state); + return (B) this; + } + @Override @SuppressWarnings("unchecked") public @NotNull B clickEvent(final @Nullable ClickEvent event) { diff --git a/api/src/main/java/net/kyori/adventure/text/Component.java b/api/src/main/java/net/kyori/adventure/text/Component.java index 1f8419863..4efca8834 100644 --- a/api/src/main/java/net/kyori/adventure/text/Component.java +++ b/api/src/main/java/net/kyori/adventure/text/Component.java @@ -1988,6 +1988,26 @@ default boolean hasDecoration(final @NotNull TextDecoration decoration) { return this.style(this.style().decoration(decoration, state)); } + /** + * Sets the state of a decoration on this component to {@code state} if the current state of + * the decoration is {@link TextDecoration.State#NOT_SET}. + * + * @param decoration the decoration + * @param state the state + * @return a component + * @since 4.12.0 + */ + @Override + default @NotNull Component decorationIfAbsent(final @NotNull TextDecoration decoration, @NotNull final TextDecoration.State state) { + requireNonNull(state, "state"); + // Not delegating this method prevents object creation if decoration is NOT absent + final TextDecoration.@NotNull State oldState = this.decoration(decoration); + if (oldState == TextDecoration.State.NOT_SET) { + return this.style(this.style().decoration(decoration, state)); + } + return this; + } + /** * Gets a set of decorations this component has. * diff --git a/api/src/main/java/net/kyori/adventure/text/ComponentBuilder.java b/api/src/main/java/net/kyori/adventure/text/ComponentBuilder.java index c32396098..04047e784 100644 --- a/api/src/main/java/net/kyori/adventure/text/ComponentBuilder.java +++ b/api/src/main/java/net/kyori/adventure/text/ComponentBuilder.java @@ -308,6 +308,19 @@ public interface ComponentBuilder, B extends @Override @NotNull B decoration(final @NotNull TextDecoration decoration, final TextDecoration.@NotNull State state); + /** + * Sets the state of a decoration on this component to {@code state} if the current state of + * the decoration is {@link TextDecoration.State#NOT_SET}. + * + * @param decoration the decoration + * @param state the state + * @return this builder + * @since 4.12.0 + */ + @Contract("_, _ -> this") + @Override + @NotNull B decorationIfAbsent(final @NotNull TextDecoration decoration, @NotNull final TextDecoration.State state); + /** * Sets the click event of this component. * diff --git a/api/src/main/java/net/kyori/adventure/text/format/Style.java b/api/src/main/java/net/kyori/adventure/text/format/Style.java index 34163f6b9..55015acc4 100644 --- a/api/src/main/java/net/kyori/adventure/text/format/Style.java +++ b/api/src/main/java/net/kyori/adventure/text/format/Style.java @@ -341,6 +341,18 @@ default boolean hasDecoration(final @NotNull TextDecoration decoration) { @Override @NotNull Style decoration(final @NotNull TextDecoration decoration, final TextDecoration.@NotNull State state); + /** + * Sets the state of a decoration on this style to {@code state} if the current state of + * the decoration is {@link TextDecoration.State#NOT_SET}. + * + * @param decoration the decoration + * @param state the state + * @return a style + * @since 4.12.0 + */ + @Override + @NotNull Style decorationIfAbsent(final @NotNull TextDecoration decoration, @NotNull final TextDecoration.State state); + /** * Gets a map of decorations this style has. * @@ -761,6 +773,18 @@ interface Builder extends AbstractBuilder