HeadDB/src/main/java/tsp/headdb/inventory/PagedPane.java
2021-06-19 17:25:26 +02:00

408 Zeilen
13 KiB
Java

package tsp.headdb.inventory;
import net.wesjd.anvilgui.AnvilGUI;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import tsp.headdb.HeadDB;
import tsp.headdb.api.HeadAPI;
import tsp.headdb.util.Utils;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
/**
* A paged pane. Credits @ I Al Ianstaan
*/
public class PagedPane implements InventoryHolder {
private Inventory inventory;
private SortedMap<Integer, Page> pages = new TreeMap<>();
private int currentIndex;
private int pageSize;
@SuppressWarnings("WeakerAccess")
protected Button controlBack;
@SuppressWarnings("WeakerAccess")
protected Button controlNext;
@SuppressWarnings("WeakerAccess")
protected Button controlMain;
/**
* @param pageSize The page size. inventory rows - 2
*/
public PagedPane(int pageSize, int rows, String title) {
Objects.requireNonNull(title, "title can not be null!");
if (rows > 6) {
throw new IllegalArgumentException("Rows must be <= 6, got " + rows);
}
if (pageSize > 6) {
throw new IllegalArgumentException("Page size must be <= 6, got" + pageSize);
}
this.pageSize = pageSize;
inventory = Bukkit.createInventory(this, rows * 9, color(title));
pages.put(0, new Page(pageSize));
}
/**
* @param button The button to add
*/
public void addButton(Button button) {
for (Entry<Integer, Page> entry : pages.entrySet()) {
if (entry.getValue().addButton(button)) {
if (entry.getKey() == currentIndex) {
reRender();
}
return;
}
}
Page page = new Page(pageSize);
page.addButton(button);
pages.put(pages.lastKey() + 1, page);
reRender();
}
/**
* @param button The Button to remove
*/
@SuppressWarnings("unused")
public void removeButton(Button button) {
for (Iterator<Entry<Integer, Page>> iterator = pages.entrySet().iterator(); iterator.hasNext(); ) {
Entry<Integer, Page> entry = iterator.next();
if (entry.getValue().removeButton(button)) {
// we may need to delete the page
if (entry.getValue().isEmpty()) {
// we have more than one page, so delete it
if (pages.size() > 1) {
iterator.remove();
}
// the currentIndex now points to a page that does not exist. Correct it.
if (currentIndex >= pages.size()) {
currentIndex--;
}
}
// if we modified the current one, re-render
// if we deleted the current page, re-render too
if (entry.getKey() >= currentIndex) {
reRender();
}
return;
}
}
}
/**
* @return The amount of pages
*/
@SuppressWarnings("WeakerAccess")
public int getPageAmount() {
return pages.size();
}
/**
* @return The number of the current page (1 based)
*/
@SuppressWarnings("WeakerAccess")
public int getCurrentPage() {
return currentIndex + 1;
}
/**
* @param index The index of the new page
*/
@SuppressWarnings("WeakerAccess")
public void selectPage(int index) {
if (index < 0 || index >= getPageAmount()) {
throw new IllegalArgumentException(
"Index out of bounds s: " + index + " [" + 0 + " " + getPageAmount() + ")"
);
}
if (index == currentIndex) {
return;
}
currentIndex = index;
reRender();
}
/**
* Renders the inventory again
*/
@SuppressWarnings("WeakerAccess")
public void reRender() {
inventory.clear();
pages.get(currentIndex).render(inventory);
controlBack = null;
controlNext = null;
controlMain = null;
createControls(inventory);
}
/**
* @param event The {@link InventoryClickEvent}
*/
@SuppressWarnings("WeakerAccess")
public void onClick(InventoryClickEvent event) {
event.setCancelled(true);
// back item
if (event.getSlot() == inventory.getSize() - 8) {
if (controlBack != null) {
controlBack.onClick(event);
}
return;
}
// next item
else if (event.getSlot() == inventory.getSize() - 2) {
if (controlNext != null) {
controlNext.onClick(event);
}
return;
}
else if (event.getSlot() == inventory.getSize()- 5) {
if (controlMain != null){
controlMain.onClick(event);
}
return;
}
pages.get(currentIndex).handleClick(event);
}
/**
* Get the object's inventory.
*
* @return The inventory.
*/
@Override
public Inventory getInventory() {
return inventory;
}
/**
* Creates the controls
*
* @param inventory The inventory
*/
@SuppressWarnings("WeakerAccess")
protected void createControls(Inventory inventory) {
// create separator
fillRow(
inventory.getSize() / 9 - 2,
new ItemStack(Material.BLACK_STAINED_GLASS_PANE),
inventory
);
if (getCurrentPage() > 1) {
String name = String.format(
Locale.ROOT,
"&3&lPage &a&l%d &7/ &c&l%d",
getCurrentPage() - 1, getPageAmount()
);
String lore = String.format(
Locale.ROOT,
"&7Previous: &c%d",
getCurrentPage() - 1
);
ItemStack itemStack = setMeta(HeadAPI.getHeadByValue("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODY1MmUyYjkzNmNhODAyNmJkMjg2NTFkN2M5ZjI4MTlkMmU5MjM2OTc3MzRkMThkZmRiMTM1NTBmOGZkYWQ1ZiJ9fX0=").getItemStack(), name, lore);
controlBack = new Button(itemStack, event -> selectPage(currentIndex - 1));
inventory.setItem(inventory.getSize() - 8, itemStack);
}
if (getCurrentPage() < getPageAmount()) {
String name = String.format(
Locale.ROOT,
"&3&lPage &a&l%d &7/ &c&l%d",
getCurrentPage() + 1, getPageAmount()
);
String lore = String.format(
Locale.ROOT,
"&7Next: &c%d",
getCurrentPage() + 1
);
ItemStack itemStack = setMeta(HeadAPI.getHeadByValue("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMmEzYjhmNjgxZGFhZDhiZjQzNmNhZThkYTNmZTgxMzFmNjJhMTYyYWI4MWFmNjM5YzNlMDY0NGFhNmFiYWMyZiJ9fX0=").getItemStack(), name, lore);
controlNext = new Button(itemStack, event -> selectPage(getCurrentPage()));
inventory.setItem(inventory.getSize() - 2, itemStack);
}
{
String name = String.format(
Locale.ROOT,
"&3&lPage &a&l%d &7/ &c&l%d",
getCurrentPage(), getPageAmount()
);
ItemStack itemStack = setMeta(HeadAPI.getHeadByValue("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q5MWY1MTI2NmVkZGM2MjA3ZjEyYWU4ZDdhNDljNWRiMDQxNWFkYTA0ZGFiOTJiYjc2ODZhZmRiMTdmNGQ0ZSJ9fX0=").getItemStack(),
name,
"&7Left-Click to go to the &cMain Menu",
"&7Right-Click to go to a &6Specific Page");
controlMain = new Button(itemStack, event -> {
if (event.getClick() == ClickType.RIGHT) {
new AnvilGUI.Builder()
.onComplete((player, text) -> {
try {
int i = Integer.parseInt(text);
if (i > getPageAmount()) {
Utils.sendMessage(player, "&cPage number is out of bounds! Max: &e" + getPageAmount());
return AnvilGUI.Response.text("&cOut of bounds!");
}
selectPage(i - 1);
return AnvilGUI.Response.openInventory(this.getInventory());
} catch (NumberFormatException nfe) {
Utils.sendMessage(player, "&cValue must be a number!");
return AnvilGUI.Response.text(Utils.colorize("&cValue must be a number!"));
}
})
.title("Select Page")
.text("Page number...")
.plugin(HeadDB.getInstance())
.open((Player) event.getWhoClicked());
} else {
InventoryUtils.openDatabase((Player) event.getWhoClicked());
}
});
inventory.setItem(inventory.getSize() - 5, itemStack);
}
}
private void fillRow(int rowIndex, ItemStack itemStack, Inventory inventory) {
int yMod = rowIndex * 9;
for (int i = 0; i < 9; i++) {
int slot = yMod + i;
inventory.setItem(slot, setMeta(itemStack, ""));
}
}
protected ItemStack setMeta(ItemStack itemStack, String name, String... lore) {
ItemMeta meta = itemStack.getItemMeta();
meta.setDisplayName(Utils.colorize(name));
meta.setLore(Arrays.stream(lore).map(this::color).collect(Collectors.toList()));
itemStack.setItemMeta(meta);
return itemStack;
}
@SuppressWarnings("WeakerAccess")
@Deprecated
protected ItemStack getItemStack(Material type, int durability, String name, String... lore) {
ItemStack itemStack = new ItemStack(type, 1, (short) durability);
ItemMeta itemMeta = itemStack.getItemMeta();
if (name != null) {
itemMeta.setDisplayName(color(name));
}
if (lore != null && lore.length != 0) {
itemMeta.setLore(Arrays.stream(lore).map(this::color).collect(Collectors.toList()));
}
itemStack.setItemMeta(itemMeta);
return itemStack;
}
@SuppressWarnings("WeakerAccess")
protected String color(String input) {
return ChatColor.translateAlternateColorCodes('&', input);
}
/**
* @param player The {@link Player} to open it for
*/
public void open(Player player) {
reRender();
player.openInventory(getInventory());
}
private static class Page {
private List<Button> buttons = new ArrayList<>();
private int maxSize;
Page(int maxSize) {
this.maxSize = maxSize;
}
/**
* @param event The click event
*/
void handleClick(InventoryClickEvent event) {
// user clicked in his own inventory. Silently drop it
if (event.getRawSlot() > event.getInventory().getSize()) {
return;
}
// user clicked outside of the inventory
if (event.getSlotType() == InventoryType.SlotType.OUTSIDE) {
return;
}
if (event.getSlot() >= buttons.size()) {
return;
}
Button button = buttons.get(event.getSlot());
button.onClick(event);
}
/**
* @return True if there is space left
*/
boolean hasSpace() {
return buttons.size() < maxSize * 9;
}
/**
* @param button The {@link Button} to add
*
* @return True if the button was added, false if there was no space
*/
boolean addButton(Button button) {
if (!hasSpace()) {
return false;
}
buttons.add(button);
return true;
}
/**
* @param button The {@link Button} to remove
*
* @return True if the button was removed
*/
boolean removeButton(Button button) {
return buttons.remove(button);
}
/**
* @param inventory The inventory to render in
*/
void render(Inventory inventory) {
for (int i = 0; i < buttons.size(); i++) {
Button button = buttons.get(i);
inventory.setItem(i, button.getItemStack());
}
}
/**
* @return True if this page is empty
*/
boolean isEmpty() {
return buttons.isEmpty();
}
}
}