Java tutorial
/* * This document is a part of the source code and related artifacts for StilesLib, an open source library that * provides a set of commonly-used functions for Bukkit plugins. * * http://github.com/mstiles92/StilesLib * * Copyright (c) 2014 Matthew Stiles (mstiles92) * * Licensed under the Common Development and Distribution License Version 1.0 * You may not use this file except in compliance with this License. * * You may obtain a copy of the CDDL-1.0 License at http://opensource.org/licenses/CDDL-1.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the license. */ package com.mstiles92.plugins.stileslib.menu.menus; import com.google.common.base.Preconditions; import com.mstiles92.plugins.stileslib.menu.MenuInventoryHolder; import com.mstiles92.plugins.stileslib.menu.events.MenuClickEvent; import com.mstiles92.plugins.stileslib.menu.items.MenuItem; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.Inventory; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; /** * A menu with clickable icons to be displayed to a Player in an Inventory. */ public class Menu { private Plugin plugin; private String title; private int numRows; private MenuItem[] contents; private Menu previousMenu; /** * Create a basic Menu with the specified title and size. * * @param plugin the Plugin that is creating this Menu * @param title the title to be shown to the Player in the open Inventory * @param numRows the number of rows that should be present in the Inventory, must be between 1 and 6 */ public Menu(Plugin plugin, String title, int numRows) { Preconditions.checkNotNull(plugin, "Plugin must not be null!"); Preconditions.checkNotNull(title, "Menu title must not be null!"); Preconditions.checkArgument(numRows > 0 && numRows < 7, "Number of rows in menu must be between 1 and 6! Was: %s", numRows); this.plugin = plugin; this.title = title; this.numRows = numRows; contents = new MenuItem[numRows * 9]; } /** * Get the Plugin that created this Menu. * * @return the plugin that created this Menu */ public Plugin getPlugin() { return plugin; } /** * Get the title of the Menu which will be displayed in the open Inventory. * * @return the title of the Menu */ public String getTitle() { return title; } /** * Get the number of rows in the Menu. * * @return the number of rows in the Menu */ public int getNumRows() { return numRows; } /** * Set a MenuItem to a specific position in the Menu. The position is zero-based, so the top-left slot is 0, the * top-right is 8, the far-left in the second row is 9, and so on. * * @param position the zero-based position in which to put the MenuItem * @param item the MenuItem to put in the Menu */ public void setItem(int position, MenuItem item) { Preconditions.checkElementIndex(position, contents.length); contents[position] = item; } /** * Get the Menu which opened this Menu, if this Menu was opened by another. * * @return the Menu which opened this Menu if this Menu was opened by another, null if it was not */ public Menu getPreviousMenu() { return previousMenu; } /** * Set the Menu that opened this Menu. * * @param previousMenu the Menu that opened this Menu. */ public void setPreviousMenu(Menu previousMenu) { this.previousMenu = previousMenu; } /** * Open and display this Menu to a Player. * * @param player the Player to display the Menu to */ public void open(Player player) { Preconditions.checkNotNull(player, "Player opening a menu inventory must not be null!"); Preconditions.checkState(player.isOnline(), "Player opening a menu inventory must be online!"); Inventory inventory = Bukkit.createInventory( new MenuInventoryHolder(this, Bukkit.createInventory(player, numRows * 9)), numRows * 9, title); applyMenuToInventory(inventory, player); player.openInventory(inventory); } /** * Handle the Player clicking with this Menu's Inventory open. * * @param event the InventoryClickEvent fired by the Player clicking a slot in this Menu's Inventory. */ public void handleClick(InventoryClickEvent event) { if (!event.getClick().equals(ClickType.LEFT)) { return; } int clickedSlot = event.getRawSlot(); if (clickedSlot >= 0 && clickedSlot < numRows * 9 && contents[clickedSlot] != null) { Player player = (Player) event.getWhoClicked(); if (contents[clickedSlot].visibleTo(player)) { MenuClickEvent menuClickEvent = new MenuClickEvent(player, this); contents[clickedSlot].onClick(menuClickEvent); switch (menuClickEvent.getResult()) { case REFRESH: refreshMenu(player); break; case CLOSE: closeMenuLater(player); break; case SUBMENU: Menu submenu = menuClickEvent.getSubmenu(); Preconditions.checkNotNull(submenu, "Result was set to SUBMENU, but no submenu was specified by MenuClickEvent.setSubmenu(Menu)"); submenu.setPreviousMenu(this); openMenuLater(submenu, player); break; case PREVIOUS: Preconditions.checkNotNull(previousMenu, "Result was set to PREVIOUS when there was no menu to go back to!"); openMenuLater(previousMenu, player); break; } } } } /** * Refresh all items in this Menu's Inventory, to reflect any changes that may have been made to the contents. * * @param player the Player who is currently viewing the Menu */ @SuppressWarnings("deprecation") private void refreshMenu(Player player) { if (player.getOpenInventory() != null) { Inventory inventory = player.getOpenInventory().getTopInventory(); if (inventory.getHolder() instanceof MenuInventoryHolder && ((MenuInventoryHolder) inventory.getHolder()).getMenu().equals(this)) { applyMenuToInventory(inventory, player); player.updateInventory(); } } } /** * Apply the current Menu's contents to the provided Inventory. * * @param inventory the Inventory to apply the current Menu's contents to * @param player the Player that the MenuItem will use to check for visibility and to get the display icon */ private void applyMenuToInventory(Inventory inventory, Player player) { inventory.clear(); for (int i = 0; i < contents.length; i++) { if (contents[i] != null && contents[i].visibleTo(player)) { inventory.setItem(i, contents[i].getDisplayIcon(player)); } } } /** * Close the specified Player's currently opened Inventory one tick later. * * @param player the Player whose currently open Inventory will be closed */ private void closeMenuLater(final Player player) { BukkitRunnable runnable = new BukkitRunnable() { @Override public void run() { player.closeInventory(); } }; runnable.runTaskLater(plugin, 1); } /** * Open the specified Menu's Inventory to the specified Player two ticks later. * * @param menu the Menu that will be represented by the Inventory to be opened * @param player the Player to who the Inventory will be opened */ private void openMenuLater(final Menu menu, final Player player) { BukkitRunnable runnable = new BukkitRunnable() { @Override public void run() { menu.open(player); } }; runnable.runTaskLater(plugin, 2); } }