public class MiniWindow implements Listener {
public MiniWindow(Plugin plugin) {
getPluginManager().registerEvents(this, plugin);
}
//--Page--
public Inventory page(final int size, final String title, final Consumer<Page> like) {
Page page = page(size, title);
like.accept(page);
return page.getInventory();
}
public Page page(final int size, final String title) {
return new PageImpl() {
final Inventory inventory = createInventory(this, size, title);
final Item[] items = new Item[size];
@Override
public Inventory getInventory() {
return inventory;
}
@Override
public int size() {
return size;
}
@Override
public String title() {
return title;
}
@Override
public Item[] items() {
return items;
}
};
}
//--Events--
@EventHandler
void onClick(InventoryClickEvent event) {
final InventoryHolder holder = event.getClickedInventory().getHolder();
if (holder instanceof PageImpl) {
final Item item = ((PageImpl) holder).items()[event.getSlot()];
if (item instanceof ItemImpl)
if (((ItemImpl) item).listener.test((Player) event.getWhoClicked(), event.getClick()))
event.setCancelled(true);
}
}
@EventHandler
void onClose(InventoryCloseEvent event) {
final InventoryHolder holder = event.getInventory().getHolder();
if (holder instanceof PageImpl)
((PageImpl) holder).openListener.accept((Player) event.getPlayer());
}
@EventHandler
void onOpen(InventoryOpenEvent event) {
final InventoryHolder holder = event.getInventory().getHolder();
if (holder instanceof PageImpl)
((PageImpl) holder).closeListener.accept((Player) event.getPlayer());
}
//--Classes--
private static abstract class PageImpl implements Page {
Consumer<Player> openListener = $ -> {
}, closeListener = $ -> {
};
@Override
public void onClose(Consumer<Player> listener) {
closeListener = listener;
}
@Override
public void onOpen(Consumer<Player> listener) {
openListener = listener;
}
}
private static abstract class ItemImpl extends ItemStack implements Item {
BiPredicate<Player, ClickType> listener = (p, t) -> true;
@Override
public ItemStack itemStack() {
return this;
}
@Override
public void onClick(BiPredicate<Player, ClickType> listener) {
this.listener = listener;
}
}
public interface Page extends InventoryHolder {
Item[] items();
int size();
String title();
default Item item() {
return item(STONE);
}
//TODO consider making this a little smarter.
default Item item(Material type) {
for (int i = 0; i < size(); i++)
if (items()[i] == null)
return item(i, type);
throw new IndexOutOfBoundsException("There is no room left in this page!");
}
default Item item(Number row, Number column) {
return item(row, column, STONE);
}
default Item item(Number row, Number column, Material type) {
return item((row.intValue() * 9) + column.intValue(), type);
}
default Item item(Number index) {
return item(index, STONE);
}
default Item item(Number index, Material type) {
final Item item = new ItemImpl() {
@Override
public void tempUpdateForAustin() {
getInventory().setItem(index.intValue(), itemStack());
}
}.type(type).amount(1);
item.tempUpdateForAustin();
return items()[index.intValue()] = item;
}
//--Events--
default void onClose(Runnable listener) {
onClose(player -> listener.run());
}
default void onOpen(Runnable listener) {
onOpen(player -> listener.run());
}
void onClose(Consumer<Player> listener);
void onOpen(Consumer<Player> listener);
}
public interface Item {
ItemStack itemStack();
void tempUpdateForAustin();
default Item text(String... lines) {
ItemMeta meta = itemStack().getItemMeta();
meta.setLore(asList(lines));
itemStack().setItemMeta(meta);
tempUpdateForAustin();
return this;
}
default Item text(Iterable<String> lines) {
ItemMeta meta = itemStack().getItemMeta();
meta.setLore(newArrayList(lines));
itemStack().setItemMeta(meta);
tempUpdateForAustin();
return this;
}
default Item amount(Number amount) {
itemStack().setAmount(amount.intValue());
tempUpdateForAustin();
return this;
}
default Item title(Object title) {
ItemMeta meta = itemStack().getItemMeta();
meta.setDisplayName(title.toString());
itemStack().setItemMeta(meta);
tempUpdateForAustin();
return this;
}
default Item type(Material material) {
itemStack().setType(material);
tempUpdateForAustin();
return this;
}
@SuppressWarnings("unchecked")
default <Data extends MaterialData> Data data() {
return (Data) itemStack().getData();
}
default Item data(MaterialData data) {
return data(data.getData());
}
default Item data(Number data) {
itemStack().getData().setData(data.byteValue());
tempUpdateForAustin();
return durability(data);
}
default Item durability(Number durability) {
itemStack().setDurability(durability.shortValue());
tempUpdateForAustin();
return this;
}
default void onClick(Runnable runnable) {
onClick($ -> runnable.run());
}
default void onClick(Consumer<Player> listener) {
onClick((player, type) -> {
listener.accept(player);
});
}
default void onClick(BiConsumer<Player, ClickType> listener) {
onClick((player, type) -> {
listener.accept(player, type);
return true;
});
}
void onClick(BiPredicate<Player, ClickType> listener);
}
}