/** * Checks if this component contains a component. * * @param that the other component * @return {@code true} if this component contains the provided * component, {@code false} otherwise */ default boolean contains(final @NonNull Component that) { if(this == that) return true; for(final Component child : this.children()) { if(child.contains(that)) return true; } if(this.hoverEvent() != null) { final Component hover = this.hoverEvent().value(); if(that == hover) return true; for(final Component child : hover.children()) { if(child.contains(that)) return true; } } return false; }
@Override public @NonNull TextComponent mergeStyle(final @NonNull Component that) { return new TextComponent(this.children, that.color(), that.decoration(TextDecoration.OBFUSCATED), that.decoration(TextDecoration.BOLD), that.decoration(TextDecoration.STRIKETHROUGH), that.decoration(TextDecoration.UNDERLINE), that.decoration(TextDecoration.ITALIC), that.clickEvent(), that.hoverEvent(), that.insertion(), this.content); }
/** * Gets a set of decorations this component has. * * @return a set of decorations this component has */ default @NonNull Set<TextDecoration> decorations() { return this.decorations(Collections.emptySet()); }
void apply(final @NonNull Component component) { if(component.color() != null) { this.color = component.color(); } for(final TextDecoration decoration : DECORATIONS) { switch(component.decoration(decoration)) { case TRUE: this.decorations.add(decoration); break; case FALSE: this.decorations.remove(decoration); break; } } }
if(!component.children().isEmpty()) { final JsonArray extra = new JsonArray(); for(final Component child : component.children()) { extra.add(this.serialize(child, child.getClass(), context)); if(component.hasStyling()) { for(final TextDecoration decoration : TextDecoration.values()) { final TextDecoration.State flag = component.decoration(decoration); if(flag != TextDecoration.State.NOT_SET) object.addProperty(decoration.toString(), flag == TextDecoration.State.TRUE); if(component.color() != null) object.add("color", context.serialize(component.color())); if(component.insertion() != null) object.add("insertion", context.serialize(component.insertion())); final /* @Nullable */ ClickEvent clickEvent = component.clickEvent(); if(clickEvent != null) { final JsonObject clickEventO = new JsonObject(); object.add("clickEvent", clickEventO); final /* @Nullable */ HoverEvent hoverEvent = component.hoverEvent(); if(hoverEvent != null) { final JsonObject hoverEventO = new JsonObject();
/** * Merges the events from another component into this component. * * @param that the other component * @return this builder */ default @NonNull B mergeEvents(final @NonNull Component that) { if(that.clickEvent() != null) this.clickEvent(that.clickEvent()); if(that.hoverEvent() != null) this.hoverEvent(that.hoverEvent().copy()); // hard copy, hover events have a component return (B) this; }
@Override public @NonNull TextComponent mergeDecorations(final @NonNull Component that) { final TextDecoration.State obfuscated = that.decoration(TextDecoration.OBFUSCATED) != TextDecoration.State.NOT_SET ? that.decoration(TextDecoration.OBFUSCATED) : this.obfuscated; final TextDecoration.State bold = that.decoration(TextDecoration.BOLD) != TextDecoration.State.NOT_SET ? that.decoration(TextDecoration.BOLD) : this.bold; final TextDecoration.State strikethrough = that.decoration(TextDecoration.STRIKETHROUGH) != TextDecoration.State.NOT_SET ? that.decoration(TextDecoration.STRIKETHROUGH) : this.strikethrough; final TextDecoration.State underlined = that.decoration(TextDecoration.UNDERLINED) != TextDecoration.State.NOT_SET ? that.decoration(TextDecoration.UNDERLINED) : this.underlined; final TextDecoration.State italic = that.decoration(TextDecoration.ITALIC) != TextDecoration.State.NOT_SET ? that.decoration(TextDecoration.ITALIC) : this.italic; return new TextComponent(this.children, this.color, obfuscated, bold, strikethrough, underlined, italic, this.clickEvent, this.hoverEvent, this.insertion, this.content); }
private <B extends BuildableComponent.Builder<?, ?>> B deepRender(final Component component, final B builder, final C context) { this.mergeStyle(component, builder, context); component.children().forEach(child -> builder.append(this.render(child, context))); return builder; }
@Test void testStyleReset() { Component component = TextComponent.builder() .content("kittens") .build(); assertFalse(component.hasStyling()); component = component.decoration(TextDecoration.BOLD, TextDecoration.State.TRUE); assertTrue(component.hasStyling()); component = component.resetStyle(); assertFalse(component.hasStyling()); }
@Test void testMergeStyle() { final C c0 = this.builder().build(); assertNull(c0.color()); assertDecorations(c0, ImmutableMap.of()); assertNull(c0.clickEvent()); final C c1 = (C) c0.mergeStyle(TextComponent.of("xyz", TextColor.RED, ImmutableSet.of(TextDecoration.BOLD)).clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/foo"))); assertEquals(TextColor.RED, c1.color()); assertDecorations(c1, ImmutableMap.of(TextDecoration.BOLD, TextDecoration.State.TRUE)); assertNotNull(c1.clickEvent()); assertEquals(c0, c1.color(null).decoration(TextDecoration.BOLD, TextDecoration.State.NOT_SET).clickEvent(null)); }
/** * Prevents a cycle between this component and the provided component. * * @param that the other component */ default void detectCycle(final @NonNull Component that) { if(that.contains(this)) { throw new IllegalStateException("Component cycle detected between " + this + " and " + that); } }
/** * Creates a copy of this hover event. * * @return a copy of this hover event */ public @NonNull HoverEvent copy() { return new HoverEvent(this.action, this.value.copy()); }
if(!component.children().isEmpty()) { final JsonArray extra = new JsonArray(); for(final Component child : component.children()) { extra.add(this.serialize(child, child.getClass(), context)); if(component.hasStyling()) { for(final TextDecoration decoration : TextDecoration.values()) { final TextDecoration.State flag = component.decoration(decoration); if(flag != TextDecoration.State.NOT_SET) object.addProperty(decoration.toString(), flag == TextDecoration.State.TRUE); if(component.color() != null) object.add("color", context.serialize(component.color())); if(component.insertion() != null) object.add("insertion", context.serialize(component.insertion())); final /* @Nullable */ ClickEvent clickEvent = component.clickEvent(); if(clickEvent != null) { final JsonObject clickEventO = new JsonObject(); object.add("clickEvent", clickEventO); final /* @Nullable */ HoverEvent hoverEvent = component.hoverEvent(); if(hoverEvent != null) { final JsonObject hoverEventO = new JsonObject();
/** * Merges the events from another component into this component. * * @param that the other component * @return this builder */ @SuppressWarnings("unchecked") default @NonNull B mergeEvents(final @NonNull Component that) { if(that.clickEvent() != null) this.clickEvent(that.clickEvent()); if(that.hoverEvent() != null) this.hoverEvent(that.hoverEvent().copy()); // hard copy, hover events have a component return (B) this; }
@Override public @NonNull ScoreComponent mergeDecorations(final @NonNull Component that) { final TextDecoration.State obfuscated = that.decoration(TextDecoration.OBFUSCATED) != TextDecoration.State.NOT_SET ? that.decoration(TextDecoration.OBFUSCATED) : this.obfuscated; final TextDecoration.State bold = that.decoration(TextDecoration.BOLD) != TextDecoration.State.NOT_SET ? that.decoration(TextDecoration.BOLD) : this.bold; final TextDecoration.State strikethrough = that.decoration(TextDecoration.STRIKETHROUGH) != TextDecoration.State.NOT_SET ? that.decoration(TextDecoration.STRIKETHROUGH) : this.strikethrough; final TextDecoration.State underlined = that.decoration(TextDecoration.UNDERLINE) != TextDecoration.State.NOT_SET ? that.decoration(TextDecoration.UNDERLINE) : this.underlined; final TextDecoration.State italic = that.decoration(TextDecoration.ITALIC) != TextDecoration.State.NOT_SET ? that.decoration(TextDecoration.ITALIC) : this.italic; return new ScoreComponent(this.children, this.color, obfuscated, bold, strikethrough, underlined, italic, this.clickEvent, this.hoverEvent, this.insertion, this.name, this.objective, this.value); }
private <B extends BuildableComponent.Builder<?, ?>> B deepRender(final Component component, final B builder, final C context) { this.mergeStyle(component, builder, context); component.children().forEach(child -> builder.append(this.render(child, context))); return builder; }
void apply(final @NonNull Component component) { if(component.color() != null) { this.color = component.color(); } for(final TextDecoration decoration : DECORATIONS) { switch(component.decoration(decoration)) { case TRUE: this.decorations.add(decoration); break; case FALSE: this.decorations.remove(decoration); break; } } }
/** * Prevents a cycle between this component and the provided component. * * @param that the other component */ default void detectCycle(final @NonNull Component that) { if(that.contains(this)) { throw new IllegalStateException("Component cycle detected between " + this + " and " + that); } }