ScrollGUI

This commit is contained in:
NichtStudioCode 2021-02-08 13:04:27 +01:00
parent 5e8a9d5536
commit b76be6ffd8
8 changed files with 269 additions and 17 deletions

@ -10,7 +10,7 @@ import de.studiocode.invui.util.SlotUtils;
import de.studiocode.invui.virtualinventory.VirtualInventory;
import org.jetbrains.annotations.NotNull;
import java.util.SortedSet;
import java.util.Set;
/**
* A subclass of {@link IndexedGUI} which contains all the
@ -79,7 +79,7 @@ public abstract class BaseGUI extends IndexedGUI {
// filling methods
public void fill(@NotNull SortedSet<Integer> slots, Item item, boolean replaceExisting) {
public void fill(@NotNull Set<Integer> slots, Item item, boolean replaceExisting) {
for (int slot : slots) {
if (!replaceExisting && hasSlotElement(slot)) continue;
setItem(slot, item);

@ -64,7 +64,8 @@ public abstract class PagedGUI extends BaseGUI {
}
private void correctPage() {
if (currentPage == 0) return;
if (currentPage == 0 || infinitePages) return;
int pageAmount = getPageAmount();
if (currentPage < 0) currentPage = 0;
else if (currentPage >= pageAmount) currentPage = pageAmount - 1;

@ -0,0 +1,120 @@
package de.studiocode.invui.gui.impl;
import de.studiocode.invui.gui.GUI;
import de.studiocode.invui.gui.SlotElement;
import de.studiocode.invui.item.Item;
import java.util.ArrayList;
import java.util.List;
/**
* A scrollable {@link GUI}
*
* @see SimpleScrollGUI
*/
public abstract class ScrollGUI extends BaseGUI {
private final List<Item> controlItems = new ArrayList<>();
private final boolean infiniteLines;
private final int lineLength;
private final int[] itemListSlots;
protected int offset;
public ScrollGUI(int width, int height, boolean infiniteLines, int lineLength, int... itemListSlots) {
super(width, height);
this.infiniteLines = infiniteLines;
this.itemListSlots = itemListSlots;
this.lineLength = lineLength;
if (lineLength == 0)
throw new IllegalArgumentException("Line length can't be 0");
if (itemListSlots.length == 0)
throw new IllegalArgumentException("No item list slots provided");
if (itemListSlots.length % lineLength != 0)
throw new IllegalArgumentException("itemListSlots has to be a multiple of lineLength");
}
public void addControlItem(int index, Item item) {
controlItems.add(item);
setItem(index, item);
}
public void setCurrentLine(int line) {
this.offset = line * lineLength;
}
public int getCurrentLine() {
return offset / lineLength;
}
private int getMaxLineIndex() {
int maxLineIndex = (int) Math.ceil((double) getElementAmount() / (double) lineLength);
return Math.max(0, maxLineIndex - getLineAmount());
}
private int getLineAmount() {
return itemListSlots.length / lineLength;
}
public boolean canScroll(int lines) {
if (lines == 0 || (infiniteLines && lines > 0)) return true;
int line = getCurrentLine() + lines;
int maxLineAmount = getMaxLineIndex();
return line >= 0 && line <= maxLineAmount;
}
public void scroll(int lines) {
if (lines == 0) return;
if (canScroll(lines)) {
setCurrentLine(getCurrentLine() + lines);
update();
} else if (lines > 1) {
setCurrentLine(getMaxLineIndex());
update();
} else if (lines < -1) {
setCurrentLine(0);
update();
}
}
protected void update() {
correctLine();
updateControlItems();
updateContent();
}
private void correctLine() {
if (offset == 0 || infiniteLines) return;
if (offset < 0) {
offset = 0;
} else {
int currentLine = getCurrentLine();
int maxLineIndex = getMaxLineIndex();
if (currentLine >= maxLineIndex) setCurrentLine(maxLineIndex);
}
}
private void updateControlItems() {
controlItems.forEach(Item::notifyWindows);
}
private void updateContent() {
List<SlotElement> slotElements = getElements(offset, itemListSlots.length + offset);
for (int i = 0; i < itemListSlots.length; i++) {
if (slotElements.size() > i) setSlotElement(itemListSlots[i], slotElements.get(i));
else remove(itemListSlots[i]);
}
}
abstract protected int getElementAmount();
abstract protected List<SlotElement> getElements(int from, int to);
}

@ -0,0 +1,37 @@
package de.studiocode.invui.gui.impl;
import de.studiocode.invui.gui.SlotElement;
import de.studiocode.invui.item.Item;
import java.util.List;
import java.util.stream.Collectors;
public class SimpleScrollGUI extends ScrollGUI {
private List<Item> items;
public SimpleScrollGUI(int width, int height, List<Item> items, int lineLength, int... itemListSlots) {
super(width, height, false, lineLength, itemListSlots);
this.items = items;
update();
}
public void setItems(List<Item> items) {
this.items = items;
update();
}
@Override
protected int getElementAmount() {
return items.size();
}
@Override
protected List<SlotElement> getElements(int from, int to) {
return items.subList(from, Math.min(items.size(), to)).stream()
.map(SlotElement.ItemSlotElement::new)
.collect(Collectors.toList());
}
}

