Improved GUIBuilder and Structure

- Structure now stores width and height
- Width and height are no longer part of the GUIBuilder constructor
- Width and height can be omitted by using the String[] Structure constructor
- Vertical item list slots
- Added GUIBuilder#setBackground
This commit is contained in:
NichtStudioCode 2022-04-23 20:37:15 +02:00
parent 11dab1eba7
commit 6a74920f75
24 changed files with 162 additions and 61 deletions

@ -3,6 +3,7 @@ package de.studiocode.invui.gui.builder;
import de.studiocode.invui.gui.GUI; import de.studiocode.invui.gui.GUI;
import de.studiocode.invui.gui.SlotElement; import de.studiocode.invui.gui.SlotElement;
import de.studiocode.invui.gui.builder.guitype.GUIType; import de.studiocode.invui.gui.builder.guitype.GUIType;
import de.studiocode.invui.gui.structure.Marker;
import de.studiocode.invui.gui.structure.Structure; import de.studiocode.invui.gui.structure.Structure;
import de.studiocode.invui.item.Item; import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemProvider; import de.studiocode.invui.item.ItemProvider;
@ -27,16 +28,20 @@ public class GUIBuilder<G extends GUI> {
private final GUIType<G> guiType; private final GUIType<G> guiType;
private final GUIContext context; private final GUIContext context;
public GUIBuilder(@NotNull GUIType<G> guiType, int width, int height) { public GUIBuilder(@NotNull GUIType<G> guiType) {
this.guiType = guiType; this.guiType = guiType;
this.context = new GUIContext(width, height); this.context = new GUIContext();
} }
public GUIBuilder<G> setStructure(@NotNull String structureData) { public GUIBuilder<G> setStructure(int width, int height, @NotNull String structureData) {
context.setStructure(new Structure(structureData)); context.setStructure(new Structure(width, height, structureData));
return this; return this;
} }
public GUIBuilder<G> setStructure(@NotNull String... structureData) {
return setStructure(new Structure(structureData));
}
public GUIBuilder<G> setStructure(@NotNull Structure structure) { public GUIBuilder<G> setStructure(@NotNull Structure structure) {
context.setStructure(structure); context.setStructure(structure);
return this; return this;
@ -72,7 +77,7 @@ public class GUIBuilder<G extends GUI> {
return this; return this;
} }
public GUIBuilder<G> addIngredient(char key, @NotNull String marker) { public GUIBuilder<G> addIngredient(char key, @NotNull Marker marker) {
context.getStructure().addIngredient(key, marker); context.getStructure().addIngredient(key, marker);
return this; return this;
} }
@ -124,6 +129,11 @@ public class GUIBuilder<G extends GUI> {
return this; return this;
} }
public GUIBuilder<G> setBackground(@Nullable ItemProvider background) {
context.setBackground(background);
return this;
}
public G build() { public G build() {
if (context.getStructure() == null) throw new IllegalStateException("GUIContext has not been set yet."); if (context.getStructure() == null) throw new IllegalStateException("GUIContext has not been set yet.");
return guiType.createGUI(context); return guiType.createGUI(context);

@ -4,6 +4,7 @@ import de.studiocode.invui.gui.GUI;
import de.studiocode.invui.gui.builder.guitype.GUIType; import de.studiocode.invui.gui.builder.guitype.GUIType;
import de.studiocode.invui.gui.structure.Structure; import de.studiocode.invui.gui.structure.Structure;
import de.studiocode.invui.item.Item; import de.studiocode.invui.item.Item;
import de.studiocode.invui.item.ItemProvider;
import de.studiocode.invui.virtualinventory.VirtualInventory; import de.studiocode.invui.virtualinventory.VirtualInventory;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -15,26 +16,12 @@ import java.util.List;
*/ */
public class GUIContext { public class GUIContext {
private final int width;
private final int height;
private Structure structure; private Structure structure;
private ItemProvider background;
private List<GUI> guis; private List<GUI> guis;
private List<Item> items; private List<Item> items;
private VirtualInventory inventory; private VirtualInventory inventory;
public GUIContext(int width, int height) {
this.width = width;
this.height = height;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Structure getStructure() { public Structure getStructure() {
return structure; return structure;
} }
@ -43,6 +30,14 @@ public class GUIContext {
this.structure = structure; this.structure = structure;
} }
public ItemProvider getBackground() {
return background;
}
public void setBackground(ItemProvider background) {
this.background = background;
}
public List<GUI> getGuis() { public List<GUI> getGuis() {
return guis; return guis;
} }

@ -7,7 +7,9 @@ class NormalGUIType implements GUIType<SimpleGUI> {
@Override @Override
public SimpleGUI createGUI(GUIContext context) { public SimpleGUI createGUI(GUIContext context) {
return new SimpleGUI(context.getWidth(), context.getHeight(), context.getStructure()); SimpleGUI gui = new SimpleGUI(context.getStructure());
gui.setBackground(context.getBackground());
return gui;
} }
@Override @Override

@ -7,7 +7,9 @@ class PagedGUIsGUIType implements GUIType<SimplePagedNestedGUI> {
@Override @Override
public SimplePagedNestedGUI createGUI(GUIContext context) { public SimplePagedNestedGUI createGUI(GUIContext context) {
return new SimplePagedNestedGUI(context.getWidth(), context.getHeight(), context.getGuis(), context.getStructure()); SimplePagedNestedGUI gui = new SimplePagedNestedGUI(context.getGuis(), context.getStructure());
gui.setBackground(context.getBackground());
return gui;
} }
@Override @Override

@ -7,7 +7,9 @@ class PagedItemsGUIType implements GUIType<SimplePagedItemsGUI> {
@Override @Override
public SimplePagedItemsGUI createGUI(GUIContext context) { public SimplePagedItemsGUI createGUI(GUIContext context) {
return new SimplePagedItemsGUI(context.getWidth(), context.getHeight(), context.getItems(), context.getStructure()); SimplePagedItemsGUI gui = new SimplePagedItemsGUI(context.getItems(), context.getStructure());
gui.setBackground(context.getBackground());
return gui;
} }
@Override @Override

@ -7,7 +7,9 @@ class ScrollGUIsGUIType implements GUIType<SimpleScrollNestedGUI> {
@Override @Override
public SimpleScrollNestedGUI createGUI(GUIContext context) { public SimpleScrollNestedGUI createGUI(GUIContext context) {
return new SimpleScrollNestedGUI(context.getWidth(), context.getHeight(), context.getGuis(), context.getStructure()); SimpleScrollNestedGUI gui = new SimpleScrollNestedGUI(context.getGuis(), context.getStructure());
gui.setBackground(gui.getBackground());
return gui;
} }
@Override @Override

@ -7,7 +7,9 @@ class ScrollItemsGUIType implements GUIType<SimpleScrollItemsGUI> {
@Override @Override
public SimpleScrollItemsGUI createGUI(GUIContext context) { public SimpleScrollItemsGUI createGUI(GUIContext context) {
return new SimpleScrollItemsGUI(context.getWidth(), context.getHeight(), context.getItems(), context.getStructure()); SimpleScrollItemsGUI gui = new SimpleScrollItemsGUI(context.getItems(), context.getStructure());
gui.setBackground(context.getBackground());
return gui;
} }
@Override @Override

@ -7,7 +7,9 @@ class ScrollVIGUIType implements GUIType<SimpleScrollVIGUI> {
@Override @Override
public SimpleScrollVIGUI createGUI(GUIContext context) { public SimpleScrollVIGUI createGUI(GUIContext context) {
return new SimpleScrollVIGUI(context.getWidth(), context.getHeight(), context.getInventory(), context.getStructure()); SimpleScrollVIGUI gui = new SimpleScrollVIGUI(context.getInventory(), context.getStructure());
gui.setBackground(context.getBackground());
return gui;
} }
@Override @Override

@ -7,7 +7,9 @@ class TabGUIType implements GUIType<SimpleTabGUI> {
@Override @Override
public SimpleTabGUI createGUI(GUIContext context) { public SimpleTabGUI createGUI(GUIContext context) {
return new SimpleTabGUI(context.getWidth(), context.getHeight(), context.getGuis(), context.getStructure()); SimpleTabGUI gui = new SimpleTabGUI(context.getGuis(), context.getStructure());
gui.setBackground(context.getBackground());
return gui;
} }
@Override @Override

@ -3,7 +3,6 @@ package de.studiocode.invui.gui.impl;
import de.studiocode.invui.gui.GUI; import de.studiocode.invui.gui.GUI;
import de.studiocode.invui.gui.SlotElement; import de.studiocode.invui.gui.SlotElement;
import de.studiocode.invui.gui.builder.GUIBuilder; import de.studiocode.invui.gui.builder.GUIBuilder;
import de.studiocode.invui.gui.structure.Markers;
import de.studiocode.invui.gui.structure.Structure; import de.studiocode.invui.gui.structure.Structure;
import java.util.List; import java.util.List;
@ -28,7 +27,7 @@ public abstract class PagedGUI extends BaseGUI {
} }
public PagedGUI(int width, int height, boolean infinitePages, Structure structure) { public PagedGUI(int width, int height, boolean infinitePages, Structure structure) {
this(width, height, infinitePages, structure.getIngredientList().findIndicesOfMarker(Markers.ITEM_LIST_SLOT)); this(width, height, infinitePages, structure.getIngredientList().findItemListSlots());
applyStructure(structure); applyStructure(structure);
} }

@ -39,7 +39,7 @@ public abstract class ScrollGUI extends BaseGUI {
} }
public ScrollGUI(int width, int height, boolean infiniteLines, Structure structure) { public ScrollGUI(int width, int height, boolean infiniteLines, Structure structure) {
this(width, height, infiniteLines, structure.getIngredientList().findIndicesOfMarker(Markers.ITEM_LIST_SLOT)); this(width, height, infiniteLines, structure.getIngredientList().findItemListSlots());
applyStructure(structure); applyStructure(structure);
} }

@ -13,8 +13,8 @@ public class SimpleGUI extends BaseGUI {
super(width, height); super(width, height);
} }
public SimpleGUI(int width, int height, @NotNull Structure structure) { public SimpleGUI(@NotNull Structure structure) {
super(width, height); super(structure.getWidth(), structure.getHeight());
applyStructure(structure); applyStructure(structure);
} }

@ -29,8 +29,8 @@ public class SimplePagedItemsGUI extends PagedGUI {
setItems(items); setItems(items);
} }
public SimplePagedItemsGUI(int width, int height, @Nullable List<Item> items, @NotNull Structure structure) { public SimplePagedItemsGUI(@Nullable List<Item> items, @NotNull Structure structure) {
super(width, height, false, structure); super(structure.getWidth(), structure.getHeight(), false, structure);
setItems(items); setItems(items);
} }

@ -29,8 +29,8 @@ public class SimplePagedNestedGUI extends PagedGUI {
setGuis(guis); setGuis(guis);
} }
public SimplePagedNestedGUI(int width, int height, @Nullable List<GUI> guis, @NotNull Structure structure) { public SimplePagedNestedGUI(@Nullable List<GUI> guis, @NotNull Structure structure) {
super(width, height, false, structure); super(structure.getWidth(), structure.getHeight(), false, structure);
setGuis(guis); setGuis(guis);
} }

@ -19,8 +19,8 @@ public class SimpleScrollItemsGUI extends ScrollGUI {
setItems(items); setItems(items);
} }
public SimpleScrollItemsGUI(int width, int height, @Nullable List<Item> items, @NotNull Structure structure) { public SimpleScrollItemsGUI(@Nullable List<Item> items, @NotNull Structure structure) {
super(width, height, false, structure); super(structure.getWidth(), structure.getHeight(), false, structure);
setItems(items); setItems(items);
} }

@ -19,8 +19,8 @@ public class SimpleScrollNestedGUI extends ScrollGUI {
setGuis(guis); setGuis(guis);
} }
public SimpleScrollNestedGUI(int width, int height, @Nullable List<GUI> guis, @NotNull Structure structure) { public SimpleScrollNestedGUI(@Nullable List<GUI> guis, @NotNull Structure structure) {
super(width, height, false, structure); super(structure.getWidth(), structure.getHeight(), false, structure);
setGuis(guis); setGuis(guis);
} }

@ -20,8 +20,8 @@ public class SimpleScrollVIGUI extends ScrollGUI {
update(); update();
} }
public SimpleScrollVIGUI(int width, int height, @Nullable VirtualInventory inventory, @NotNull Structure structure) { public SimpleScrollVIGUI(@Nullable VirtualInventory inventory, @NotNull Structure structure) {
super(width, height, false, structure); super(structure.getWidth(), structure.getHeight(), false, structure);
this.inventory = inventory; this.inventory = inventory;
update(); update();

@ -33,8 +33,8 @@ public class SimpleTabGUI extends TabGUI {
update(); update();
} }
public SimpleTabGUI(int width, int height, @NotNull List<GUI> tabs, @NotNull Structure structure) { public SimpleTabGUI(@NotNull List<GUI> tabs, @NotNull Structure structure) {
super(width, height, tabs.size(), structure); super(structure.getWidth(), structure.getHeight(), tabs.size(), structure);
this.linkingElements = tabs.stream().map(this::getLinkingElements).collect(Collectors.toList()); this.linkingElements = tabs.stream().map(this::getLinkingElements).collect(Collectors.toList());
this.tabs = tabs; this.tabs = tabs;

@ -2,7 +2,6 @@ package de.studiocode.invui.gui.impl;
import de.studiocode.invui.gui.Controllable; import de.studiocode.invui.gui.Controllable;
import de.studiocode.invui.gui.SlotElement; import de.studiocode.invui.gui.SlotElement;
import de.studiocode.invui.gui.structure.Markers;
import de.studiocode.invui.gui.structure.Structure; import de.studiocode.invui.gui.structure.Structure;
import java.util.List; import java.util.List;
@ -21,7 +20,7 @@ public abstract class TabGUI extends BaseGUI implements Controllable {
} }
public TabGUI(int width, int height, int tabAmount, Structure structure) { public TabGUI(int width, int height, int tabAmount, Structure structure) {
this(width, height, tabAmount, structure.getIngredientList().findIndicesOfMarker(Markers.ITEM_LIST_SLOT)); this(width, height, tabAmount, structure.getIngredientList().findItemListSlots());
applyStructure(structure); applyStructure(structure);
} }

@ -7,7 +7,7 @@ import java.util.function.Supplier;
class Ingredient { class Ingredient {
private final SlotElement slotElement; private final SlotElement slotElement;
private final String marker; private final Marker marker;
private final Supplier<? extends SlotElement> elementSupplier; private final Supplier<? extends SlotElement> elementSupplier;
public Ingredient(SlotElement slotElement) { public Ingredient(SlotElement slotElement) {
@ -22,7 +22,7 @@ class Ingredient {
this.marker = null; this.marker = null;
} }
public Ingredient(String marker) { public Ingredient(Marker marker) {
this.marker = marker; this.marker = marker;
this.slotElement = null; this.slotElement = null;
this.elementSupplier = null; this.elementSupplier = null;
@ -32,7 +32,7 @@ class Ingredient {
return slotElement == null ? elementSupplier.get() : slotElement; return slotElement == null ? elementSupplier.get() : slotElement;
} }
public String getMarker() { public Marker getMarker() {
return marker; return marker;
} }

@ -1,14 +1,22 @@
package de.studiocode.invui.gui.structure; package de.studiocode.invui.gui.structure;
import de.studiocode.invui.gui.GUI; import de.studiocode.invui.gui.GUI;
import de.studiocode.invui.util.SlotUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.stream.Stream;
public class IngredientList extends ArrayList<Ingredient> { public class IngredientList extends ArrayList<Ingredient> {
public IngredientList(String structure, HashMap<Character, Ingredient> ingredientMap) { private final int width;
private final int height;
public IngredientList(int width, int height, String structure, HashMap<Character, Ingredient> ingredientMap) {
this.width = width;
this.height = height;
for (char c : structure.toCharArray()) { for (char c : structure.toCharArray()) {
Ingredient ingredient = null; Ingredient ingredient = null;
if (ingredientMap.containsKey(c)) ingredient = ingredientMap.get(c); if (ingredientMap.containsKey(c)) ingredient = ingredientMap.get(c);
@ -27,15 +35,48 @@ public class IngredientList extends ArrayList<Ingredient> {
} }
} }
public int[] findIndicesOfMarker(String marker) { private List<Integer> findIndicesOfHorizontalMarker(Marker marker) {
List<Integer> indices = new ArrayList<>(); List<Integer> indices = new ArrayList<>();
for (int i = 0; i < size(); i++) { for (int i = 0; i < size(); i++) {
Ingredient ingredient = get(i); Ingredient ingredient = get(i);
if (ingredient != null && ingredient.isMarker() && ingredient.getMarker().equals(marker)) if (ingredient != null && ingredient.isMarker() && ingredient.getMarker() == marker)
indices.add(i); indices.add(i);
} }
return indices;
}
public List<Integer> findIndicesOfVerticalMarker(Marker marker) {
List<Integer> indices = new ArrayList<>();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int i = SlotUtils.convertToIndex(x, y, width);
Ingredient ingredient = get(i);
if (ingredient != null && ingredient.isMarker() && ingredient.getMarker() == marker)
indices.add(i);
}
}
return indices;
}
public int[] findIndicesOfMarker(Marker marker) {
List<Integer> indices;
if (marker.isHorizontal()) {
indices = findIndicesOfHorizontalMarker(marker);
} else {
indices = findIndicesOfVerticalMarker(marker);
}
return indices.stream().mapToInt(Integer::intValue).toArray(); return indices.stream().mapToInt(Integer::intValue).toArray();
} }
public int[] findItemListSlots() {
return Stream.concat(
findIndicesOfHorizontalMarker(Markers.ITEM_LIST_SLOT_HORIZONTAL).stream(),
findIndicesOfVerticalMarker(Markers.ITEM_LIST_SLOT_VERTICAL).stream()
).mapToInt(Integer::intValue).toArray();
}
} }

@ -0,0 +1,15 @@
package de.studiocode.invui.gui.structure;
public class Marker {
private final boolean horizontal;
public Marker(boolean horizontal) {
this.horizontal = horizontal;
}
public boolean isHorizontal() {
return horizontal;
}
}

@ -10,9 +10,15 @@ import de.studiocode.invui.gui.impl.TabGUI;
public class Markers { public class Markers {
/** /**
* The marker for item list slots in {@link PagedGUI PagedGUIs}, * The marker for horizontal item list slots in {@link PagedGUI PagedGUIs},
* {@link ScrollGUI ScrollGUIs} and {@link TabGUI TabGUIs} * {@link ScrollGUI ScrollGUIs} and {@link TabGUI TabGUIs}
*/ */
public static final String ITEM_LIST_SLOT = "ILS"; public static final Marker ITEM_LIST_SLOT_HORIZONTAL = new Marker(true);
/**
* The marker for vertical item list slots in {@link PagedGUI PagedGUIs},
* {@link ScrollGUI ScrollGUIs} and {@link TabGUI TabGUIs}
*/
public static final Marker ITEM_LIST_SLOT_VERTICAL = new Marker(true);
} }

@ -26,13 +26,27 @@ public class Structure implements Cloneable {
private static final HashMap<Character, Ingredient> globalIngredientMap = new HashMap<>(); private static final HashMap<Character, Ingredient> globalIngredientMap = new HashMap<>();
private final String structureData; private final String structureData;
private final int width;
private final int height;
private HashMap<Character, Ingredient> ingredientMap = new HashMap<>(); private HashMap<Character, Ingredient> ingredientMap = new HashMap<>();
private IngredientList ingredientList; private IngredientList ingredientList;
public Structure(String structureData) { public Structure(String... structureData) {
this.structureData = structureData this(sanitize(structureData[0]).length(), structureData.length, String.join("", structureData));
.replace(" ", "") }
.replace("\n", "");
public Structure(int width, int height, String structureData) {
this.width = width;
this.height = height;
this.structureData = sanitize(structureData);
if (width * height != this.structureData.length())
throw new IllegalArgumentException("Length of structure data does not match width * height");
}
private static String sanitize(String s) {
return s.replace(" ", "").replace("\n", "");
} }
public static void addGlobalIngredient(char key, @NotNull ItemStack itemStack) { public static void addGlobalIngredient(char key, @NotNull ItemStack itemStack) {
@ -55,7 +69,7 @@ public class Structure implements Cloneable {
globalIngredientMap.put(key, new Ingredient(element)); globalIngredientMap.put(key, new Ingredient(element));
} }
public static void addGlobalIngredient(char key, @NotNull String marker) { public static void addGlobalIngredient(char key, @NotNull Marker marker) {
globalIngredientMap.put(key, new Ingredient(marker)); globalIngredientMap.put(key, new Ingredient(marker));
} }
@ -94,7 +108,7 @@ public class Structure implements Cloneable {
return this; return this;
} }
public Structure addIngredient(char key, @NotNull String marker) { public Structure addIngredient(char key, @NotNull Marker marker) {
if (ingredientList != null) throw new IllegalStateException("Structure is locked"); if (ingredientList != null) throw new IllegalStateException("Structure is locked");
ingredientMap.put(key, new Ingredient(marker)); ingredientMap.put(key, new Ingredient(marker));
return this; return this;
@ -117,7 +131,15 @@ public class Structure implements Cloneable {
HashMap<Character, Ingredient> ingredients = new HashMap<>(globalIngredientMap); HashMap<Character, Ingredient> ingredients = new HashMap<>(globalIngredientMap);
ingredients.putAll(this.ingredientMap); ingredients.putAll(this.ingredientMap);
return ingredientList = new IngredientList(structureData, ingredients); return ingredientList = new IngredientList(width, height, structureData, ingredients);
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
} }
@Override @Override