austinhaha
4/27/2018 - 3:43 AM

miniwindow.java

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);
	}
}