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

api: Style#unmerge #793

Merged
merged 1 commit into from Nov 12, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -33,16 +33,14 @@
import org.jetbrains.annotations.Nullable;

final class ComponentCompaction {
private static final TextDecoration[] DECORATIONS = TextDecoration.values();

private ComponentCompaction() {
}

static Component compact(final @NotNull Component self, final @Nullable Style parentStyle) {
final List<Component> children = self.children();
Component optimized = self.children(Collections.emptyList());
if (parentStyle != null) {
optimized = optimized.style(simplifyStyle(self.style(), parentStyle));
optimized = optimized.style(self.style().unmerge(parentStyle));
}

final int childrenSize = children.size();
Expand Down Expand Up @@ -153,49 +151,6 @@ static Component compact(final @NotNull Component self, final @Nullable Style pa
return optimized.children(childrenToAppend);
}

/**
* Simplify the provided style to remove any information that is redundant.
*
* @param style style to simplify
* @param parentStyle parent to compare against
* @return a new, simplified style
*/
private static @NotNull Style simplifyStyle(final @NotNull Style style, final @NotNull Style parentStyle) {
if (style.isEmpty()) {
// the target style is empty, so there is nothing to simplify
return style;
}

final Style.Builder builder = style.toBuilder();
if (Objects.equals(style.font(), parentStyle.font())) {
builder.font(null);
}

if (Objects.equals(style.color(), parentStyle.color())) {
builder.color(null);
}

for (final TextDecoration decoration : DECORATIONS) {
if (style.decoration(decoration) == parentStyle.decoration(decoration)) {
builder.decoration(decoration, TextDecoration.State.NOT_SET);
}
}

if (Objects.equals(style.clickEvent(), parentStyle.clickEvent())) {
builder.clickEvent(null);
}

if (Objects.equals(style.hoverEvent(), parentStyle.hoverEvent())) {
builder.hoverEvent(null);
}

if (Objects.equals(style.insertion(), parentStyle.insertion())) {
builder.insertion(null);
}

return builder.build();
}

/**
* Checks whether the Component is blank (a TextComponent containing only space characters).
*
Expand Down
9 changes: 9 additions & 0 deletions api/src/main/java/net/kyori/adventure/text/format/Style.java
Expand Up @@ -529,6 +529,15 @@ default boolean hasDecoration(final @NotNull TextDecoration decoration) {
*/
@NotNull Style merge(final @NotNull Style that, final Merge.@NotNull Strategy strategy, final @NotNull Set<Merge> merges);

/**
* Simplify this style to remove any information that is redundant.
*
* @param that parent to compare against
* @return a new, simplified style
* @since 4.12.0
*/
@NotNull Style unmerge(final @NotNull Style that);

/**
* Tests if this style is empty.
*
Expand Down
39 changes: 39 additions & 0 deletions api/src/main/java/net/kyori/adventure/text/format/StyleImpl.java
Expand Up @@ -183,6 +183,45 @@ final class StyleImpl implements Style {
return builder.build();
}

@Override
public @NotNull Style unmerge(final @NotNull Style that) {
if (this.isEmpty()) {
// the target style is empty, so there is nothing to simplify
return this;
}

final Style.Builder builder = new BuilderImpl(this);

if (Objects.equals(this.font(), that.font())) {
builder.font(null);
}

if (Objects.equals(this.color(), that.color())) {
builder.color(null);
}

for (int i = 0, length = DecorationMap.DECORATIONS.length; i < length; i++) {
final TextDecoration decoration = DecorationMap.DECORATIONS[i];
if (this.decoration(decoration) == that.decoration(decoration)) {
builder.decoration(decoration, TextDecoration.State.NOT_SET);
}
}

if (Objects.equals(this.clickEvent(), that.clickEvent())) {
builder.clickEvent(null);
}

if (Objects.equals(this.hoverEvent(), that.hoverEvent())) {
builder.hoverEvent(null);
}

if (Objects.equals(this.insertion(), that.insertion())) {
builder.insertion(null);
}

return builder.build();
}

@SuppressWarnings("RedundantIfStatement")
static boolean nothingToMerge(final @NotNull Style mergeFrom, final Merge.@NotNull Strategy strategy, final @NotNull Set<Merge> merges) {
if (strategy == Merge.Strategy.NEVER) return true;
Expand Down
26 changes: 26 additions & 0 deletions api/src/test/java/net/kyori/adventure/text/format/StyleTest.java
Expand Up @@ -370,6 +370,32 @@ void testBuilderMerge_color() {
);
}

@Test
void testUnmergeEmpty() {
final Style s0 = Style.empty();
final Style s1 = Style.style(NamedTextColor.DARK_RED, TextDecoration.BOLD, TextDecoration.ITALIC);
final Style s2 = s1.unmerge(s0);
assertEquals(NamedTextColor.DARK_RED, s2.color());
assertDecorations(s2, ImmutableSet.of(TextDecoration.BOLD, TextDecoration.ITALIC), ImmutableSet.of());
}

@Test
void testUnmerge() {
final Style s0 = Style.style(NamedTextColor.DARK_RED, TextDecoration.BOLD);
final Style s1 = Style.style(NamedTextColor.DARK_RED, TextDecoration.BOLD, TextDecoration.ITALIC);
final Style s2 = s1.unmerge(s0);
assertNull(s2.color());
assertDecorations(s2, ImmutableSet.of(TextDecoration.ITALIC), ImmutableSet.of());
}

@Test
void testUnmergeWithEmptyChild() {
final Style s0 = Style.style(NamedTextColor.DARK_RED, TextDecoration.BOLD);
final Style s1 = Style.empty();
final Style s2 = s1.unmerge(s0);
assertSame(s1, s2);
}

@Test
void testEquals() {
new EqualsTester()
Expand Down