parent = child.toBuilder(); } else { parent.append(child); return parent.build(); for(int i = 0, size = extra.size(); i < size; i++) { final JsonElement extraElement = extra.get(i); component.append(this.deserialize(extraElement, extraElement.getClass(), context)); if(object.has("bold")) component.decoration(TextDecoration.BOLD, object.get("bold").getAsBoolean()); if(object.has("italic")) component.decoration(TextDecoration.ITALIC, object.get("italic").getAsBoolean()); if(object.has("underlined")) component.decoration(TextDecoration.UNDERLINED, object.get("underlined").getAsBoolean()); if(object.has("strikethrough")) component.decoration(TextDecoration.STRIKETHROUGH, object.get("strikethrough").getAsBoolean()); if(object.has("obfuscated")) component.decoration(TextDecoration.OBFUSCATED, object.get("obfuscated").getAsBoolean()); if(object.has("color")) component.color(context.deserialize(object.get("color"), TextColor.class)); if(object.has("insertion")) component.insertion(object.get("insertion").getAsString()); if(object.has("clickEvent")) { final JsonObject clickEvent = object.getAsJsonObject("clickEvent"); final /* @Nullable */ String value = rawValue == null ? null : rawValue.getAsString(); if(action != null && value != null && action.readable()) { component.clickEvent(new ClickEvent(action, value)); final /* @Nullable */ JsonElement rawValue = hoverEvent.get("value"); final /* @Nullable */ Component value = rawValue == null ? null : this.deserialize(rawValue, rawValue.getClass(), context); if(value != null) component.hoverEvent(new HoverEvent(action, value)); return component.build();
@Override @SuppressWarnings("unchecked") public @NonNull B applyDeep(final @NonNull Consumer<Builder<?, ?>> consumer) { this.apply(consumer); if(this.children == EMPTY_COMPONENT_LIST) { return (B) this; } final ListIterator<Component> it = this.children.listIterator(); while(it.hasNext()) { final Component child = it.next(); if(!(child instanceof BuildableComponent)) { continue; } final Builder<?, ?> childBuilder = ((BuildableComponent) child).toBuilder(); childBuilder.applyDeep(consumer); it.set(childBuilder.build()); } return (B) this; }
@Override @SuppressWarnings({"rawtypes", "unchecked"}) public @NonNull B mapChildrenDeep(final @NonNull Function<BuildableComponent<? ,?>, BuildableComponent<? ,?>> function) { if(this.children == EMPTY_COMPONENT_LIST) { return (B) this; } final ListIterator<Component> it = this.children.listIterator(); while(it.hasNext()) { final Component child = it.next(); if(!(child instanceof BuildableComponent)) { continue; } final BuildableComponent mappedChild = function.apply((BuildableComponent) child); if(mappedChild.children().isEmpty()) { if(child == mappedChild) { continue; } it.set(mappedChild); } else { final Builder<?, ?> builder = mappedChild.toBuilder(); builder.mapChildrenDeep(function); it.set(builder.build()); } } return (B) this; }
parent = child.toBuilder(); } else { parent.append(child); return parent.build(); for(int i = 0, size = extra.size(); i < size; i++) { final JsonElement extraElement = extra.get(i); component.append(this.deserialize(extraElement, extraElement.getClass(), context)); if(object.has("bold")) component.decoration(TextDecoration.BOLD, object.get("bold").getAsBoolean()); if(object.has("italic")) component.decoration(TextDecoration.ITALIC, object.get("italic").getAsBoolean()); if(object.has("underlined")) component.decoration(TextDecoration.UNDERLINE, object.get("underlined").getAsBoolean()); if(object.has("strikethrough")) component.decoration(TextDecoration.STRIKETHROUGH, object.get("strikethrough").getAsBoolean()); if(object.has("obfuscated")) component.decoration(TextDecoration.OBFUSCATED, object.get("obfuscated").getAsBoolean()); if(object.has("color")) component.color(context.deserialize(object.get("color"), TextColor.class)); if(object.has("insertion")) component.insertion(object.get("insertion").getAsString()); if(object.has("clickEvent")) { final JsonObject clickEvent = object.getAsJsonObject("clickEvent"); final /* @Nullable */ String value = rawValue == null ? null : rawValue.getAsString(); if(action != null && value != null && action.readable()) { component.clickEvent(new ClickEvent(action, value)); final /* @Nullable */ JsonElement rawValue = hoverEvent.get("value"); final /* @Nullable */ Component value = rawValue == null ? null : this.deserialize(rawValue, rawValue.getClass(), context); if(value != null) component.hoverEvent(new HoverEvent(action, value)); return component.build();
@Override @SuppressWarnings({"rawtypes", "unchecked"}) public @NonNull B mapChildrenDeep(final @NonNull Function<BuildableComponent<? ,?>, BuildableComponent<? ,?>> function) { if(this.children == EMPTY_COMPONENT_LIST) { return (B) this; } final ListIterator<Component> it = this.children.listIterator(); while(it.hasNext()) { final Component child = it.next(); if(!(child instanceof BuildableComponent)) { continue; } final BuildableComponent mappedChild = function.apply((BuildableComponent) child); if(mappedChild.children().isEmpty()) { if(child == mappedChild) { continue; } it.set(mappedChild); } else { final Builder<?, ?> builder = mappedChild.toBuilder(); builder.mapChildrenDeep(function); it.set(builder.build()); } } return (B) this; }
@Override public @NonNull B mapChildrenDeep(final @NonNull Function<BuildableComponent<? ,?>, BuildableComponent<? ,?>> function) { if(this.children == EMPTY_COMPONENT_LIST) { return (B) this; } final ListIterator<Component> it = this.children.listIterator(); while(it.hasNext()) { final Component child = it.next(); if(!(child instanceof BuildableComponent)) { continue; } final BuildableComponent mappedChild = function.apply((BuildableComponent) child); if(mappedChild.children().isEmpty()) { if(child == mappedChild) { continue; } it.set(mappedChild); } else { final Builder<?, ?> builder = mappedChild.toBuilder(); builder.mapChildrenDeep(function); it.set(builder.build()); } } return (B) this; }
@Override @SuppressWarnings("unchecked") public @NonNull B applyDeep(final @NonNull Consumer<Builder<?, ?>> consumer) { this.apply(consumer); if(this.children == EMPTY_COMPONENT_LIST) { return (B) this; } final ListIterator<Component> it = this.children.listIterator(); while(it.hasNext()) { final Component child = it.next(); if(!(child instanceof BuildableComponent)) { continue; } final Builder<?, ?> childBuilder = ((BuildableComponent) child).toBuilder(); childBuilder.applyDeep(consumer); it.set(childBuilder.build()); } return (B) this; }
@Override public @NonNull B applyDeep(final @NonNull Consumer<Builder<?, ?>> consumer) { this.apply(consumer); if(this.children == EMPTY_COMPONENT_LIST) { return (B) this; } final ListIterator<Component> it = this.children.listIterator(); while(it.hasNext()) { final Component child = it.next(); if(!(child instanceof BuildableComponent)) { continue; } final Builder<?, ?> childBuilder = ((BuildableComponent) child).toBuilder(); childBuilder.applyDeep(consumer); it.set(childBuilder.build()); } return (B) this; }
/** * Merges the decorations from another component into this component. * * @param that the other component * @return this builder */ @SuppressWarnings("unchecked") default @NonNull B mergeDecorations(final @NonNull Component that) { for(final TextDecoration decoration : TextDecoration.values()) { final TextDecoration.State state = that.decoration(decoration); if(state != TextDecoration.State.NOT_SET) this.decoration(decoration, state); } return (B) this; }
/** * Sets the state of a set of decorations to {@code flag} on this component. * * @param decorations the decorations * @param flag {@code true} if this component should have the decorations, {@code false} if * this component should not have the decorations * @return this builder */ @SuppressWarnings("unchecked") default @NonNull B decorations(final @NonNull Set<TextDecoration> decorations, final boolean flag) { final TextDecoration.State state = TextDecoration.State.byBoolean(flag); decorations.forEach(decoration -> this.decoration(decoration, state)); return (B) this; }
/** * Merges the decorations from another component into this component. * * @param that the other component * @return this builder */ @SuppressWarnings("unchecked") default @NonNull B mergeDecorations(final @NonNull Component that) { for(final TextDecoration decoration : TextDecoration.values()) { final TextDecoration.State state = that.decoration(decoration); if(state != TextDecoration.State.NOT_SET) this.decoration(decoration, state); } return (B) this; }
/** * Sets the state of a set of decorations to {@code flag} on this component. * * @param decorations the decorations * @param flag {@code true} if this component should have the decorations, {@code false} if * this component should not have the decorations * @return this builder */ @SuppressWarnings("unchecked") default @NonNull B decorations(final @NonNull Set<TextDecoration> decorations, final boolean flag) { final TextDecoration.State state = TextDecoration.State.byBoolean(flag); decorations.forEach(decoration -> this.decoration(decoration, state)); return (B) this; }
/** * Resets all styling on this component. * * @return this builder */ @SuppressWarnings("unchecked") default @NonNull B resetStyle() { this.color(null); for(final TextDecoration decoration : TextDecoration.values()) this.decoration(decoration, TextDecoration.State.NOT_SET); this.clickEvent(null); this.hoverEvent(null); return (B) this; }
/** * Sets the state of a set of decorations to {@code flag} on this component. * * @param decorations the decorations * @param flag {@code true} if this component should have the decorations, {@code false} if * this component should not have the decorations * @return this builder */ default @NonNull B decorations(final @NonNull Set<TextDecoration> decorations, final boolean flag) { final TextDecoration.State state = TextDecoration.State.byBoolean(flag); decorations.forEach(decoration -> this.decoration(decoration, state)); return (B) this; }
@Test void testMergeDecorations() { final C c0 = this.builder().build(); assertNull(c0.color()); assertDecorations(c0, ImmutableMap.of()); assertNull(c0.clickEvent()); final C c1 = (C) c0.mergeDecorations(TextComponent.of("xyz", TextColor.RED, ImmutableSet.of(TextDecoration.BOLD)).clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/foo"))); assertNull(c1.color()); assertDecorations(c1, ImmutableMap.of(TextDecoration.BOLD, TextDecoration.State.TRUE)); assertNull(c1.clickEvent()); assertEquals(c0, c1.decoration(TextDecoration.BOLD, TextDecoration.State.NOT_SET)); }
@Test void testHoverEvent() { final C c0 = this.builder().build(); assertNull(c0.hoverEvent()); final C c1 = (C) c0.hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("hover"))); assertNotNull(c1.hoverEvent()); assertEquals(c0, c1.hoverEvent(null)); }
@Test void testClickEvent() { final C c0 = this.builder().build(); assertNull(c0.clickEvent()); final C c1 = (C) c0.clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "foo")); assertNotNull(c1.clickEvent()); assertEquals(c0, c1.clickEvent(null)); }
@Test void testDecoration() { final C c0 = this.builder().build(); assertDecorations(c0, ImmutableMap.of()); final C c1 = (C) c0.decoration(TextDecoration.BOLD, true); assertDecorations(c1, ImmutableMap.of(TextDecoration.BOLD, TextDecoration.State.TRUE)); assertEquals(c0, c1.decoration(TextDecoration.BOLD, TextDecoration.State.NOT_SET)); }
/** * Merges the color from another component into this component. * * @param that the other component * @return this builder */ @SuppressWarnings("unchecked") default @NonNull B mergeColor(final @NonNull Component that) { if(that.color() != null) this.color(that.color()); return (B) this; }
/** * Merges styling from another component into this component. * * @param that the other component * @return this builder */ @SuppressWarnings("unchecked") default @NonNull B mergeStyle(final @NonNull Component that) { this.mergeColor(that); this.mergeDecorations(that); this.mergeEvents(that); return (B) this; }