@ -0,0 +1,34 @@
package de.studiocode.invui.item.impl.scrollgui;
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;
import org.bukkit.event.inventory.InventoryClickEvent;
import java.util.HashMap;
import java.util.function.Function;
public class ScrollItem extends FunctionItem<ScrollGUI> {
private final HashMap<ClickType, Integer> scroll;
public ScrollItem(ScrollGUI scrollGUI, int scrollLeftClick, Function<ScrollGUI, ItemBuilder> builderFunction) {
super(scrollGUI, builderFunction);
scroll = new HashMap<>();
scroll.put(ClickType.LEFT, scrollLeftClick);
}
public ScrollItem(ScrollGUI scrollGUI, HashMap<ClickType, Integer> scroll, Function<ScrollGUI, ItemBuilder> builderFunction) {
super(scrollGUI, builderFunction);
this.scroll = scroll;
}
@Override
public void handleClick(ClickType clickType, Player player, InventoryClickEvent event) {
if (scroll.containsKey(clickType)) getT().scroll(scroll.get(clickType));
}
}

@ -0,0 +1,21 @@
package de.studiocode.invui.util;
public class Point2D {
private int x;
private int y;
public Point2D(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}

@ -1,24 +1,24 @@
package de.studiocode.invui.util;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.LinkedHashSet;
import java.util.Set;
public class SlotUtils {
public static SortedSet<Integer> getSlotsRow(int row, int width) {
SortedSet<Integer> slots = new TreeSet<>();
public static Set<Integer> getSlotsRow(int row, int width) {
Set<Integer> slots = new LinkedHashSet<>();
for (int x = 0; x < width; x++) slots.add(convertToIndex(x, row, width));
return slots;
}
public static SortedSet<Integer> getSlotsColumn(int column, int width, int height) {
SortedSet<Integer> slots = new TreeSet<>();
public static Set<Integer> getSlotsColumn(int column, int width, int height) {
Set<Integer> slots = new LinkedHashSet<>();
for (int y = 0; y < height; y++) slots.add(convertToIndex(column, y, width));
return slots;
}
public static SortedSet<Integer> getSlotsBorders(int width, int height) {
SortedSet<Integer> slots = new TreeSet<>();
public static Set<Integer> getSlotsBorders(int width, int height) {
Set<Integer> slots = new LinkedHashSet<>();
if (height > 0) slots.addAll(getSlotsRow(0, width));
if (height - 1 > 0) slots.addAll(getSlotsRow(height - 1, width));
if (width > 0) slots.addAll(getSlotsColumn(0, width, height));
@ -26,21 +26,45 @@ public class SlotUtils {
return slots;
}
public static SortedSet<Integer> getSlotsRect(int x, int y, int width, int height, int frameWidth) {
SortedSet<Integer> slots = new TreeSet<>();
public static Set<Integer> getSlotsRect(int x, int y, int width, int height, int frameWidth) {
return getSlotsRect(Order.HORIZONTAL, x, y, width, height, frameWidth);
}
public static Set<Integer> getSlotsRect(Order order, int x, int y, int width, int height, int frameWidth) {
Set<Integer> slots = new LinkedHashSet<>();
switch (order) {
case HORIZONTAL:
for (int y1 = y; y1 < height + y; y1++) {
for (int x1 = x; x1 < width + x; x1++) {
slots.add(convertToIndex(x1, y1, frameWidth));
}
}
break;
case VERTICAL:
for (int x1 = x; x1 < width + x; x1++) {
for (int y1 = y; y1 < height + y; y1++) {
slots.add(convertToIndex(x1, y1, frameWidth));
}
}
}
return slots;
}
public static int convertToIndex(Point2D point, int width) {
return convertToIndex(point.getX(), point.getY(), width);
}
public static int convertToIndex(int x, int y, int width) {
return y * width + x;
}
public static Point2D convertFromIndex(int index, int width) {
return new Point2D(index % width, index / width);
}
public static int translatePlayerInvToGui(int slot) {
if (slot > 8) return slot - 9;
else return slot + 27;
@ -51,4 +75,11 @@ public class SlotUtils {
else return slot + 9;
}
public enum Order {
HORIZONTAL,
VERTICAL
}
}

@ -12,8 +12,16 @@ public class SimpleWindow extends SingleWindow {
super(viewerUUID, gui, InventoryUtils.createMatchingInventory(gui, title), true, closeable, closeOnEvent);
}
public SimpleWindow(UUID viewerUUID, String title, GUI gui) {
this(viewerUUID, title, gui, true, true);
}
public SimpleWindow(Player player, String title, GUI gui, boolean closeable, boolean closeOnEvent) {
this(player.getUniqueId(), title, gui, closeable, closeOnEvent);
}
public SimpleWindow(Player player, String title, GUI gui) {
this(player, title, gui, true, true);
}
}