package com.onarandombox.MultiverseCore.display; import com.onarandombox.MultiverseCore.display.settings.DisplaySetting; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.Map; import java.util.Objects; import java.util.WeakHashMap; /** * Helps to display contents such as list and maps in a nicely formatted fashion. * * @param Type of content to display. */ public class ContentDisplay { public static final String LINE_BREAK = "%br%"; /** * Creates a ContentDisplay.Builder for the given content. * * @param content The content to be displayed. * @param The type of the content which can be inferred. * @return A new Builder. */ public static Builder forContent(T content) { return new Builder<>(content); } /** * Creates a ContentDisplay.Builder for the given collection of content. * * @param content The content to be displayed. * @return A new Builder. */ public static Builder> forContent(Collection content) { return new Builder<>(content).displayHandler(DisplayHandlers.LIST); } /** * Creates a ContentDisplay.Builder for the given map of content. * * @param content The content to be displayed. * @return A new Builder. */ public static Builder> forContent(Map content) { return new Builder<>(content).displayHandler(DisplayHandlers.INLINE_MAP); } private final T contents; private String header; private String emptyMessage = "No matching content to display."; private DisplayHandler displayHandler; private ColorTool colorTool = ColorTool.DEFAULT; private ContentFilter filter = ContentFilter.DEFAULT; private final Map, Object> settingsMap = new WeakHashMap<>(); private ContentDisplay(T contents) { this.contents = contents; } /** * Do the actual displaying of contents to the sender. * * @param sender The CommandSender to show the display to. */ public void show(@NotNull CommandSender sender) { Collection formattedContent; try { formattedContent = (this.contents == null) ? null : this.displayHandler.format(sender, this); } catch (DisplayFormatException e) { sender.sendMessage(String.format("%sError: %s", ChatColor.RED, e.getMessage())); return; } this.displayHandler.sendHeader(sender, this); this.displayHandler.sendSubHeader(sender, this); this.displayHandler.sendBody(sender, this, formattedContent); } /** * @return Gets the header to display. */ public String getHeader() { return header; } /** * Sets the header text. */ public void setHeader(@NotNull String header) { this.header = header; } /** * @return Gets the contents to display. */ public T getContents() { return contents; } /** * @return Gets the message to display when no content is shown. */ @NotNull public String getEmptyMessage() { return emptyMessage; } /** * @return Gets the display handler that formats and sends content to sender. */ @NotNull public DisplayHandler getDisplayHandler() { return displayHandler; } /** * @return Gets the color tool used. */ @NotNull public ColorTool getColorTool() { return colorTool; } /** * @return Gets the filter used. */ @NotNull public ContentFilter getFilter() { return filter; } /** * Gets the value for a given setting option. * * @param setting The setting option. * @param The setting type. * @return Value set for the given setting. */ public S getSetting(@NotNull DisplaySetting setting) { return (S) settingsMap.getOrDefault(setting, setting.defaultValue()); } /** * Sets other specific settings that may be used by the {@link DisplayHandler}. * * @param setting The settings option. * @param value The value to set. * @param The type of setting. */ public void setSetting(@NotNull DisplaySetting setting, S value) { this.settingsMap.put(setting, value); } /** * Builds a {@link ContentDisplay}. * * @param Type of content to display. */ public static class Builder { private final ContentDisplay display; private Builder(T content) { this.display = new ContentDisplay<>(content); } /** * Sets header to be displayed. * * @param header The header text. * @param replacements String formatting replacements. * @return The builder. */ @NotNull public Builder header(@NotNull String header, Object...replacements) { this.display.header = String.format(header, replacements); return this; } /** * Sets the message to show when no content is available for display. * * @param emptyMessage The message text. * @param replacements String formatting replacements. * @return The builder. */ @NotNull public Builder emptyMessage(@NotNull String emptyMessage, Object...replacements) { this.display.emptyMessage = String.format(emptyMessage, replacements); return this; } /** * Sets the display handler that does the formatting and sending of content. Required. * * @param displayHandler The display handler for the given content type. * @return The builder. */ @NotNull public Builder displayHandler(@NotNull DisplayHandler displayHandler) { this.display.displayHandler = displayHandler; return this; } /** * Sets the color tool used to make messages more colourful. * * @param colorTool The color tool to use. * @return The builder. */ @NotNull public Builder colorTool(@NotNull ColorTool colorTool) { this.display.colorTool = colorTool; return this; } /** * Sets content filter used to match specific content to be displayed. * * @param filter The filter to use. * @return The builder. */ @NotNull public Builder filter(@NotNull ContentFilter filter) { this.display.filter = filter; return this; } /** * Sets other specific settings that may be used by the {@link DisplayHandler}. * * @param setting The settings option. * @param value The value to set. * @param The type of setting. * @return The builder. */ @NotNull public Builder setting(@NotNull DisplaySetting setting, S value) { this.display.settingsMap.put(setting, value); return this; } /** * Validates and build the content display. * * @return The content display. */ @NotNull public ContentDisplay build() { Objects.requireNonNull(this.display.displayHandler); return this.display; } /** * Build and show the content to the sender. * * @param sender The CommandSender to show the display to. */ public void show(CommandSender sender) { this.build().show(sender); } } }