mirror of
https://github.com/zDevelopers/ImageOnMap.git
synced 2024-11-25 11:35:35 +01:00
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.
This commit is contained in:
parent
efd62283ea
commit
80089c7bf5
@ -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<? extends ActionGui> guiClass = this.getClass();
|
||||
|
||||
@ -58,12 +57,14 @@ abstract public class ActionGui extends Gui
|
||||
* their position in the inventory.
|
||||
*/
|
||||
private final HashMap<Integer, Action> 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;
|
||||
}
|
||||
|
@ -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 <T> The type of data this GUI will display.
|
||||
*
|
||||
* @author ProkopyL (main) and Amaury Carrade
|
||||
*/
|
||||
abstract public class ExplorerGui<T> 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<T> 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<T> 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<T> 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<T> 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<T> 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<T> 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<T> 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<T> 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<T> 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<T> extends ActionGui
|
||||
@Override
|
||||
protected void onAfterUpdate()
|
||||
{
|
||||
|
||||
//Calculating page count
|
||||
if(data != null && data.length <= 0)
|
||||
{
|
||||
@ -251,15 +319,17 @@ abstract public class ExplorerGui<T> 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<T> 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<T> 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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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<String>)null);
|
||||
}
|
||||
|
||||
static public ItemStack makeItem(Material material, String title)
|
||||
{
|
||||
return makeItem(material, title, (List<String>)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<String> loreLines)
|
||||
{
|
||||
return makeItem(new ItemStack(material), title, loreLines);
|
||||
}
|
||||
static public ItemStack makeItem(ItemStack itemStack, String title, List<String> 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<String>) 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<String>) 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<String> 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<String> 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ public class MapDetailGui extends ExplorerGui<Void>
|
||||
protected void onUpdate()
|
||||
{
|
||||
setTitle("Details for map " + map.getName());
|
||||
setData(map.getColumnCount(), map.getRowCount());
|
||||
setDataShape(map.getColumnCount(), map.getRowCount());
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user