/*
* This file is part of NucleusFramework for Bukkit, licensed under the MIT License (MIT).
*
* Copyright (c) JCThePants (www.jcwhatever.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.jcwhatever.nucleus.views.menu;
import com.jcwhatever.nucleus.managed.items.serializer.InvalidItemStackStringException;
import com.jcwhatever.nucleus.utils.MetaKey;
import com.jcwhatever.nucleus.utils.PreCon;
import com.jcwhatever.nucleus.utils.items.ItemStackUtils;
import com.jcwhatever.nucleus.utils.materials.NamedMaterialData;
import com.jcwhatever.nucleus.utils.text.TextUtils;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.MaterialData;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* A utility class to build {@link MenuItem}'s.
*/
public class MenuItemBuilder {
private ItemStack _itemStack;
private MaterialData _materialData;
private Integer _amount;
private CharSequence _title;
private CharSequence _description;
private Map<Object, Object> _meta;
private List<Runnable> _onClick;
/**
* Constructor.
*
* @param itemStack The {@link org.bukkit.inventory.ItemStack} that represents the menu item.
*/
public MenuItemBuilder(ItemStack itemStack) {
PreCon.notNull(itemStack);
_itemStack = itemStack;
}
/**
* Constructor.
*
* @param material The item {@link org.bukkit.Material}.
*/
public MenuItemBuilder(Material material) {
PreCon.notNull(material);
_materialData = new MaterialData(material);
}
/**
* Constructor.
*
* @param materialData The item {@link org.bukkit.material.MaterialData}.
*/
public MenuItemBuilder(MaterialData materialData) {
PreCon.notNull(materialData);
_materialData = materialData.clone();
}
/**
* Constructor.
*
* @param materialName The name of the material or serialized item stack string.
*/
public MenuItemBuilder(String materialName) {
PreCon.notNullOrEmpty(materialName);
_materialData = NamedMaterialData.get(materialName);
if (_materialData == null) {
try {
// try parsing serialized item stack
ItemStack[] itemStacks = ItemStackUtils.parse(materialName);
if (itemStacks != null && itemStacks.length == 1) {
_itemStack = itemStacks[0];
return;
}
} catch (InvalidItemStackStringException ignore) {}
throw new RuntimeException(materialName + " is not a recognized material.");
}
}
/**
* Set the menu item title.
*
* @param title The title text.
* @param args Optional title format arguments.
*
* @return Self for chaining.
*/
public MenuItemBuilder title(CharSequence title, Object... args) {
PreCon.notNull(title);
_title = TextUtils.format(title, args);
return this;
}
/**
* Set the menu item description.
*
* @param description The description text.
* @param args Optional description format arguments.
*
* @return Self for chaining.
*/
public MenuItemBuilder description(CharSequence description, Object... args) {
PreCon.notNull(description);
_description = TextUtils.format(description, args);
return this;
}
/**
* Set the amount.
*
* @param amount The amount.
*
* @return Self for chaining.
*/
public MenuItemBuilder amount(int amount) {
_amount = amount;
return this;
}
/**
* Add meta data to the menu item.
*
* @param key The meta key.
* @param value The meta value.
*
* @param <T> The meta value type.
*
* @return Self for chaining.
*/
public <T> MenuItemBuilder meta(MetaKey<T> key, T value) {
PreCon.notNull(key);
if (_meta == null) {
_meta = new HashMap<>(7);
}
_meta.put(key, value);
return this;
}
/**
* Add an onClick handler to the menu item.
*
* @param onClick The onClick handler.
*
* @return Self for chaining.
*/
public MenuItemBuilder onClick(final Runnable onClick) {
PreCon.notNull(onClick);
if (_onClick == null)
_onClick = new ArrayList<>(3);
// encapsulate handler to prevent exceptions caused by script objects
// that do not have a hashCode or equals method.
_onClick.add(new Runnable() {
@Override
public void run() {
onClick.run();
}
});
return this;
}
/**
* Build and return a new {@link MenuItem}.
*
* @param slot The inventory slot the menu item will be placed in.
*/
public MenuItem build(int slot) {
if (_itemStack == null) {
_itemStack = new ItemStack(_materialData.getItemType());
_itemStack.setData(_materialData);
}
MenuItem item = createMenuItem(slot, _itemStack.clone(), _meta, _onClick);
if (_amount != null)
item.setAmount(_amount);
if (_title != null)
item.setTitle(_title);
if (_description != null)
item.setDescription(_description);
return item;
}
protected MenuItem createMenuItem(int slot, ItemStack itemStack,
@Nullable Map<Object, Object> meta,
@Nullable List<Runnable> onClick) {
MenuItem menuItem = new MenuItem(slot, itemStack);
if (meta != null)
menuItem.getMeta().copyAll(meta);
if (onClick != null) {
for (Runnable runnable : onClick) {
menuItem.onClick(runnable);
}
}
return menuItem;
}
}