package me.desht.scrollingmenusign.views;
import me.desht.dhutils.MiscUtil;
import me.desht.scrollingmenusign.SMSException;
import me.desht.scrollingmenusign.SMSMenu;
import me.desht.scrollingmenusign.SMSValidate;
import me.desht.scrollingmenusign.ScrollingMenuSign;
import me.desht.scrollingmenusign.enums.ViewJustification;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import java.util.List;
import java.util.Observable;
/**
* This view draws menus on signs.
*/
public class SMSSignView extends SMSGlobalScrollableView {
/**
* Create a new sign view object.
*
* @param name Unique name for this view.
* @param menu The SMSMenu object to attach this view to.
* @param loc The location of this view's sign
* @throws SMSException if the given location is not suitable for this view
*/
public SMSSignView(String name, SMSMenu menu, Location loc) throws SMSException {
super(name, menu);
addLocation(loc);
}
/**
* Create a new sign view object with no registered location. A location
* which contains a sign must be added with @see #addLocation(Location) before
* this view is useful.
*
* @param name Unique name for this view.
* @param menu The SMSMenu object to attach this view to.
*/
public SMSSignView(String name, SMSMenu menu) {
super(name, menu);
}
/**
* Create a new sign view object. Equivalent to calling SMSSignView(null, menu, loc). The
* view's name will be automatically generated, based on the menu name.
*
* @param menu The SMSMenu object to attach this view to.
* @param loc The location of this view's sign
* @throws SMSException if the given location is not suitable for this view
*/
public SMSSignView(SMSMenu menu, Location loc) throws SMSException {
this(null, menu, loc);
}
/* (non-Javadoc)
* @see me.desht.scrollingmenusign.views.SMSView#addLocation(org.bukkit.Location)
*/
@Override
public void addLocation(Location loc) throws SMSException {
Block b = loc.getBlock();
SMSValidate.isTrue(b.getType() == Material.WALL_SIGN || b.getType() == Material.SIGN_POST,
"Location " + MiscUtil.formatLocation(loc) + " does not contain a sign.");
super.addLocation(loc);
}
/* (non-Javadoc)
* @see me.desht.scrollingmenusign.views.SMSScrollableView#update(java.util.Observable, java.lang.Object)
*/
@Override
public void update(Observable menu, Object arg1) {
super.update(menu, arg1);
repaintAll();
}
@Override
public void onDeleted(boolean permanent) {
super.onDeleted(permanent);
if (permanent) {
Sign sign = getSign();
if (sign != null) {
for (int i = 0; i < SIGN_LINES; i++) {
sign.setLine(i, "");
}
sign.update();
}
}
}
private void repaintAll() {
Sign sign = getSign();
if (sign != null) {
String[] lines = buildSignText(getScrollPos());
for (int i = 0; i < lines.length; i++) {
sign.setLine(i, lines[i]);
}
sign.update();
setDirty(false);
}
}
private String[] buildSignText(int scrollPos) {
String[] res = new String[SIGN_LINES];
List<String> title = splitTitle(null);
// first line (or two) of the sign is the menu title
for (int i = 0; i < title.size(); i++) {
res[i] = String.format(makePrefix("", getTitleJustification()), title.get(i));
}
String prefixNotSel = ScrollingMenuSign.getInstance().getConfigCache().getPrefixNotSelected();
String prefixSel = ScrollingMenuSign.getInstance().getConfigCache().getPrefixSelected();
ViewJustification ij = getItemJustification();
int pageSize = res.length - title.size();
int menuSize = getActiveMenuItemCount(null);
switch (getScrollType()) {
case SCROLL:
// line 2-4 are the menu items around the current menu position
// line 3 is the current position
if (title.size() < 2) {
res[1] = String.format(makePrefix(prefixNotSel, ij), getLine2Item(scrollPos));
}
res[2] = String.format(makePrefix(prefixSel, ij), getLine3Item(scrollPos));
res[3] = String.format(makePrefix(prefixNotSel, ij), getLine4Item(scrollPos));
break;
case PAGE:
int pageNum = (scrollPos - 1) / pageSize;
for (int j = 0, pos = (pageNum * pageSize) + 1; j < pageSize && pos <= menuSize; j++, pos++) {
String pre = pos == scrollPos ? prefixSel : prefixNotSel;
res[j + title.size()] = String.format(makePrefix(pre, ij), getActiveItemLabel(null, pos));
}
break;
}
return res;
}
private String getLine2Item(int pos) {
if (getActiveMenuItemCount(null) < 3) {
return "";
}
int prevPos = pos - 1;
if (prevPos < 1) {
prevPos = getActiveMenuItemCount(null);
}
return getActiveItemLabel(null, prevPos);
}
private String getLine3Item(int pos) {
if (getActiveMenuItemCount(null) < 1) {
return "";
}
return getActiveItemLabel(null, pos);
}
private String getLine4Item(int pos) {
if (getActiveMenuItemCount(null) < 2)
return "";
int nextPos = pos + 1;
if (nextPos > getActiveMenuItemCount(null)) {
nextPos = 1;
}
return getActiveItemLabel(null, nextPos);
}
private String makePrefix(String prefix, ViewJustification just) {
int l = SIGN_WIDTH - prefix.length();
String s = "";
switch (just) {
case LEFT:
s = prefix + "%1$-" + l + "s";
break;
case CENTER:
s = prefix + "%1$s";
break;
case RIGHT:
s = prefix + "%1$" + l + "s";
break;
default:
break;
}
return s;
}
/**
* Get the actual Bukkit Sign object for this view.
*
* @return The Sign object
*/
private Sign getSign() {
if (getLocations().isEmpty())
return null;
Location loc = getLocationsArray()[0];
Block b = loc.getBlock();
if (b.getType() != Material.SIGN_POST && b.getType() != Material.WALL_SIGN) {
return null;
}
return (Sign) b.getState();
}
@Override
public String toString() {
Location[] locs = getLocationsArray();
return "sign @ " + (locs.length == 0 ? "NONE" : MiscUtil.formatLocation(getLocationsArray()[0]));
}
/* (non-Javadoc)
* @see me.desht.scrollingmenusign.views.SMSView#getType()
*/
@Override
public String getType() {
return "sign";
}
/* (non-Javadoc)
* @see me.desht.scrollingmenusign.views.SMSScrollableView#getLineLength()
*/
@Override
protected int getLineLength() {
return SIGN_WIDTH;
}
/* (non-Javadoc)
* @see me.desht.scrollingmenusign.views.SMSScrollableView#getHardMaxTitleLines()
*/
@Override
protected int getHardMaxTitleLines() {
return 2;
}
}