diff --git a/src/main/java/de/studiocode/invui/gui/Controllable.java b/src/main/java/de/studiocode/invui/gui/Controllable.java new file mode 100644 index 0000000..971176e --- /dev/null +++ b/src/main/java/de/studiocode/invui/gui/Controllable.java @@ -0,0 +1,9 @@ +package de.studiocode.invui.gui; + +import de.studiocode.invui.item.impl.controlitem.ControlItem; + +public interface Controllable { + + void addControlItem(int index, ControlItem controlItem); + +} diff --git a/src/main/java/de/studiocode/invui/gui/GUI.java b/src/main/java/de/studiocode/invui/gui/GUI.java index 7fbec12..f786bc2 100644 --- a/src/main/java/de/studiocode/invui/gui/GUI.java +++ b/src/main/java/de/studiocode/invui/gui/GUI.java @@ -3,8 +3,6 @@ package de.studiocode.invui.gui; import de.studiocode.invui.animation.Animation; import de.studiocode.invui.gui.SlotElement.ItemStackHolder; import de.studiocode.invui.gui.builder.GUIBuilder; -import de.studiocode.invui.gui.builder.PagedGUIBuilder; -import de.studiocode.invui.gui.builder.TabGUIBuilder; import de.studiocode.invui.gui.impl.*; import de.studiocode.invui.item.Item; import de.studiocode.invui.virtualinventory.VirtualInventory; @@ -38,8 +36,6 @@ import java.util.function.Predicate; * @see SimplePagedGUIsGUI * @see SimpleTabGUI * @see GUIBuilder - * @see PagedGUIBuilder - * @see TabGUIBuilder */ public interface GUI extends GUIParent { diff --git a/src/main/java/de/studiocode/invui/gui/builder/GUIBuilder.java b/src/main/java/de/studiocode/invui/gui/builder/GUIBuilder.java index 26ca249..8bdfd8e 100644 --- a/src/main/java/de/studiocode/invui/gui/builder/GUIBuilder.java +++ b/src/main/java/de/studiocode/invui/gui/builder/GUIBuilder.java @@ -2,15 +2,19 @@ package de.studiocode.invui.gui.builder; import de.studiocode.invui.gui.GUI; import de.studiocode.invui.gui.SlotElement; -import de.studiocode.invui.gui.impl.SimpleGUI; +import de.studiocode.invui.gui.SlotElement.ItemSlotElement; +import de.studiocode.invui.gui.impl.*; import de.studiocode.invui.item.Item; +import de.studiocode.invui.item.impl.SimpleItem; +import de.studiocode.invui.item.itembuilder.ItemBuilder; import org.bukkit.inventory.ShapedRecipe; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Map; + +import static de.studiocode.invui.gui.builder.GUIType.*; /** * A builder class to easily construct {@link GUI}s.
@@ -19,151 +23,138 @@ import java.util.Map; */ public class GUIBuilder { - protected final int width; - protected final int height; - private final int size; - - private final Map ingredientMap = new HashMap<>(); + private final GUIType guiType; + private final int width; + private final int height; + private final HashMap ingredientMap = new HashMap<>(); private String structure; - public GUIBuilder(int width, int height) { + private List items = new ArrayList<>(); + private List guis = new ArrayList<>(); + + public GUIBuilder(@NotNull GUIType guiType, int width, int height) { + this.guiType = guiType; this.width = width; this.height = height; - this.size = width * height; } - /** - * Builds the {@link GUI}. - * - * @return The built {@link GUI} - */ + public GUIBuilder setStructure(@NotNull String structure) { + String trimmedStructure = structure + .replace(" ", "") + .replace("\n", ""); + + if (trimmedStructure.length() != width * height) + throw new IllegalArgumentException("Structure size does not match GUI size"); + + this.structure = trimmedStructure; + return this; + } + + public GUIBuilder setIngredient(char key, @NotNull ItemBuilder itemBuilder) { + return setIngredient(key, new SimpleItem(itemBuilder)); + } + + public GUIBuilder setIngredient(char key, @NotNull Item item) { + return setIngredient(key, new ItemSlotElement(item)); + } + + public GUIBuilder setIngredient(char key, @NotNull SlotElement element) { + ingredientMap.put(key, new Ingredient(element)); + return this; + } + + public GUIBuilder setMarker(char key, @NotNull Marker marker) { + ingredientMap.put(key, new Ingredient(marker)); + return this; + } + + public GUIBuilder setItems(@NotNull List items) { + if (guiType != PAGED_ITEMS && guiType != SCROLL) + throw new UnsupportedOperationException("Items cannot be set in this gui type."); + this.items = items; + return this; + } + + public GUIBuilder addItem(@NotNull Item item) { + if (guiType != PAGED_ITEMS && guiType != SCROLL) + throw new UnsupportedOperationException("Items cannot be set in this gui type."); + items.add(item); + return this; + } + + public GUIBuilder setGUIs(@NotNull List guis) { + if (guiType != PAGED_GUIs) + throw new UnsupportedOperationException("GUIs cannot be set in this gui type."); + this.guis = guis; + return this; + } + + public GUIBuilder addGUI(@NotNull GUI gui) { + if (guiType != PAGED_GUIs) + throw new UnsupportedOperationException("GUIs cannot be set in this gui type."); + guis.add(gui); + return this; + } + public GUI build() { + IngredientList ingredients = new IngredientList(structure, ingredientMap); + + switch (guiType) { + + case NORMAL: + return buildSimpleGUI(ingredients); + + case PAGED_ITEMS: + return buildSimplePagedItemsGUI(ingredients); + + case PAGED_GUIs: + return buildSimplePagedGUIsGUI(ingredients); + + case TAB: + return buildSimpleTabGUI(ingredients); + + case SCROLL: + return buildSimpleScrollGUI(ingredients); + + default: + throw new UnsupportedOperationException("Unknown GUI type"); + } + } + + private SimpleGUI buildSimpleGUI(IngredientList ingredients) { SimpleGUI gui = new SimpleGUI(width, height); - setSlotElements(gui); + ingredients.insertIntoGUI(gui); + return gui; } - /** - * Sets the structure of the {@link GUI}. - * The structure is a {@link String} of characters, like used in {@link ShapedRecipe} to - * define where which {@link Item} should be. - * - * @param structure The structure {@link String} - * @return The {@link GUIBuilder} - */ - public GUIBuilder setStructure(@NotNull String structure) { - String cleanedStructure = structure.replace(" ", "").replace("\n", ""); - if (cleanedStructure.length() != size) - throw new IllegalArgumentException("Structure length does not match size"); - this.structure = cleanedStructure; + private SimplePagedItemsGUI buildSimplePagedItemsGUI(IngredientList ingredients) { + SimplePagedItemsGUI gui = new SimplePagedItemsGUI(width, height, items, ingredients.findIndicesOfMarkerAsArray(Marker.ITEM_LIST_SLOT)); + ingredients.insertIntoGUI(gui); - return this; + return gui; } - /** - * Sets an ingredient for the structure String, which will later be - * used to set up the inventory correctly. - * - * @param key The ingredient key - * @param item The {@link Item} - * @return The {@link GUIBuilder} - */ - public GUIBuilder setIngredient(char key, @NotNull Item item) { - ingredientMap.put(key, new Ingredient(item)); - return this; + private SimplePagedGUIsGUI buildSimplePagedGUIsGUI(IngredientList ingredients) { + SimplePagedGUIsGUI gui = new SimplePagedGUIsGUI(width, height, guis, ingredients.findIndicesOfMarkerAsArray(Marker.ITEM_LIST_SLOT)); + ingredients.insertIntoGUI(gui); + + return gui; } - /** - * Sets an ingredient for the structure String, which will later be - * used to set up the inventory correctly. - * - * @param key The ingredient key - * @param slotElement The {@link SlotElement} - * @return The {@link GUIBuilder} - */ - public GUIBuilder setIngredient(char key, @NotNull SlotElement slotElement) { - ingredientMap.put(key, new Ingredient(slotElement)); - return this; + private SimpleTabGUI buildSimpleTabGUI(IngredientList ingredients) { + SimpleTabGUI gui = new SimpleTabGUI(width, height, guis, ingredients.findIndicesOfMarkerAsArray(Marker.ITEM_LIST_SLOT)); + ingredients.insertIntoGUI(gui); + + return gui; } - protected void setIngredient(char key, int special) { - ingredientMap.put(key, new Ingredient(special)); - } - - private Ingredient[] parseStructure() { - if (structure == null) throw new IllegalStateException("Structure has not been set yet."); - - Ingredient[] ingredients = new Ingredient[size]; - int i = 0; - for (char c : structure.toCharArray()) { - if (c != '.') ingredients[i] = this.ingredientMap.get(c); - i++; - } - - return ingredients; - } - - protected void setSlotElements(GUI gui) { - Ingredient[] ingredients = parseStructure(); - for (int i = 0; i < gui.getSize(); i++) { - Ingredient ingredient = ingredients[i]; - if (ingredient != null && ingredient.isSlotElement()) - gui.setSlotElement(i, ingredient.getSlotElement()); - } - } - - protected int[] findIndicesOf(int special) { - List indices = new ArrayList<>(); - - Ingredient[] ingredients = parseStructure(); - for (int i = 0; i < size; i++) { - Ingredient ingredient = ingredients[i]; - if (ingredient != null && ingredient.isSpecial() && ingredient.getSpecial() == special) - indices.add(i); - } - - return indices.stream().mapToInt(Integer::intValue).toArray(); - } - - static class Ingredient { - - private final SlotElement slotElement; - private final int special; - - public Ingredient(Item item) { - this.slotElement = new SlotElement.ItemSlotElement(item); - this.special = -1; - } - - public Ingredient(SlotElement slotElement) { - this.slotElement = slotElement; - this.special = -1; - } - - public Ingredient(int special) { - this.special = special; - this.slotElement = null; - } - - public SlotElement getSlotElement() { - if (isSpecial()) throw new IllegalStateException("Ingredient is special"); - return slotElement; - } - - public int getSpecial() { - if (isSlotElement()) throw new IllegalStateException("Ingredient is item"); - return special; - } - - public boolean isSlotElement() { - return slotElement != null; - } - - public boolean isSpecial() { - return slotElement == null; - } + private SimpleScrollGUI buildSimpleScrollGUI(IngredientList ingredients) { + SimpleScrollGUI gui = new SimpleScrollGUI(width, height, items, ingredients.findIndicesOfMarkerAsArray(Marker.ITEM_LIST_SLOT)); + ingredients.insertIntoGUI(gui); + return gui; } } diff --git a/src/main/java/de/studiocode/invui/gui/builder/GUIType.java b/src/main/java/de/studiocode/invui/gui/builder/GUIType.java new file mode 100644 index 0000000..143b211 --- /dev/null +++ b/src/main/java/de/studiocode/invui/gui/builder/GUIType.java @@ -0,0 +1,11 @@ +package de.studiocode.invui.gui.builder; + +public enum GUIType { + + NORMAL, + PAGED_ITEMS, + PAGED_GUIs, + TAB, + SCROLL + +} diff --git a/src/main/java/de/studiocode/invui/gui/builder/Ingredient.java b/src/main/java/de/studiocode/invui/gui/builder/Ingredient.java new file mode 100644 index 0000000..e2f06e2 --- /dev/null +++ b/src/main/java/de/studiocode/invui/gui/builder/Ingredient.java @@ -0,0 +1,57 @@ +package de.studiocode.invui.gui.builder; + +import de.studiocode.invui.gui.GUI; +import de.studiocode.invui.gui.SlotElement; +import de.studiocode.invui.item.itembuilder.ItemBuilder; + +import java.util.function.Function; + +class Ingredient { + + private final SlotElement slotElement; + private final Marker marker; + private final Function builderFunction; + + public Ingredient(SlotElement slotElement) { + this.slotElement = slotElement; + this.builderFunction = null; + this.marker = null; + } + + public Ingredient(Marker marker) { + this.marker = marker; + this.slotElement = null; + this.builderFunction = null; + } + + public Ingredient(Function builderFunction) { + this.builderFunction = builderFunction; + this.slotElement = null; + this.marker = null; + } + + public SlotElement getSlotElement() { + return slotElement; + } + + public Marker getMarker() { + return marker; + } + + public Function getBuilderFunction() { + return builderFunction; + } + + public boolean isSlotElement() { + return slotElement != null; + } + + public boolean isMarker() { + return marker != null; + } + + public boolean isBuilderFunction() { + return builderFunction != null; + } + +} \ No newline at end of file diff --git a/src/main/java/de/studiocode/invui/gui/builder/IngredientList.java b/src/main/java/de/studiocode/invui/gui/builder/IngredientList.java new file mode 100644 index 0000000..86d79ce --- /dev/null +++ b/src/main/java/de/studiocode/invui/gui/builder/IngredientList.java @@ -0,0 +1,58 @@ +package de.studiocode.invui.gui.builder; + +import de.studiocode.invui.gui.Controllable; +import de.studiocode.invui.gui.GUI; +import de.studiocode.invui.gui.SlotElement; +import de.studiocode.invui.gui.SlotElement.ItemSlotElement; +import de.studiocode.invui.item.Item; +import de.studiocode.invui.item.impl.controlitem.ControlItem; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +class IngredientList extends ArrayList { + + public IngredientList(String structure, HashMap ingredientMap) { + for (char c : structure.toCharArray()) { + Ingredient ingredient = null; + if (ingredientMap.containsKey(c)) ingredient = ingredientMap.get(c); + add(ingredient); + } + } + + public void insertIntoGUI(GUI gui) { + for (int i = 0; i < size(); i++) { + Ingredient ingredient = get(i); + if (ingredient != null && ingredient.isSlotElement()) { + SlotElement slotElement = ingredient.getSlotElement(); + + if (gui instanceof Controllable && slotElement instanceof ItemSlotElement) { + Item item = ((ItemSlotElement) slotElement).getItem(); + if (item instanceof ControlItem) { + ((Controllable) gui).addControlItem(i, (ControlItem) item); + continue; + } + } + + gui.setSlotElement(i, ingredient.getSlotElement()); + } + } + } + + public List findIndicesOfMarker(Marker marker) { + List indices = new ArrayList<>(); + for (int i = 0; i < size(); i++) { + Ingredient ingredient = get(i); + if (ingredient != null && ingredient.isMarker() && ingredient.getMarker() == marker) + indices.add(i); + } + + return indices; + } + + public int[] findIndicesOfMarkerAsArray(Marker marker) { + return findIndicesOfMarker(marker).stream().mapToInt(Integer::intValue).toArray(); + } + +} diff --git a/src/main/java/de/studiocode/invui/gui/builder/Marker.java b/src/main/java/de/studiocode/invui/gui/builder/Marker.java new file mode 100644 index 0000000..162bfc7 --- /dev/null +++ b/src/main/java/de/studiocode/invui/gui/builder/Marker.java @@ -0,0 +1,7 @@ +package de.studiocode.invui.gui.builder; + +public enum Marker { + + ITEM_LIST_SLOT + +} diff --git a/src/main/java/de/studiocode/invui/gui/builder/PagedGUIBuilder.java b/src/main/java/de/studiocode/invui/gui/builder/PagedGUIBuilder.java deleted file mode 100644 index 5b81a56..0000000 --- a/src/main/java/de/studiocode/invui/gui/builder/PagedGUIBuilder.java +++ /dev/null @@ -1,119 +0,0 @@ -package de.studiocode.invui.gui.builder; - -import de.studiocode.invui.gui.GUI; -import de.studiocode.invui.gui.SlotElement; -import de.studiocode.invui.gui.impl.PagedGUI; -import de.studiocode.invui.gui.impl.SimplePagedGUIsGUI; -import de.studiocode.invui.gui.impl.SimplePagedItemsGUI; -import de.studiocode.invui.item.Item; -import de.studiocode.invui.item.itembuilder.ItemBuilder; -import org.jetbrains.annotations.NotNull; - -import java.util.List; -import java.util.function.Function; - -public class PagedGUIBuilder extends GUIBuilder { - - private final ContentType contentType; - - private Function backFunction; - private Function forwardFunction; - private int[] listSlots; - private List content; - - public PagedGUIBuilder(ContentType contentType, int width, int height) { - super(width, height); - this.contentType = contentType; - } - - @SuppressWarnings("unchecked") - @Override - public PagedGUI build() { - int[] listSlots = this.listSlots != null ? this.listSlots : findIndicesOf(2); - int[] backSlots = findIndicesOf(0); - int[] forwardSlots = findIndicesOf(1); - - if (listSlots.length == 0) throw new IllegalStateException("No list slots have been set."); - if (backSlots.length == 0) throw new IllegalStateException("Not back slot has been set."); - if (forwardSlots.length == 0) throw new IllegalStateException("No forward slot has been set."); - if (content == null) throw new IllegalStateException("Content has not been set."); - if (forwardFunction == null) throw new IllegalStateException("Forward function has not been set."); - if (backFunction == null) throw new IllegalStateException("Back function has not been set"); - - int backSlot = backSlots[0]; - int forwardSlot = forwardSlots[0]; - - PagedGUI gui; - if (contentType == ContentType.GUI) { - gui = new SimplePagedGUIsGUI(width, height, backSlot, backFunction, - forwardSlot, forwardFunction, (List) content, listSlots); - } else { - gui = new SimplePagedItemsGUI(width, height, backSlot, backFunction, - forwardSlot, forwardFunction, (List) content, listSlots); - } - - setSlotElements(gui); - return gui; - } - - public PagedGUIBuilder setGUIs(List guis) { - if (contentType != ContentType.GUI) - throw new IllegalStateException("Can't set guis if ContentType is not GUI"); - content = guis; - - return this; - } - - public PagedGUIBuilder setItems(List items) { - if (contentType != ContentType.SINGLE_ITEMS) - throw new IllegalStateException("Can't set items if ContentType is not SINGLE_ITEMS"); - content = items; - - return this; - } - - public PagedGUIBuilder setListSlots(int[] listSlots) { - this.listSlots = listSlots; - return this; - } - - public PagedGUIBuilder setListSlotIngredient(char key) { - setIngredient(key, 2); - return this; - } - - public PagedGUIBuilder setBackItem(char key, Function backFunction) { - setIngredient(key, 0); - this.backFunction = backFunction; - return this; - } - - public PagedGUIBuilder setForwardItem(char key, Function forwardFunction) { - setIngredient(key, 1); - this.forwardFunction = forwardFunction; - return this; - } - - @Override - public PagedGUIBuilder setStructure(@NotNull String structure) { - return (PagedGUIBuilder) super.setStructure(structure); - } - - @Override - public PagedGUIBuilder setIngredient(char key, @NotNull Item item) { - return (PagedGUIBuilder) super.setIngredient(key, item); - } - - @Override - public PagedGUIBuilder setIngredient(char key, @NotNull SlotElement slotElement) { - return (PagedGUIBuilder) super.setIngredient(key, slotElement); - } - - public enum ContentType { - - SINGLE_ITEMS, - GUI - - } - -} diff --git a/src/main/java/de/studiocode/invui/gui/builder/TabGUIBuilder.java b/src/main/java/de/studiocode/invui/gui/builder/TabGUIBuilder.java deleted file mode 100644 index 1257a9d..0000000 --- a/src/main/java/de/studiocode/invui/gui/builder/TabGUIBuilder.java +++ /dev/null @@ -1,80 +0,0 @@ -package de.studiocode.invui.gui.builder; - -import de.studiocode.invui.gui.GUI; -import de.studiocode.invui.gui.SlotElement; -import de.studiocode.invui.gui.impl.SimpleTabGUI; -import de.studiocode.invui.gui.impl.TabGUI; -import de.studiocode.invui.item.Item; -import de.studiocode.invui.item.itembuilder.ItemBuilder; -import org.jetbrains.annotations.NotNull; - -import java.util.LinkedHashMap; -import java.util.function.Function; - -public class TabGUIBuilder extends GUIBuilder { - - private final LinkedHashMap> tabs = new LinkedHashMap<>(); - - private int[] listSlots; - private int[] tabItemSlots; - - public TabGUIBuilder(int width, int height) { - super(width, height); - } - - @Override - public TabGUI build() { - int[] listSlots = this.listSlots != null ? this.listSlots : findIndicesOf(0); - int[] tabItemSlots = this.tabItemSlots != null ? this.tabItemSlots : findIndicesOf(1); - - if (listSlots.length == 0) throw new IllegalStateException("No list slots have been set."); - if (tabItemSlots.length != tabs.size()) - throw new IllegalStateException("TabItemSlots length has to be the same as tabs size"); - - SimpleTabGUI tabGUI = new SimpleTabGUI(width, height, tabs, listSlots, tabItemSlots); - setSlotElements(tabGUI); - - return tabGUI; - } - - public TabGUIBuilder addTab(GUI gui, Function builderFunction) { - tabs.put(gui, builderFunction); - return this; - } - - public TabGUIBuilder setListSlotIngredient(char key) { - setIngredient(key, 0); - return this; - } - - public TabGUIBuilder setTabSlotIngredient(char key) { - setIngredient(key, 1); - return this; - } - - public TabGUIBuilder setListSlots(int[] listSlots) { - this.listSlots = listSlots; - return this; - } - - public TabGUIBuilder setTabItemSlots(int[] tabItemSlots) { - this.tabItemSlots = tabItemSlots; - return this; - } - - @Override - public TabGUIBuilder setStructure(@NotNull String structure) { - return (TabGUIBuilder) super.setStructure(structure); - } - - @Override - public TabGUIBuilder setIngredient(char key, @NotNull Item item) { - return (TabGUIBuilder) super.setIngredient(key, item); - } - - @Override - public TabGUIBuilder setIngredient(char key, @NotNull SlotElement slotElement) { - return (TabGUIBuilder) super.setIngredient(key, slotElement); - } - -} diff --git a/src/main/java/de/studiocode/invui/gui/impl/PagedGUI.java b/src/main/java/de/studiocode/invui/gui/impl/PagedGUI.java index e8cd13d..aa592a4 100644 --- a/src/main/java/de/studiocode/invui/gui/impl/PagedGUI.java +++ b/src/main/java/de/studiocode/invui/gui/impl/PagedGUI.java @@ -1,28 +1,29 @@ package de.studiocode.invui.gui.impl; +import de.studiocode.invui.gui.Controllable; import de.studiocode.invui.gui.GUI; import de.studiocode.invui.gui.SlotElement; -import de.studiocode.invui.gui.builder.PagedGUIBuilder; +import de.studiocode.invui.gui.builder.GUIBuilder; import de.studiocode.invui.item.Item; -import de.studiocode.invui.item.impl.pagedgui.BackItem; -import de.studiocode.invui.item.impl.pagedgui.ForwardItem; +import de.studiocode.invui.item.impl.controlitem.ControlItem; +import de.studiocode.invui.item.impl.controlitem.PageItem; +import java.util.ArrayList; import java.util.List; /** * A {@link GUI} with pages. * - * @see PagedGUIBuilder + * @see GUIBuilder * @see SimplePagedItemsGUI * @see SimplePagedGUIsGUI */ -public abstract class PagedGUI extends BaseGUI { +public abstract class PagedGUI extends BaseGUI implements Controllable { + private final List controlItems = new ArrayList<>(); private final boolean infinitePages; private final int[] itemListSlots; protected int currentPage; - private Item forwardItem; - private Item backItem; public PagedGUI(int width, int height, boolean infinitePages, int... itemListSlots) { super(width, height); @@ -30,9 +31,14 @@ public abstract class PagedGUI extends BaseGUI { this.itemListSlots = itemListSlots; } - public void setControlItems(int backItemSlot, BackItem backItem, int forwardItemSlot, ForwardItem forwardItem) { - setItem(backItemSlot, this.backItem = backItem); - setItem(forwardItemSlot, this.forwardItem = forwardItem); + @Override + public void addControlItem(int index, ControlItem controlItem) { + if (!(controlItem instanceof PageItem)) + throw new IllegalArgumentException("controlItem is not an instance of PageItem"); + + ((PageItem) controlItem).setGui(this); + setItem(index, controlItem); + controlItems.add(controlItem); } public void goForward() { @@ -72,8 +78,7 @@ public abstract class PagedGUI extends BaseGUI { } private void updateControlItems() { - backItem.notifyWindows(); - forwardItem.notifyWindows(); + controlItems.forEach(Item::notifyWindows); } private void updatePageContent() { @@ -89,14 +94,6 @@ public abstract class PagedGUI extends BaseGUI { return currentPage; } - public Item getForwardItem() { - return forwardItem; - } - - public Item getBackItem() { - return backItem; - } - public boolean hasInfinitePages() { return infinitePages; } diff --git a/src/main/java/de/studiocode/invui/gui/impl/ScrollGUI.java b/src/main/java/de/studiocode/invui/gui/impl/ScrollGUI.java index 2782ed4..9710b94 100644 --- a/src/main/java/de/studiocode/invui/gui/impl/ScrollGUI.java +++ b/src/main/java/de/studiocode/invui/gui/impl/ScrollGUI.java @@ -1,8 +1,12 @@ package de.studiocode.invui.gui.impl; +import de.studiocode.invui.gui.Controllable; import de.studiocode.invui.gui.GUI; import de.studiocode.invui.gui.SlotElement; import de.studiocode.invui.item.Item; +import de.studiocode.invui.item.impl.controlitem.ControlItem; +import de.studiocode.invui.item.impl.controlitem.ScrollItem; +import de.studiocode.invui.util.SlotUtils; import java.util.ArrayList; import java.util.List; @@ -12,7 +16,7 @@ import java.util.List; * * @see SimpleScrollGUI */ -public abstract class ScrollGUI extends BaseGUI { +public abstract class ScrollGUI extends BaseGUI implements Controllable { private final List controlItems = new ArrayList<>(); private final boolean infiniteLines; @@ -21,12 +25,11 @@ public abstract class ScrollGUI extends BaseGUI { protected int offset; - - public ScrollGUI(int width, int height, boolean infiniteLines, int lineLength, int... itemListSlots) { + public ScrollGUI(int width, int height, boolean infiniteLines, int... itemListSlots) { super(width, height); this.infiniteLines = infiniteLines; this.itemListSlots = itemListSlots; - this.lineLength = lineLength; + this.lineLength = SlotUtils.getLongestLineLength(itemListSlots, width); if (lineLength == 0) throw new IllegalArgumentException("Line length can't be 0"); @@ -36,9 +39,14 @@ public abstract class ScrollGUI extends BaseGUI { throw new IllegalArgumentException("itemListSlots has to be a multiple of lineLength"); } - public void addControlItem(int index, Item item) { - controlItems.add(item); - setItem(index, item); + @Override + public void addControlItem(int index, ControlItem controlItem) { + if (!(controlItem instanceof ScrollItem)) + throw new IllegalArgumentException("controlItem is not an instance of ScrollItem"); + + ((ScrollItem) controlItem).setGui(this); + setItem(index, controlItem); + controlItems.add(controlItem); } public void setCurrentLine(int line) { diff --git a/src/main/java/de/studiocode/invui/gui/impl/SimplePagedGUIsGUI.java b/src/main/java/de/studiocode/invui/gui/impl/SimplePagedGUIsGUI.java index 59d3d9e..dbfee62 100644 --- a/src/main/java/de/studiocode/invui/gui/impl/SimplePagedGUIsGUI.java +++ b/src/main/java/de/studiocode/invui/gui/impl/SimplePagedGUIsGUI.java @@ -2,36 +2,30 @@ package de.studiocode.invui.gui.impl; import de.studiocode.invui.gui.GUI; import de.studiocode.invui.gui.SlotElement; -import de.studiocode.invui.gui.builder.PagedGUIBuilder; -import de.studiocode.invui.item.impl.pagedgui.BackItem; -import de.studiocode.invui.item.impl.pagedgui.ForwardItem; -import de.studiocode.invui.item.itembuilder.ItemBuilder; +import de.studiocode.invui.gui.builder.GUIBuilder; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.function.Function; /** * A {@link PagedGUI} where every page is it's own {@link GUI}. * - * @see PagedGUIBuilder + * @see GUIBuilder * @see SimplePagedItemsGUI */ public class SimplePagedGUIsGUI extends PagedGUI { private List guis; - public SimplePagedGUIsGUI(int width, int height, - int backItemSlot, Function backFunction, - int forwardItemSlot, Function forwardFunction, - List guis, int... itemListSlots) { - + public SimplePagedGUIsGUI(int width, int height, int... itemListSlots) { + this(width, height, new ArrayList<>(), itemListSlots); + } + + public SimplePagedGUIsGUI(int width, int height, List guis, int... itemListSlots) { super(width, height, false, itemListSlots); this.guis = guis; - setControlItems(backItemSlot, new BackItem(this, backFunction), - forwardItemSlot, new ForwardItem(this, forwardFunction)); - update(); } diff --git a/src/main/java/de/studiocode/invui/gui/impl/SimplePagedItemsGUI.java b/src/main/java/de/studiocode/invui/gui/impl/SimplePagedItemsGUI.java index 1d2e050..90a823f 100644 --- a/src/main/java/de/studiocode/invui/gui/impl/SimplePagedItemsGUI.java +++ b/src/main/java/de/studiocode/invui/gui/impl/SimplePagedItemsGUI.java @@ -2,36 +2,31 @@ package de.studiocode.invui.gui.impl; import de.studiocode.invui.gui.SlotElement; import de.studiocode.invui.gui.SlotElement.ItemSlotElement; -import de.studiocode.invui.gui.builder.PagedGUIBuilder; +import de.studiocode.invui.gui.builder.GUIBuilder; import de.studiocode.invui.item.Item; -import de.studiocode.invui.item.impl.pagedgui.BackItem; -import de.studiocode.invui.item.impl.pagedgui.ForwardItem; -import de.studiocode.invui.item.itembuilder.ItemBuilder; +import java.util.ArrayList; import java.util.List; -import java.util.function.Function; import java.util.stream.Collectors; /** * A {@link PagedGUI} that is filled with {@link Item}s. * - * @see PagedGUIBuilder + * @see GUIBuilder * @see SimplePagedGUIsGUI */ public class SimplePagedItemsGUI extends PagedGUI { private List items; - public SimplePagedItemsGUI(int width, int height, - int backItemSlot, Function backFunction, - int forwardItemSlot, Function forwardFunction, - List items, int... itemListSlots) { - + public SimplePagedItemsGUI(int width, int height, int... itemListSlots) { + this(width, height, new ArrayList<>(), itemListSlots); + } + + public SimplePagedItemsGUI(int width, int height, List items, int... itemListSlots) { super(width, height, false, itemListSlots); this.items = items; - setControlItems(backItemSlot, new BackItem(this, backFunction), - forwardItemSlot, new ForwardItem(this, forwardFunction)); update(); } @@ -53,4 +48,5 @@ public class SimplePagedItemsGUI extends PagedGUI { this.items = items; update(); } + } diff --git a/src/main/java/de/studiocode/invui/gui/impl/SimpleScrollGUI.java b/src/main/java/de/studiocode/invui/gui/impl/SimpleScrollGUI.java index f0a976c..bc931a2 100644 --- a/src/main/java/de/studiocode/invui/gui/impl/SimpleScrollGUI.java +++ b/src/main/java/de/studiocode/invui/gui/impl/SimpleScrollGUI.java @@ -10,8 +10,8 @@ public class SimpleScrollGUI extends ScrollGUI { private List items; - public SimpleScrollGUI(int width, int height, List items, int lineLength, int... itemListSlots) { - super(width, height, false, lineLength, itemListSlots); + public SimpleScrollGUI(int width, int height, List items, int... itemListSlots) { + super(width, height, false, itemListSlots); this.items = items; update(); diff --git a/src/main/java/de/studiocode/invui/gui/impl/SimpleTabGUI.java b/src/main/java/de/studiocode/invui/gui/impl/SimpleTabGUI.java index 428c350..4a02f96 100644 --- a/src/main/java/de/studiocode/invui/gui/impl/SimpleTabGUI.java +++ b/src/main/java/de/studiocode/invui/gui/impl/SimpleTabGUI.java @@ -2,36 +2,23 @@ package de.studiocode.invui.gui.impl; import de.studiocode.invui.gui.GUI; import de.studiocode.invui.gui.SlotElement; -import de.studiocode.invui.gui.builder.TabGUIBuilder; -import de.studiocode.invui.item.impl.tabgui.TabItem; -import de.studiocode.invui.item.itembuilder.ItemBuilder; +import de.studiocode.invui.gui.builder.GUIBuilder; -import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedHashMap; import java.util.List; -import java.util.function.Function; /** * A {@link GUI} that has multiple tabs with which users can switch between {@link GUI}s. * - * @see TabGUIBuilder + * @see GUIBuilder */ public class SimpleTabGUI extends TabGUI { private final List tabs; - public SimpleTabGUI(int width, int height, LinkedHashMap> tabs, - int[] listSlots, int[] tabItemSlots) { - + public SimpleTabGUI(int width, int height, List tabs, int[] listSlots) { super(width, height, tabs.size(), listSlots); - this.tabs = new ArrayList<>(tabs.keySet()); - - List> builderFunctions = new ArrayList<>(tabs.values()); - for (int i = 0; i < tabs.size(); i++) { - TabItem tabItem = new TabItem(this, i, builderFunctions.get(i)); - setTabItem(i, tabItemSlots[i], tabItem); - } + this.tabs = tabs; update(); } diff --git a/src/main/java/de/studiocode/invui/gui/impl/TabGUI.java b/src/main/java/de/studiocode/invui/gui/impl/TabGUI.java index af6cac8..ffbd612 100644 --- a/src/main/java/de/studiocode/invui/gui/impl/TabGUI.java +++ b/src/main/java/de/studiocode/invui/gui/impl/TabGUI.java @@ -1,17 +1,19 @@ package de.studiocode.invui.gui.impl; +import de.studiocode.invui.gui.Controllable; import de.studiocode.invui.gui.SlotElement; import de.studiocode.invui.item.Item; -import de.studiocode.invui.item.impl.tabgui.TabItem; +import de.studiocode.invui.item.impl.controlitem.ControlItem; +import de.studiocode.invui.item.impl.controlitem.TabItem; -import java.util.Arrays; +import java.util.ArrayList; import java.util.List; -public abstract class TabGUI extends BaseGUI { +public abstract class TabGUI extends BaseGUI implements Controllable { + private final List controlItems = new ArrayList<>(); private final int tabAmount; private final int[] listSlots; - private final Item[] tabItems; private int currentTab; @@ -19,7 +21,6 @@ public abstract class TabGUI extends BaseGUI { super(width, height); this.tabAmount = tabAmount; this.listSlots = listSlots; - this.tabItems = new Item[tabAmount]; } public void showTab(int tab) { @@ -30,14 +31,26 @@ public abstract class TabGUI extends BaseGUI { update(); } - public void setTabItem(int tab, int index, TabItem tabItem) { - tabItems[tab] = tabItem; - setItem(index, tabItem); + @Override + public void addControlItem(int index, ControlItem controlItem) { + if (!(controlItem instanceof TabItem)) + throw new IllegalArgumentException("controlItem is not an instance of TabItem"); + + ((TabItem) controlItem).setGui(this); + setItem(index, controlItem); + controlItems.add(controlItem); } protected void update() { - Arrays.stream(tabItems).forEach(Item::notifyWindows); - + updateControlItems(); + updateContent(); + } + + private void updateControlItems() { + controlItems.forEach(Item::notifyWindows); + } + + private void updateContent() { List slotElements = getSlotElements(currentTab); for (int i = 0; i < listSlots.length; i++) { int slot = listSlots[i]; diff --git a/src/main/java/de/studiocode/invui/item/impl/FunctionItem.java b/src/main/java/de/studiocode/invui/item/impl/FunctionItem.java deleted file mode 100644 index a108cb1..0000000 --- a/src/main/java/de/studiocode/invui/item/impl/FunctionItem.java +++ /dev/null @@ -1,34 +0,0 @@ -package de.studiocode.invui.item.impl; - -import de.studiocode.invui.item.itembuilder.ItemBuilder; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.event.inventory.InventoryClickEvent; - -import java.util.function.Function; - -public class FunctionItem extends BaseItem { - - private final T t; - private final Function builderFunction; - - public FunctionItem(T t, Function builderFunction) { - this.t = t; - this.builderFunction = builderFunction; - } - - @Override - public ItemBuilder getItemBuilder() { - return builderFunction.apply(t); - } - - public T getT() { - return t; - } - - @Override - public void handleClick(ClickType clickType, Player player, InventoryClickEvent event) { - // empty - } - -} diff --git a/src/main/java/de/studiocode/invui/item/impl/controlitem/ControlItem.java b/src/main/java/de/studiocode/invui/item/impl/controlitem/ControlItem.java new file mode 100644 index 0000000..9b8ccad --- /dev/null +++ b/src/main/java/de/studiocode/invui/item/impl/controlitem/ControlItem.java @@ -0,0 +1,31 @@ +package de.studiocode.invui.item.impl.controlitem; + +import de.studiocode.invui.gui.GUI; +import de.studiocode.invui.item.impl.BaseItem; +import de.studiocode.invui.item.itembuilder.ItemBuilder; + +import java.util.function.Function; + +public abstract class ControlItem extends BaseItem { + + private G gui; + private final Function builderFunction; + + public ControlItem(Function builderFunction) { + this.builderFunction = builderFunction; + } + + @Override + public ItemBuilder getItemBuilder() { + return builderFunction.apply(gui); + } + + public G getGui() { + return gui; + } + + public void setGui(G gui) { + this.gui = gui; + } + +} diff --git a/src/main/java/de/studiocode/invui/item/impl/controlitem/PageItem.java b/src/main/java/de/studiocode/invui/item/impl/controlitem/PageItem.java new file mode 100644 index 0000000..a97beb6 --- /dev/null +++ b/src/main/java/de/studiocode/invui/item/impl/controlitem/PageItem.java @@ -0,0 +1,31 @@ +package de.studiocode.invui.item.impl.controlitem; + +import de.studiocode.invui.gui.impl.PagedGUI; +import de.studiocode.invui.item.itembuilder.ItemBuilder; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; + +import java.util.function.Function; + +/** + * Switches between pages in a {@link PagedGUI} + */ +public class PageItem extends ControlItem { + + private final boolean forward; + + public PageItem(boolean forward, Function builderFunction) { + super(builderFunction); + this.forward = forward; + } + + @Override + public void handleClick(ClickType clickType, Player player, InventoryClickEvent event) { + if (clickType == ClickType.LEFT) { + if (forward) getGui().goForward(); + else getGui().goBack(); + } + } + +} diff --git a/src/main/java/de/studiocode/invui/item/impl/scrollgui/ScrollItem.java b/src/main/java/de/studiocode/invui/item/impl/controlitem/ScrollItem.java similarity index 51% rename from src/main/java/de/studiocode/invui/item/impl/scrollgui/ScrollItem.java rename to src/main/java/de/studiocode/invui/item/impl/controlitem/ScrollItem.java index 9b134a8..de5cb9e 100644 --- a/src/main/java/de/studiocode/invui/item/impl/scrollgui/ScrollItem.java +++ b/src/main/java/de/studiocode/invui/item/impl/controlitem/ScrollItem.java @@ -1,7 +1,6 @@ -package de.studiocode.invui.item.impl.scrollgui; +package de.studiocode.invui.item.impl.controlitem; import de.studiocode.invui.gui.impl.ScrollGUI; -import de.studiocode.invui.item.impl.FunctionItem; import de.studiocode.invui.item.itembuilder.ItemBuilder; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; @@ -10,25 +9,27 @@ import org.bukkit.event.inventory.InventoryClickEvent; import java.util.HashMap; import java.util.function.Function; -public class ScrollItem extends FunctionItem { +/** + * Scrolls in a {@link ScrollGUI} + */ +public class ScrollItem extends ControlItem { private final HashMap scroll; - public ScrollItem(ScrollGUI scrollGUI, int scrollLeftClick, Function builderFunction) { - super(scrollGUI, builderFunction); - + public ScrollItem(int scrollLeftClick, Function builderFunction) { + super(builderFunction); scroll = new HashMap<>(); scroll.put(ClickType.LEFT, scrollLeftClick); } - public ScrollItem(ScrollGUI scrollGUI, HashMap scroll, Function builderFunction) { - super(scrollGUI, builderFunction); + public ScrollItem(HashMap scroll, Function builderFunction) { + super(builderFunction); this.scroll = scroll; } @Override public void handleClick(ClickType clickType, Player player, InventoryClickEvent event) { - if (scroll.containsKey(clickType)) getT().scroll(scroll.get(clickType)); + if (scroll.containsKey(clickType)) getGui().scroll(scroll.get(clickType)); } } diff --git a/src/main/java/de/studiocode/invui/item/impl/tabgui/TabItem.java b/src/main/java/de/studiocode/invui/item/impl/controlitem/TabItem.java similarity index 57% rename from src/main/java/de/studiocode/invui/item/impl/tabgui/TabItem.java rename to src/main/java/de/studiocode/invui/item/impl/controlitem/TabItem.java index 1c0c3e5..07ade04 100644 --- a/src/main/java/de/studiocode/invui/item/impl/tabgui/TabItem.java +++ b/src/main/java/de/studiocode/invui/item/impl/controlitem/TabItem.java @@ -1,7 +1,6 @@ -package de.studiocode.invui.item.impl.tabgui; +package de.studiocode.invui.item.impl.controlitem; import de.studiocode.invui.gui.impl.TabGUI; -import de.studiocode.invui.item.impl.FunctionItem; import de.studiocode.invui.item.itembuilder.ItemBuilder; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; @@ -9,18 +8,21 @@ import org.bukkit.event.inventory.InventoryClickEvent; import java.util.function.Function; -public class TabItem extends FunctionItem { +/** + * Switches between tabs in a {@link TabGUI} + */ +public class TabItem extends ControlItem { private final int tab; - public TabItem(TabGUI tabGUI, int tab, Function builderFunction) { - super(tabGUI, builderFunction); + public TabItem(int tab, Function builderFunction) { + super(builderFunction); this.tab = tab; } @Override public void handleClick(ClickType clickType, Player player, InventoryClickEvent event) { - if (clickType == ClickType.LEFT) getT().showTab(tab); + if (clickType == ClickType.LEFT) getGui().showTab(tab); } } diff --git a/src/main/java/de/studiocode/invui/item/impl/pagedgui/BackItem.java b/src/main/java/de/studiocode/invui/item/impl/pagedgui/BackItem.java deleted file mode 100644 index 48c320e..0000000 --- a/src/main/java/de/studiocode/invui/item/impl/pagedgui/BackItem.java +++ /dev/null @@ -1,23 +0,0 @@ -package de.studiocode.invui.item.impl.pagedgui; - -import de.studiocode.invui.gui.impl.PagedGUI; -import de.studiocode.invui.item.impl.FunctionItem; -import de.studiocode.invui.item.itembuilder.ItemBuilder; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.event.inventory.InventoryClickEvent; - -import java.util.function.Function; - -public class BackItem extends FunctionItem { - - public BackItem(PagedGUI pagedGUI, Function builderFunction) { - super(pagedGUI, builderFunction); - } - - @Override - public void handleClick(ClickType clickType, Player player, InventoryClickEvent event) { - if (clickType == ClickType.LEFT) getT().goBack(); - } - -} diff --git a/src/main/java/de/studiocode/invui/item/impl/pagedgui/ForwardItem.java b/src/main/java/de/studiocode/invui/item/impl/pagedgui/ForwardItem.java deleted file mode 100644 index 18f24e7..0000000 --- a/src/main/java/de/studiocode/invui/item/impl/pagedgui/ForwardItem.java +++ /dev/null @@ -1,23 +0,0 @@ -package de.studiocode.invui.item.impl.pagedgui; - -import de.studiocode.invui.gui.impl.PagedGUI; -import de.studiocode.invui.item.impl.FunctionItem; -import de.studiocode.invui.item.itembuilder.ItemBuilder; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.event.inventory.InventoryClickEvent; - -import java.util.function.Function; - -public class ForwardItem extends FunctionItem { - - public ForwardItem(PagedGUI pagedGUI, Function builderFunction) { - super(pagedGUI, builderFunction); - } - - @Override - public void handleClick(ClickType clickType, Player player, InventoryClickEvent event) { - if (clickType == ClickType.LEFT) getT().goForward(); - } - -} diff --git a/src/main/java/de/studiocode/invui/util/SlotUtils.java b/src/main/java/de/studiocode/invui/util/SlotUtils.java index 059ce62..a3530ed 100644 --- a/src/main/java/de/studiocode/invui/util/SlotUtils.java +++ b/src/main/java/de/studiocode/invui/util/SlotUtils.java @@ -1,7 +1,9 @@ package de.studiocode.invui.util; +import java.util.Arrays; import java.util.LinkedHashSet; import java.util.Set; +import java.util.stream.Collectors; public class SlotUtils { @@ -75,6 +77,30 @@ public class SlotUtils { else return slot + 9; } + public static int getLongestLineLength(int[] slots, int frameWidth) { + int longestLength = 0; + int currentLength = 1; + Point2D previous = null; + + for (Point2D point : Arrays.stream(slots) + .mapToObj(index -> convertFromIndex(index, frameWidth)) + .collect(Collectors.toList())) { + if (previous != null) { + if (isNeighbor(previous, point)) currentLength++; + else currentLength = 1; + } + + previous = point; + longestLength = Math.max(longestLength, currentLength); + } + + return longestLength; + } + + public static boolean isNeighbor(Point2D point1, Point2D point2) { + return Math.abs(point1.getX() - point2.getX()) + Math.abs(point1.getY() - point2.getY()) == 1; + } + public enum Order { HORIZONTAL,