Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api): Add possibility of using Component#join with a root style #653

Merged
merged 3 commits into from
Apr 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.function.Function;
import java.util.function.Predicate;
import net.kyori.adventure.builder.AbstractBuilder;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.util.Buildable;
import net.kyori.examination.Examinable;
import org.jetbrains.annotations.ApiStatus;
Expand Down Expand Up @@ -62,6 +63,10 @@
* <b>a predicate</b> (required, defaults to {@code true})
* <p>a predicate that specifies if a given component should be included in the join process</p>
* </li>
* <li>
* <b>a root {@link Style style} (required, defaults to {@link Style#empty()})</b>
* <p>the style of the parent component that contains the joined components.</p>
* </li>
* </ul>
*
* <p>Note that the last separator only acts as an override for the normal separator.
Expand Down Expand Up @@ -228,6 +233,14 @@ public interface JoinConfiguration extends Buildable<JoinConfiguration, JoinConf
*/
@NotNull Predicate<ComponentLike> predicate();

/**
* Gets the style of the parent component that contains the joined components.
*
* @return the style
* @since 4.11.0
*/
@NotNull Style parentStyle();

/**
* A builder for join configurations.
*
Expand Down Expand Up @@ -300,7 +313,7 @@ interface Builder extends AbstractBuilder<JoinConfiguration>, Buildable.Builder<
@NotNull Builder convertor(final @NotNull Function<ComponentLike, Component> convertor);

/**
* Gets the predicate of this join configuration builder.
* Sets the predicate of this join configuration builder.
*
* <p>This is used to determine if a component is to be included in the join process. It does not touch the prefix, suffix or any of the separators.</p>
*
Expand All @@ -310,5 +323,15 @@ interface Builder extends AbstractBuilder<JoinConfiguration>, Buildable.Builder<
*/
@Contract("_ -> this")
@NotNull Builder predicate(final @NotNull Predicate<ComponentLike> predicate);

/**
* Sets the style of the parent component that contains the joined components.
*
* @param parentStyle the style
* @return this builder
* @since 4.11.0
*/
@Contract("_ -> this")
@NotNull Builder parentStyle(final @NotNull Style parentStyle);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.function.Predicate;
import java.util.stream.Stream;
import net.kyori.adventure.internal.Internals;
import net.kyori.adventure.text.format.Style;
import net.kyori.examination.ExaminableProperty;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
Expand All @@ -55,6 +56,7 @@ final class JoinConfigurationImpl implements JoinConfiguration {
private final Component lastSeparatorIfSerial;
private final Function<ComponentLike, Component> convertor;
private final Predicate<ComponentLike> predicate;
private final Style rootStyle;

private JoinConfigurationImpl() {
this.prefix = null;
Expand All @@ -64,6 +66,7 @@ private JoinConfigurationImpl() {
this.lastSeparatorIfSerial = null;
this.convertor = DEFAULT_CONVERTOR;
this.predicate = DEFAULT_PREDICATE;
this.rootStyle = Style.empty();
}

private JoinConfigurationImpl(final @NotNull BuilderImpl builder) {
Expand All @@ -74,6 +77,7 @@ private JoinConfigurationImpl(final @NotNull BuilderImpl builder) {
this.lastSeparatorIfSerial = ComponentLike.unbox(builder.lastSeparatorIfSerial);
this.convertor = builder.convertor;
this.predicate = builder.predicate;
this.rootStyle = builder.rootStyle;
}

@Override
Expand Down Expand Up @@ -111,6 +115,11 @@ private JoinConfigurationImpl(final @NotNull BuilderImpl builder) {
return this.predicate;
}

@Override
public @NotNull Style parentStyle() {
return this.rootStyle;
}

@Override
public JoinConfiguration.@NotNull Builder toBuilder() {
return new BuilderImpl(this);
Expand All @@ -125,7 +134,8 @@ private JoinConfigurationImpl(final @NotNull BuilderImpl builder) {
ExaminableProperty.of("lastSeparator", this.lastSeparator),
ExaminableProperty.of("lastSeparatorIfSerial", this.lastSeparatorIfSerial),
ExaminableProperty.of("convertor", this.convertor),
ExaminableProperty.of("predicate", this.predicate)
ExaminableProperty.of("predicate", this.predicate),
ExaminableProperty.of("rootStyle", this.rootStyle)
);
}

Expand All @@ -140,10 +150,6 @@ public String toString() {
Objects.requireNonNull(components, "components");

final Iterator<? extends ComponentLike> it = components.iterator();
final Component prefix = config.prefix();
final Component suffix = config.suffix();
final Function<ComponentLike, Component> convertor = config.convertor();
final Predicate<ComponentLike> predicate = config.predicate();

if (!it.hasNext()) {
return singleElementJoin(config, null);
KingOfSquares marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -153,13 +159,26 @@ public String toString() {
int componentsSeen = 0;

if (!it.hasNext()) {
return singleElementJoin(config, component);
return singleElementJoin(
config,
component
);
}

final Component prefix = config.prefix();
final Component suffix = config.suffix();
final Function<ComponentLike, Component> convertor = config.convertor();
final Predicate<ComponentLike> predicate = config.predicate();
final Style rootStyle = config.parentStyle();
final boolean hasRootStyle = rootStyle != Style.empty();

final Component separator = config.separator();
final boolean hasSeparator = separator != null;

final TextComponent.Builder builder = Component.text();
final TextComponent.Builder builder =
hasRootStyle ?
Component.text().style(rootStyle) :
Component.text();
if (prefix != null) builder.append(prefix);

while (component != null) {
Expand Down Expand Up @@ -203,20 +222,24 @@ public String toString() {
final Component suffix = config.suffix();
final Function<ComponentLike, Component> convertor = config.convertor();
final Predicate<ComponentLike> predicate = config.predicate();
final Style rootStyle = config.parentStyle();
final boolean hasRootStyle = rootStyle != Style.empty();

if (prefix == null && suffix == null) {
final Component result;
if (component == null || !predicate.test(component)) {
return Component.empty();
result = Component.empty();
} else {
return convertor.apply(component);
result = convertor.apply(component);
}
return hasRootStyle ? Component.text().style(rootStyle).append(result).build() : result;
}

final TextComponent.Builder builder = Component.text();
if (prefix != null) builder.append(prefix);
if (component != null && predicate.test(component)) builder.append(convertor.apply(component));
if (suffix != null) builder.append(suffix);
return builder.build();
return hasRootStyle ? Component.text().style(rootStyle).append(builder).build() : builder.build();
}

static final class BuilderImpl implements JoinConfiguration.Builder {
Expand All @@ -227,6 +250,7 @@ static final class BuilderImpl implements JoinConfiguration.Builder {
private ComponentLike lastSeparatorIfSerial;
private Function<ComponentLike, Component> convertor;
private Predicate<ComponentLike> predicate;
private Style rootStyle;

BuilderImpl() {
this(JoinConfigurationImpl.NULL);
Expand All @@ -240,6 +264,7 @@ private BuilderImpl(final @NotNull JoinConfigurationImpl joinConfig) {
this.convertor = joinConfig.convertor;
this.lastSeparatorIfSerial = joinConfig.lastSeparatorIfSerial;
this.predicate = joinConfig.predicate;
this.rootStyle = joinConfig.rootStyle;
}

@Override
Expand Down Expand Up @@ -284,6 +309,12 @@ private BuilderImpl(final @NotNull JoinConfigurationImpl joinConfig) {
return this;
}

@Override
public @NotNull Builder parentStyle(final @NotNull Style parentStyle) {
this.rootStyle = Objects.requireNonNull(parentStyle, "rootStyle");
return this;
}

@Override
public @NotNull JoinConfiguration build() {
return new JoinConfigurationImpl(this);
Expand Down
52 changes: 52 additions & 0 deletions api/src/test/java/net/kyori/adventure/text/JoinTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@
*/
package net.kyori.adventure.text;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextDecoration;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -319,6 +323,54 @@ final void testStandardJoinConfigurationsArrayLike() {
);
}

@Test
final void testJoinWithRootStyle() {
final Style style = Style.style(NamedTextColor.RED, TextDecoration.BOLD);
final Style epicStyle = Style.style(NamedTextColor.BLACK, TextDecoration.ITALIC);
final List<Component> componentsToJoin = new ArrayList<>();
componentsToJoin.add(Component.text("FIRST"));
componentsToJoin.add(Component.text("SECOND", style));
componentsToJoin.add(Component.text("THIRD"));
final Component result = Component.join(JoinConfiguration.builder().separator(Component.text(",")).parentStyle(epicStyle).build(), componentsToJoin);

assertEquals(
Component.text().style(epicStyle)
.append(Component.text("FIRST"))
.append(Component.text(","))
.append(Component.text("SECOND", style))
.append(Component.text(","))
.append(Component.text("THIRD"))
.build(),
result
);
}

@Test
final void testJoinWithRootStyleSingleComponent() {
final List<Component> componentsToJoin = new ArrayList<>();
componentsToJoin.add(Component.text("FIRST"));
final Style epicStyle = Style.style(NamedTextColor.BLACK, TextDecoration.ITALIC);
final Component result = Component.join(JoinConfiguration.builder().separator(Component.text(",")).parentStyle(epicStyle).build(), componentsToJoin);

assertEquals(
Component.text().style(epicStyle)
.append(Component.text("FIRST"))
.build(),
result
);
}

@Test
final void testJoinWithRootStyleNoComponents() {
final List<Component> componentsToJoin = new ArrayList<>();
final Style epicStyle = Style.style(NamedTextColor.BLACK, TextDecoration.ITALIC);
final Component result = Component.join(JoinConfiguration.builder().separator(Component.text(", ")).parentStyle(epicStyle).build(), componentsToJoin);

assertEquals(
Component.text().style(epicStyle).build(),
result);
}

private static final class TestComponentLike implements ComponentLike {

@Override
Expand Down