From 80089c7bf54fb33f9b77b64126fc29b5b091addf Mon Sep 17 00:00:00 2001 From: Amaury Carrade Date: Thu, 10 Sep 2015 00:55:10 +0200 Subject: [PATCH] Improved the GUI manager. * NEW: reformatted the code a little bit to make it more readable. * NEW: added Javadoc when it was missing. * NEW: changed the name of the fallback action method in `ActionGui`, from `onAction_unknown` to `unknown_action` (coherence of the methods names). * NEW: the action methods (both declared and unknown) can now take an extra argument: the triggered InventoryClickEvent. This argument is completely optional, so this will not break any code, and if the event is not needed, it can just be skipped. * NEW: renamed the setData(int, int) method to setDataShape(int, int), because this method does not actually set any data. --- .../imageonmap/guiproko/core/ActionGui.java | 101 ++++-- .../imageonmap/guiproko/core/ExplorerGui.java | 219 +++++++++++-- .../moribus/imageonmap/guiproko/core/Gui.java | 98 +++--- .../imageonmap/guiproko/core/GuiUtils.java | 293 ++++++++++-------- .../guiproko/list/MapDetailGui.java | 2 +- 5 files changed, 481 insertions(+), 232 deletions(-) diff --git a/src/main/java/fr/moribus/imageonmap/guiproko/core/ActionGui.java b/src/main/java/fr/moribus/imageonmap/guiproko/core/ActionGui.java index 6a24237..3ca2a93 100644 --- a/src/main/java/fr/moribus/imageonmap/guiproko/core/ActionGui.java +++ b/src/main/java/fr/moribus/imageonmap/guiproko/core/ActionGui.java @@ -18,18 +18,14 @@ package fr.moribus.imageonmap.guiproko.core; -import fr.moribus.imageonmap.PluginLogger; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import org.bukkit.Material; -import org.bukkit.event.inventory.InventoryAction; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; +import fr.moribus.imageonmap.*; +import org.bukkit.*; +import org.bukkit.event.inventory.*; +import org.bukkit.inventory.*; +import org.bukkit.inventory.meta.*; + +import java.lang.reflect.*; +import java.util.*; /** * This class implements an action-based GUI. @@ -38,7 +34,10 @@ import org.bukkit.inventory.meta.ItemMeta; * * Events handlers are (usually private) methods implemented in the derived * class(es). They are named using the pattern 'action_[action name]', and - * are called when the associated action is triggered. + * are called when the associated action is triggered. They take an optional + * argument (add it if you need it): the {@link InventoryClickEvent} triggered. + * + * @author ProkopyL (main) and Amaury Carrade */ abstract public class ActionGui extends Gui { @@ -49,7 +48,7 @@ abstract public class ActionGui extends Gui /** * The class of this GUI. - * Useful to retreive methods from the derived classes. + * Useful to retrieve methods from the derived classes. */ private final Class guiClass = this.getClass(); @@ -58,12 +57,14 @@ abstract public class ActionGui extends Gui * their position in the inventory. */ private final HashMap actions = new HashMap<>(); - + + /* ===== Protected API ===== */ /** * Creates a new action, represented by the given item. * The item's metadata is changed to use the given title and lore. + * * @param name The identifier of the action. * @param slot The slot the action will be placed on. * @param material The material used to represent the action. @@ -78,6 +79,7 @@ abstract public class ActionGui extends Gui /** * Creates a new action, represented by the given item. * The item's metadata is changed to use the given title and lore. + * * @param name The identifier of the action. * @param slot The slot the action will be placed on. * @param item The item used to represent the action. @@ -92,6 +94,7 @@ abstract public class ActionGui extends Gui /** * Creates a new action, represented by the given item. * The item's metadata is changed to use the given title and lore. + * * @param name The identifier of the action. * @param slot The slot the action will be placed on. * @param item The item used to represent the action. @@ -105,6 +108,7 @@ abstract public class ActionGui extends Gui /** * Creates a new action, represented by the given material. + * * @param name The identifier of the action. * @param slot The slot the action will be placed on. * @param material The material used to represent the action. @@ -116,18 +120,21 @@ abstract public class ActionGui extends Gui /** * Creates a new action, represented by no item. - * This action will not be rendered to the user until {@link #updateAction(java.lang.String, org.bukkit.inventory.ItemStack, java.lang.String) - * } is called. + * This action will not be rendered to the user until + * {@link #updateAction(java.lang.String, org.bukkit.inventory.ItemStack, java.lang.String)} + * is called. + * * @param name The identifier of the action. * @param slot The slot the action will be placed on. */ protected void action(String name, int slot) { - action(name, slot, (ItemStack)null); + action(name, slot, (ItemStack) null); } /** * Creates a new action, and adds it to the GUI. + * * @param name The identifier of the action. * @param slot The slot the action will be placed on. * @param item The item used to represent the action. @@ -142,7 +149,8 @@ abstract public class ActionGui extends Gui /** * Adds an action to the GUI. - * @param action + * + * @param action The {@link fr.moribus.imageonmap.guiproko.core.ActionGui.Action} to register. */ private void action(Action action) { @@ -151,6 +159,7 @@ abstract public class ActionGui extends Gui /** * Updates the action represented by the given name. + * * @param name The name of the action to update. * @param item The new material to affect to the action. * @param title The new title to affect to the action. @@ -163,6 +172,7 @@ abstract public class ActionGui extends Gui /** * Updates the action represented by the given name. + * * @param name The name of the action to update. * @param item The new item to affect to the action. * @param title The new title to affect to the action. @@ -178,7 +188,8 @@ abstract public class ActionGui extends Gui } /** - * Retreives the action represented by the given name. + * Retrieves the action represented by the given name. + * * @param name The name of the action to retreive. * @return The action represented by the given name. * @throws IllegalArgumentException If no action has the given name. @@ -200,13 +211,28 @@ abstract public class ActionGui extends Gui protected abstract void onUpdate(); /** - * Raised when an action whithout any event handler has been triggered. + * Raised when an action without any event handler has been triggered. + * + * @param name The name of the triggered action. + * @param slot The slot of the action. + * @param item The item of the action. + * @param event The {@link InventoryClickEvent} raised when this action was triggered. + */ + protected void unknown_action(String name, int slot, ItemStack item, InventoryClickEvent event) + { + unknown_action(name, slot, item); + } + + /** + * Raised when an action without any event handler has been triggered. + * * @param name The name of the triggered action. * @param slot The slot of the action. * @param item The item of the action. */ - protected void onAction_unknown(String name, int slot, ItemStack item){} - + protected void unknown_action(String name, int slot, ItemStack item) {} + + @Override public void update() { @@ -226,11 +252,12 @@ abstract public class ActionGui extends Gui @Override protected void onClick(InventoryClickEvent event) { - if(event.getRawSlot() >= event.getInventory().getSize())//The user clicked in its own inventory + if(event.getRawSlot() >= event.getInventory().getSize()) //The user clicked in its own inventory { if(!event.getAction().equals(InventoryAction.MOVE_TO_OTHER_INVENTORY)) return; } + event.setCancelled(true); callAction(actions.get(event.getRawSlot())); @@ -243,9 +270,10 @@ abstract public class ActionGui extends Gui private void callAction(Action action) { if(action == null) return; + if(action.callback == null) { - onAction_unknown(action.name, action.slot, action.item); + unknown_action(action.name, action.slot, action.item); return; } @@ -265,19 +293,29 @@ abstract public class ActionGui extends Gui } /** - * Retreives the event handler matching the given name from a class (or any of its parents). - * @param klass The class to retreive the event handler from. + * Retrieves the event handler matching the given name from a class (or any of its parents). + * + * @param klass The class to retrieve the event handler from. * @param name The name of the action. * @return The event handler matching the action name, or null if none was found. */ - private Method getActionHandler(Class klass, String name) + private Method getActionHandler(Class klass, String name) { - Method callback = null; + Method callback; + do { try { - callback = klass.getDeclaredMethod(ACTION_HANDLER_NAME + name); + try + { + callback = klass.getDeclaredMethod(ACTION_HANDLER_NAME + name, InventoryClickEvent.class); + } + catch(NoSuchMethodException e) + { + callback = klass.getDeclaredMethod(ACTION_HANDLER_NAME + name); + } + callback.setAccessible(true); break; } @@ -286,8 +324,7 @@ abstract public class ActionGui extends Gui callback = null; klass = klass.getSuperclass(); } - - }while(klass != null); + } while (klass != null); return callback; } diff --git a/src/main/java/fr/moribus/imageonmap/guiproko/core/ExplorerGui.java b/src/main/java/fr/moribus/imageonmap/guiproko/core/ExplorerGui.java index 4d2bc41..a2f8909 100644 --- a/src/main/java/fr/moribus/imageonmap/guiproko/core/ExplorerGui.java +++ b/src/main/java/fr/moribus/imageonmap/guiproko/core/ExplorerGui.java @@ -27,9 +27,33 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +/** + * This class implements an exploration GUI, allowing users to see a set of data + * in a paginated view, and to manipulate it or get it (if the + * {@link fr.moribus.imageonmap.guiproko.core.ExplorerGui.Mode#CREATIVE Creative} mode + * is enabled for this GUI — enabled by default). + * + * This GUI supports both one- and two-dimensional contents; two-dimensional content is + * represented by a one-dimension list and a width, or by {@link #getViewItem(int, int)} + * if you override it (in this case you need to call {@link #setDataShape(int, int)} in the + * {@link #onUpdate()} method). + * + * @param The type of data this GUI will display. + * + * @author ProkopyL (main) and Amaury Carrade + */ abstract public class ExplorerGui extends ActionGui { - static protected enum Mode {READONLY, CREATIVE}; + /** + * The explorer GUI's reading mode. + * + * In creative mode (the default mode), the players are able to manipulate the content, get it + * inside their own inventory (without consumption, just like the creative mode), and whatever + * you want if you override some methods. + * + * In read-only mode, they are only able to browse the content. + */ + protected enum Mode {READONLY, CREATIVE} private T[] data; private boolean isData2D = false; @@ -48,21 +72,42 @@ abstract public class ExplorerGui extends ActionGui private int pageCountY; private Mode mode = Mode.CREATIVE; - + + /** + * Sets the displayed data. + * + * @param data The data. + * @param dataWidth The data's width, if this data is in two dimensions. + * In this case the data array will be read like a matrix, with + * lines stored in a consecutive way; the height is automatically + * calculated. + */ protected void setData(T[] data, int dataWidth) { this.data = data; if(dataWidth > 0) - setData(dataWidth, (int) Math.ceil((double)data.length / (double)dataWidth)); + setDataShape(dataWidth, (int) Math.ceil((double) data.length / (double) dataWidth)); } - - protected void setData(int dataWidth, int dataHeight) + + /** + * Sets the data's shape. Use this if you're providing data through + * {@link #getViewItem(int, int)}, as example. + * + * @param dataWidth The data's width. + * @param dataHeight The data's height. + */ + protected void setDataShape(int dataWidth, int dataHeight) { this.dataWidth = dataWidth; this.dataHeight = dataHeight; this.isData2D = dataWidth > 0; } - + + /** + * Sets the displayed data, assuming this data is in one dimension. + * + * @param data The data. + */ protected void setData(T[] data) { setData(data, 0); @@ -101,6 +146,7 @@ abstract public class ExplorerGui extends ActionGui { int start = currentPageX * viewSize; int max = Math.min(viewSize, data.length - start); + for(int i = 0; i < max; i++) { inventory.setItem(i, getViewItem(i + start)); @@ -118,10 +164,11 @@ abstract public class ExplorerGui extends ActionGui { for(int j = maxX; j --> 0;) { - inventory.setItem(i*INVENTORY_ROW_SIZE + j, getViewItem(j + startX, i + startY)); + inventory.setItem(i * INVENTORY_ROW_SIZE + j, getViewItem(j + startX, i + startY)); } } } + if(hasActions()) super.populate(inventory); } @@ -130,7 +177,7 @@ abstract public class ExplorerGui extends ActionGui { int slot = event.getRawSlot(); - //Clicked in the action bar + // Clicked in the action bar if(hasActions() && slot >= MAX_INVENTORY_SIZE - INVENTORY_ROW_SIZE && slot < MAX_INVENTORY_SIZE) @@ -146,7 +193,7 @@ abstract public class ExplorerGui extends ActionGui return; } - if(affectsGui(event))//The user clicked in its own inventory + if(affectsGui(event)) // The user clicked in its own inventory { switch(event.getAction()) { @@ -154,11 +201,14 @@ abstract public class ExplorerGui extends ActionGui case HOTBAR_MOVE_AND_READD: case HOTBAR_SWAP: case MOVE_TO_OTHER_INVENTORY: onActionPickup(event); break; + case PLACE_ALL: case PLACE_ONE: case PLACE_SOME: case SWAP_WITH_CURSOR: onActionPut(event); break; + case DROP_ALL_CURSOR: case DROP_ONE_CURSOR: break; + default: event.setCancelled(true); } @@ -195,11 +245,18 @@ abstract public class ExplorerGui extends ActionGui } event.setCancelled(true); + if(mode.equals(Mode.READONLY)) return; if(!onPutItem(event.getOldCursor())) return; + event.setCursor(new ItemStack(Material.AIR)); } - + + /** + * Triggered when a player clicks on the GUI to get an item. + * + * @param event The triggered event. + */ private void onActionPickup(InventoryClickEvent event) { int dataIndex = getDataIndex(event.getSlot()); @@ -209,16 +266,23 @@ abstract public class ExplorerGui extends ActionGui event.setCancelled(true); return; } + ItemStack pickedUpItem = getPickedUpItem(dataIndex); if(pickedUpItem == null || mode.equals(Mode.READONLY)) { event.setCancelled(true); return; } + event.setCurrentItem(pickedUpItem); GuiUtils.setItemLater(this, event.getSlot(), getViewItem(dataIndex)); } - + + /** + * Triggered when a player clicks on the GUI to place an item. + * + * @param event The triggered event. + */ private void onActionPut(InventoryClickEvent event) { event.setCancelled(true); @@ -226,7 +290,12 @@ abstract public class ExplorerGui extends ActionGui if(!onPutItem(event.getCursor())) return; event.setCursor(new ItemStack(Material.AIR)); } - + + /** + * Triggered when a player moves an item on the GUI. + * + * @param event The triggered event. + */ private void onActionMove(InventoryClickEvent event) { event.setCancelled(true); @@ -238,7 +307,6 @@ abstract public class ExplorerGui extends ActionGui @Override protected void onAfterUpdate() { - //Calculating page count if(data != null && data.length <= 0) { @@ -251,15 +319,17 @@ abstract public class ExplorerGui extends ActionGui } else if(!isData2D) { + int dataLength = (data == null) ? 0 : data.length; + viewWidth = INVENTORY_ROW_SIZE; - viewHeight = Math.min((int)Math.ceil((double)data.length / (double)viewWidth), + viewHeight = Math.min((int)Math.ceil((double)dataLength / (double)viewWidth), MAX_INVENTORY_COLUMN_SIZE); - if(hasActions() || data.length > MAX_INVENTORY_SIZE) + if(hasActions() || dataLength > MAX_INVENTORY_SIZE) viewHeight--; viewSize = viewWidth * viewHeight; - pageCountX = (int)Math.ceil((double)data.length / (double)viewSize); + pageCountX = (int)Math.ceil((double)dataLength / (double)viewSize); pageCountY = 1; } else @@ -329,53 +399,111 @@ abstract public class ExplorerGui extends ActionGui { if(i < 0 || i >= data.length) return null; + return data[i]; } - + + /** + * Returns the stack to display at the given index. + * + * @param i The index. + * @return The stack. + */ protected ItemStack getViewItem(int i) { return getViewItem(getData(i)); } - + + /** + * Returns the stack to display at the given coordinates. + * + * @param x The x-coordinate (left to right). + * @param y The y-coordinate (top to bottom). + * @return The stack. + */ protected ItemStack getViewItem(int x, int y) { return getViewItem(y * dataWidth + x); } - - protected ItemStack getViewItem(T data){return null;}; - + + /** + * Returns the ItemStack representation of the given piece of data. + * + * @param data The piece of data. + * @return The piece's representation. + */ + protected ItemStack getViewItem(T data) { return null; } + + private ItemStack getPickedUpItem(int dataIndex) { if(dataIndex < 0 || dataIndex >= data.length) return null; + return getPickedUpItem(getData(dataIndex)); } - - protected ItemStack getPickedUpItem(T data){return getViewItem(data);} - protected void onRightClick(T data){} - protected boolean onPutItem(ItemStack item){return true;} - + + /** + * Returns the stack the players will get when they try to take an item from + * the GUI, in {@link fr.moribus.imageonmap.guiproko.core.ExplorerGui.Mode#CREATIVE} + * mode. + * + * @param data The picked-up piece of data. + * @return The stack to pick-up ({@code null} to cancel the pick-up). + */ + protected ItemStack getPickedUpItem(T data) { return getViewItem(data); } + + /** + * Triggered when the player right-clicks an item on the GUI. + * + * @param data The right-clicked piece of data. + */ + protected void onRightClick(T data) {} + + /** + * Triggered when the player try to place an item inside the GUI. + * + * This will not place the item in the GUI, it's up to you to update the data and refresh + * the GUI if you need so. + * + * @param item The {@link ItemStack} the player is trying to put. + * @return {@code false} to cancel the placement; {@code true} to accept it. + */ + protected boolean onPutItem(ItemStack item) { return true; } + + /** + * Displays the next horizontal page, if possible. + */ public void next() { if(!canGoNext()) return; currentPageX++; refresh(); } - + + /** + * Displays the previous horizontal page, if possible. + */ public void previous() { if(!canGoPrevious()) return; currentPageX--; refresh(); } - + + /** + * Displays the previous vertical page, if possible. + */ public void up() { if(!canGoUp()) return; currentPageY--; refresh(); } - + + /** + * Displays the next vertical page, if possible. + */ public void down() { if(!canGoDown()) return; @@ -402,17 +530,40 @@ abstract public class ExplorerGui extends ActionGui { return currentPageY < pageCountY - 1; } - + + /** + * Returns the amount of horizontal pages. + * + * @return The pages' amount. + */ public int getPageCount() { return pageCountX; } - + + /** + * Returns the amount of vertical pages. + * This will always be 1 if the GUI is representing a one-dimensional data set. + * + * @return The pages' amount. + */ public int getVerticalPageCount() { return pageCountY; } - - protected Mode getMode() {return mode;} - protected void setMode(Mode mode) {this.mode = mode;} + + /** @return The GUI's manipulation mode. */ + protected Mode getMode() + { + return mode; + } + + /** + * Sets the GUI's manipulation mode. + * @param mode The mode. + */ + protected void setMode(Mode mode) + { + this.mode = mode; + } } diff --git a/src/main/java/fr/moribus/imageonmap/guiproko/core/Gui.java b/src/main/java/fr/moribus/imageonmap/guiproko/core/Gui.java index 0ff6ef5..5183229 100644 --- a/src/main/java/fr/moribus/imageonmap/guiproko/core/Gui.java +++ b/src/main/java/fr/moribus/imageonmap/guiproko/core/Gui.java @@ -18,16 +18,14 @@ package fr.moribus.imageonmap.guiproko.core; -import java.util.HashMap; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; -import org.bukkit.event.inventory.InventoryDragEvent; -import org.bukkit.inventory.Inventory; -import org.bukkit.plugin.Plugin; +import org.bukkit.*; +import org.bukkit.entity.*; +import org.bukkit.event.*; +import org.bukkit.event.inventory.*; +import org.bukkit.inventory.*; +import org.bukkit.plugin.*; + +import java.util.*; /** * This class provides the basic needs for chest-type GUIs. @@ -64,7 +62,8 @@ abstract public class Gui * If the inventory is currently open. */ private boolean open = false; - + + private void open(Player player) { this.player = player; @@ -73,7 +72,8 @@ abstract public class Gui player.openInventory(inventory); this.open = true; } - + + /* ===== Public API ===== */ /** @@ -94,7 +94,8 @@ abstract public class Gui { inventory = Bukkit.createInventory(player, size, title); populate(inventory); - if(isOpen())//Reopening the inventory + + if(isOpen()) // Reopening the inventory { player.closeInventory(); player.openInventory(inventory); @@ -125,32 +126,36 @@ abstract public class Gui /* ===== Protected API ===== */ /** - * Raised when the {@link Gui#update() } method is called. + * Raised when the {@link Gui#update()} method is called. * Use this method to update your internal data. */ - protected void onUpdate(){} + protected void onUpdate() {} /** - * Raised when the {@link Gui#update() } method is called, but before the inventory is populated. + * Raised when the {@link Gui#update()} method is called, but before the inventory is populated. * Use this method in a Gui subclass to analyze given data and set other parameters accordingly. */ - protected void onAfterUpdate(){} + protected void onAfterUpdate() {} /** * Called when the inventory needs to be (re)populated. + * * @param inventory The inventory to populate */ abstract protected void populate(Inventory inventory); /** * Raised when an action is performed on an item in the inventory. + * * @param event The click event data. */ abstract protected void onClick(InventoryClickEvent event); - + + /** * Raised when an drag is performed on the inventory. * The default behaviour is to cancel any event that affects the GUI. + * * @param event The drag event data. */ protected void onDrag(InventoryDragEvent event) @@ -159,18 +164,20 @@ abstract public class Gui } /** - * Returns if the given event affects the GUI's inventory + * Returns if the given event affects the GUI's inventory. + * * @param event The event to test - * @return true if the event's slot is in the GUI's inventory, - * false otherwise. + * @return {@code true} if the event's slot is in the GUI's inventory, + * {@code false} otherwise. */ static protected boolean affectsGui(InventoryClickEvent event) { return event.getRawSlot() < event.getInventory().getSize(); } - + /** - * Returns if the given event affects the GUI's inventory + * Returns if the given event affects the GUI's inventory. + * * @param event The event to test * @return true if any of the event's slots is in the GUI's inventory, * false otherwise. @@ -192,18 +199,19 @@ abstract public class Gui * Raised when the GUI is being closed. * Use this method to cleanup data. */ - protected void onClose(){}; - + protected void onClose() {} + + /* ===== Getters & Setters ===== */ - /** @return If the GUI is currently open or not.*/ - public boolean isOpen(){return open;} + /** @return If the GUI is currently open or not. */ + public boolean isOpen() { return open; } - /** @return The player this Gui instance is associated to.*/ - protected Player getPlayer(){return player;} + /** @return The player this Gui instance is associated to. */ + protected Player getPlayer() { return player; } - /** @return The size of the inventory.*/ - protected int getSize(){return size;} + /** @return The size of the inventory. */ + protected int getSize() { return size; } /** * Sets the new size of the inventory. @@ -217,8 +225,9 @@ abstract public class Gui this.size = Math.min(((int)(Math.ceil((double) size / INVENTORY_ROW_SIZE))) * INVENTORY_ROW_SIZE, MAX_INVENTORY_SIZE); } - /** @return The title of the inventory.*/ - protected String getTitle(){return title;} + /** @return The title of the inventory. */ + protected String getTitle() { return title; } + /** * Sets the new title of the inventory. * It will be applied on the next GUI update. @@ -226,9 +235,10 @@ abstract public class Gui */ protected void setTitle(String title){this.title = title;} - /** @return The underlying inventory, or null if the Gui has not been opened yet.*/ - public Inventory getInventory(){return inventory;} - + /** @return The underlying inventory, or null if the Gui has not been opened yet. */ + public Inventory getInventory() { return inventory; } + + /* ===== Static API ===== */ /** @@ -277,6 +287,7 @@ abstract public class Gui { close(owner); ((Gui)gui).open(owner);/* JAVA GENERICS Y U NO WORK */ + return gui; } @@ -287,11 +298,10 @@ abstract public class Gui static public void close(Player owner) { Gui openGui = openGuis.get(owner); - if(openGui == null) return; - - openGui.close(); + if(openGui != null) openGui.close(); } - + + /** * Implements a Bukkit listener for all GUI-related events. */ @@ -307,9 +317,9 @@ abstract public class Gui openGui.onDrag(event); } - + @EventHandler - public void onInventoryClick(InventoryClickEvent event) + public void onInventoryClick(InventoryClickEvent event) { if(!(event.getWhoClicked() instanceof Player)) return; Player owner = (Player) event.getWhoClicked(); @@ -318,9 +328,9 @@ abstract public class Gui openGui.onClick(event); } - + @EventHandler - public void onInventoryClose(InventoryCloseEvent event) + public void onInventoryClose(InventoryCloseEvent event) { if(!(event.getPlayer() instanceof Player)) return; Player owner = (Player) event.getPlayer(); diff --git a/src/main/java/fr/moribus/imageonmap/guiproko/core/GuiUtils.java b/src/main/java/fr/moribus/imageonmap/guiproko/core/GuiUtils.java index 1135ac1..022633e 100644 --- a/src/main/java/fr/moribus/imageonmap/guiproko/core/GuiUtils.java +++ b/src/main/java/fr/moribus/imageonmap/guiproko/core/GuiUtils.java @@ -18,131 +18,182 @@ package fr.moribus.imageonmap.guiproko.core; -import fr.moribus.imageonmap.ImageOnMap; -import fr.moribus.imageonmap.PluginLogger; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; +import fr.moribus.imageonmap.*; +import org.bukkit.*; +import org.bukkit.entity.*; +import org.bukkit.inventory.*; +import org.bukkit.inventory.meta.*; + +import java.lang.reflect.*; +import java.util.*; + /** * Various utility methods for GUIs. */ -abstract public class GuiUtils +abstract public class GuiUtils { - static private Method addItemFlagsMethod = null; - static private Object[] itemFlagValues = null; - - /** - * Initializes the GUI utilities. - * This method must be called on plugin enabling. - */ - static public void init() - { - try - { - Class itemFlagClass = Class.forName("org.bukkit.inventory.ItemFlag"); - Method valuesMethod = itemFlagClass.getDeclaredMethod("values"); - itemFlagValues = (Object[]) valuesMethod.invoke(null); - addItemFlagsMethod = ItemMeta.class.getMethod("addItemFlags", itemFlagClass); - addItemFlagsMethod.setAccessible(true); + static private Method addItemFlagsMethod = null; + static private Object[] itemFlagValues = null; - } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) { - // Not supported :c - } catch (InvocationTargetException e) { - PluginLogger.error("Exception occurred while looking for the ItemFlag API.", e); - } - } - - static public void hideItemAttributes(ItemMeta meta) - { - if(addItemFlagsMethod == null) return; - try - { - addItemFlagsMethod.invoke(meta, itemFlagValues); - } - catch (IllegalAccessException | InvocationTargetException ex) - { - PluginLogger.error("Exception occurred while invoking the ItemMeta.addItemFlags method.", ex); - } - } - - /** - * Stores the ItemStack at the given index of a GUI's inventory. - * The inventory is only updated the next time the Bukkit Scheduler runs (i.e. next server tick). - * - * @param gui The GUI to update - * @param slot The slot where to put the ItemStack - * @param item The ItemStack to set - */ - static public void setItemLater(Gui gui, int slot, ItemStack item) - { - Bukkit.getScheduler().scheduleSyncDelayedTask(ImageOnMap.getPlugin(), - new CreateDisplayItemTask(gui.getInventory(), item, slot)); - } - - static public ItemStack makeItem(Material material) - { - return makeItem(material, null, (List)null); - } - - static public ItemStack makeItem(Material material, String title) - { - return makeItem(material, title, (List)null); - } - - static public ItemStack makeItem(Material material, String title, String... loreLines) - { - return makeItem(material, title, Arrays.asList(loreLines)); - } - - static public ItemStack makeItem(Material material, String title, List loreLines) - { - return makeItem(new ItemStack(material), title, loreLines); - } - static public ItemStack makeItem(ItemStack itemStack, String title, List loreLines) - { - ItemMeta meta = itemStack.getItemMeta(); - meta.setDisplayName(title); - meta.setLore(loreLines); - if(itemStack.getType().equals(Material.MAP)) - hideItemAttributes(meta); - itemStack.setItemMeta(meta); - return itemStack; - } - - /** - * Implements a bukkit runnable that updates an inventory slot later. - */ - static private class CreateDisplayItemTask implements Runnable - { - private final Inventory inventory; - private final ItemStack item; - private final int slot; - - public CreateDisplayItemTask(Inventory inventory, ItemStack item, int slot) - { - this.inventory = inventory; - this.item = item; - this.slot = slot; - } - - @Override - public void run() - { - inventory.setItem(slot, item); - for(HumanEntity player : inventory.getViewers()) - { - ((Player)player).updateInventory(); - } - } - - } + /** + * Initializes the GUI utilities. This method must be called on plugin enabling. + */ + static public void init() + { + try + { + Class itemFlagClass = Class.forName("org.bukkit.inventory.ItemFlag"); + Method valuesMethod = itemFlagClass.getDeclaredMethod("values"); + itemFlagValues = (Object[]) valuesMethod.invoke(null); + addItemFlagsMethod = ItemMeta.class.getMethod("addItemFlags", itemFlagClass); + addItemFlagsMethod.setAccessible(true); + } + catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) + { + // Not supported :c + } + catch (InvocationTargetException e) + { + PluginLogger.error("Exception occurred while looking for the ItemFlag API.", e); + } + } + + /** + * Hides all the item attributes of the given {@link ItemMeta}. + * + * @param meta The {@link ItemMeta} to hide attributes from. + */ + static public void hideItemAttributes(ItemMeta meta) + { + if (addItemFlagsMethod == null) return; + try + { + addItemFlagsMethod.invoke(meta, itemFlagValues); + } + catch (IllegalAccessException | InvocationTargetException ex) + { + PluginLogger.error("Exception occurred while invoking the ItemMeta.addItemFlags method.", ex); + } + } + + + /** + * Stores the ItemStack at the given index of a GUI's inventory. The inventory is only updated + * the next time the Bukkit Scheduler runs (i.e. next server tick). + * + * @param gui The GUI to update + * @param slot The slot where to put the ItemStack + * @param item The ItemStack to set + */ + static public void setItemLater(Gui gui, int slot, ItemStack item) + { + Bukkit.getScheduler().scheduleSyncDelayedTask(ImageOnMap.getPlugin(), + new CreateDisplayItemTask(gui.getInventory(), item, slot)); + } + + /** + * One-liner to construct an {@link ItemStack}. + * + * @param material The stack's material. + * + * @return The constructed {@link ItemStack}. + */ + static public ItemStack makeItem(Material material) + { + return makeItem(material, null, (List) null); + } + + /** + * One-liner to construct an {@link ItemStack}. + * + * @param material The stack's material. + * @param title The stack's title. + * + * @return The constructed {@link ItemStack}. + */ + static public ItemStack makeItem(Material material, String title) + { + return makeItem(material, title, (List) null); + } + + /** + * One-liner to construct an {@link ItemStack}. + * + * @param material The stack's material. + * @param title The stack's title. + * @param loreLines The stack's lore lines. + * + * @return The constructed {@link ItemStack}. + */ + static public ItemStack makeItem(Material material, String title, String... loreLines) + { + return makeItem(material, title, Arrays.asList(loreLines)); + } + + /** + * One-liner to construct an {@link ItemStack}. + * + * @param material The stack's material. + * @param title The stack's title. + * @param loreLines The stack's lore lines. + * + * @return The constructed {@link ItemStack}. + */ + static public ItemStack makeItem(Material material, String title, List loreLines) + { + return makeItem(new ItemStack(material), title, loreLines); + } + + /** + * One-liner to update an {@link ItemStack}'s {@link ItemMeta}. + * + * If the stack is a map, it's attributes will be hidden. + * + * @param itemStack The original {@link ItemStack}. This stack will be directly modified. + * @param title The stack's title. + * @param loreLines A list containing the stack's lines. + * + * @return The same {@link ItemStack}, but with an updated {@link ItemMeta}. + */ + static public ItemStack makeItem(ItemStack itemStack, String title, List loreLines) + { + ItemMeta meta = itemStack.getItemMeta(); + meta.setDisplayName(title); + meta.setLore(loreLines); + + if (itemStack.getType().equals(Material.MAP)) + hideItemAttributes(meta); + + itemStack.setItemMeta(meta); + return itemStack; + } + + /** + * Implements a bukkit runnable that updates an inventory slot later. + */ + static private class CreateDisplayItemTask implements Runnable + { + private final Inventory inventory; + private final ItemStack item; + private final int slot; + + public CreateDisplayItemTask(Inventory inventory, ItemStack item, int slot) + { + this.inventory = inventory; + this.item = item; + this.slot = slot; + } + + @Override + public void run() + { + inventory.setItem(slot, item); + for (HumanEntity player : inventory.getViewers()) + { + ((Player) player).updateInventory(); + } + } + + } } diff --git a/src/main/java/fr/moribus/imageonmap/guiproko/list/MapDetailGui.java b/src/main/java/fr/moribus/imageonmap/guiproko/list/MapDetailGui.java index ae437ca..764364c 100644 --- a/src/main/java/fr/moribus/imageonmap/guiproko/list/MapDetailGui.java +++ b/src/main/java/fr/moribus/imageonmap/guiproko/list/MapDetailGui.java @@ -41,7 +41,7 @@ public class MapDetailGui extends ExplorerGui protected void onUpdate() { setTitle("Details for map " + map.getName()); - setData(map.getColumnCount(), map.getRowCount()); + setDataShape(map.getColumnCount(), map.getRowCount()); } }