/*
* Copyright (c) CovertJaguar, 2014 http://railcraft.info
*
* This code is the property of CovertJaguar
* and may only be used with explicit written
* permission unless otherwise specified on the
* license page at http://railcraft.info/wiki/info:license.
*/
package mods.railcraft.client.gui;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import mods.railcraft.client.gui.buttons.GuiBetterButton;
import mods.railcraft.client.gui.buttons.GuiButtonRoutingTableNextPage;
import mods.railcraft.common.core.Railcraft;
import mods.railcraft.common.core.RailcraftConstants;
import mods.railcraft.common.items.ItemRoutingTable;
import mods.railcraft.common.plugins.forge.LocalizationPlugin;
import mods.railcraft.common.util.inventory.InvTools;
import mods.railcraft.common.util.network.PacketCurrentItemNBT;
import mods.railcraft.common.util.network.PacketDispatcher;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ChatAllowedCharacters;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
@SideOnly(Side.CLIENT)
public class GuiRoutingTable extends GuiScreen {
public static final ResourceLocation TEXTURE = new ResourceLocation(RailcraftConstants.GUI_TEXTURE_FOLDER + "routing_table.png");
public static final int MANUAL_PAGES = 7;
public static final int MAX_PAGES = 50;
public static final int WRAP_WIDTH = 226;
/**
* The player editing the book
*/
private final EntityPlayer player;
private final ItemStack bookStack;
/**
* Whether the book is signed or can still be edited
*/
private final boolean editable = true;
private boolean bookModified;
private boolean editingTitle;
private boolean readingManual;
/**
* Update ticks since the gui was opened
*/
private int updateCount;
private final int bookImageWidth = 256;
private final int bookImageHeight = 192;
private int currPage, currLine, currChar;
private final List<List<String>> bookPages;
private String bookTitle = "";
private GuiButtonRoutingTableNextPage buttonNextPage;
private GuiButtonRoutingTableNextPage buttonPreviousPage;
private GuiBetterButton buttonDone;
private GuiBetterButton buttonSign;
private GuiBetterButton buttonHelp;
public GuiRoutingTable(EntityPlayer player, ItemStack stack) {
this.player = player;
this.bookStack = stack;
List<List<String>> pages = ItemRoutingTable.getPages(stack);
if (pages == null) {
bookPages = new LinkedList<List<String>>();
initPages();
} else {
bookPages = pages;
if (bookPages.isEmpty())
initPages();
}
if (stack.hasTagCompound()) {
NBTTagCompound nbt = stack.getTagCompound();
bookTitle = nbt.getString("title");
}
}
private void initPages() {
List<String> page = new LinkedList<String>();
bookPages.add(page);
page.add("");
}
/**
* Called from the main game loop to update the screen.
*/
@Override
public void updateScreen() {
super.updateScreen();
++this.updateCount;
}
/**
* Adds the buttons (and other controls) to the screen in question.
*/
@Override
public void initGui() {
super.initGui();
this.buttonList.clear();
Keyboard.enableRepeatEvents(true);
if (editable) {
List<GuiBetterButton> buttons = new ArrayList<GuiBetterButton>();
buttons.add(buttonSign = new GuiBetterButton(3, 0, 4 + bookImageHeight, 65, LocalizationPlugin.translate("railcraft.gui.routing.table.name")));
buttons.add(buttonHelp = new GuiBetterButton(4, 0, 4 + bookImageHeight, 65, LocalizationPlugin.translate("railcraft.gui.help")));
buttons.add(buttonDone = new GuiBetterButton(0, 0, 4 + bookImageHeight, 65, StatCollector.translateToLocal("gui.done")));
GuiTools.newButtonRowAuto(buttonList, width / 2 - 100, 200, buttons);
} else
buttonList.add(buttonDone = new GuiBetterButton(0, width / 2 - 100, 4 + bookImageHeight, 200, StatCollector.translateToLocal("gui.done")));
int xOffset = (width - bookImageWidth) / 2;
byte yOffset = 2;
buttonList.add(buttonNextPage = new GuiButtonRoutingTableNextPage(1, xOffset + 200, yOffset + 154, true));
buttonList.add(buttonPreviousPage = new GuiButtonRoutingTableNextPage(2, xOffset + 30, yOffset + 154, false));
updateButtons();
}
/**
* Called when the screen is unloaded. Used to disable keyboard repeat
* events
*/
@Override
public void onGuiClosed() {
Keyboard.enableRepeatEvents(false);
}
private int getMaxPages() {
if (readingManual)
return MANUAL_PAGES;
if (editingTitle)
return 0;
return MAX_PAGES;
}
private void updateButtons() {
buttonNextPage.visible = !editingTitle && (currPage < getMaxPages() - 1);
buttonPreviousPage.visible = !editingTitle && currPage > 0;
buttonHelp.displayString = readingManual ? StatCollector.translateToLocal("gui.back") : LocalizationPlugin.translate("railcraft.gui.help");
if (editable)
buttonSign.displayString = editingTitle ? StatCollector.translateToLocal("gui.back") : LocalizationPlugin.translate("railcraft.gui.routing.table.name");
}
private void sendBookToServer() {
if (this.editable && this.bookModified) {
ItemRoutingTable.setPages(bookStack, bookPages);
NBTTagCompound nbt = InvTools.getItemData(bookStack);
nbt.setString("author", Railcraft.proxy.getPlayerUsername(player));
if (!bookTitle.equals(""))
nbt.setString("title", bookTitle);
PacketCurrentItemNBT pkt = new PacketCurrentItemNBT(player, bookStack);
PacketDispatcher.sendToServer(pkt);
}
}
private void cleanEmptyLines() {
Iterator<List<String>> pageIt = bookPages.iterator();
while (pageIt.hasNext()) {
List<String> page = pageIt.next();
Iterator<String> lineIt = page.iterator();
while (lineIt.hasNext()) {
String line = lineIt.next();
if (line.equals(""))
lineIt.remove();
}
if (page.isEmpty())
pageIt.remove();
}
}
/**
* Fired when a control is clicked. This is the equivalent of
* ActionListener.actionPerformed(ActionEvent e).
*/
@Override
protected void actionPerformed(GuiButton button) {
if (button.enabled) {
if (button == buttonDone) {
this.mc.displayGuiScreen((GuiScreen) null);
this.sendBookToServer();
} else if (button == buttonSign) {
editingTitle = !editingTitle;
readingManual = false;
currPage = 0;
currLine = 0;
currChar = 0;
} else if (button == buttonHelp) {
readingManual = !readingManual;
editingTitle = false;
currPage = 0;
currLine = 0;
currChar = 0;
} else if (button == buttonNextPage) {
if (readingManual) {
if (currPage < MANUAL_PAGES - 1) {
currPage++;
currLine = 0;
currChar = 0;
}
} else if (currPage < bookPages.size() - 1) {
currPage++;
currLine = 0;
currChar = 0;
} else if (editable) {
addNewPage();
if (currPage < bookPages.size() - 1) {
currPage++;
currLine = 0;
currChar = 0;
}
}
} else if (button == buttonPreviousPage)
if (currPage > 0) {
currPage--;
currLine = 0;
currChar = 0;
}
this.updateButtons();
}
}
private void addNewPage() {
if (bookPages.size() < 50) {
List<String> page = new LinkedList<String>();
page.add("");
bookPages.add(page);
bookModified = true;
}
}
/**
* Fired when a key is typed. This is the equivalent of
* KeyListener.keyTyped(KeyEvent e).
*/
@Override
protected void keyTyped(char c, int key) {
super.keyTyped(c, key);
if (editable && !readingManual)
if (this.editingTitle)
this.keyTypedInTitle(c, key);
else
this.keyTypedInBook(c, key);
}
/**
* Processes keystrokes when editing the text of a book
*/
private void keyTypedInBook(char c, int key) {
switch (c) {
case 22:
this.addToBook(GuiScreen.getClipboardString());
return;
}
switch (key) {
case Keyboard.KEY_BACK: {
String text = getLine(currLine);
if (text.length() > 0 && currChar > 0)
setLine(currPage, currLine, text.substring(0, currChar - 1) + text.substring(currChar--));
else if (currLine > 0) {
List<String> page = getPage(currPage);
page.remove(currLine--);
currChar = getLine(currLine).length();
}
return;
}
case Keyboard.KEY_DELETE: {
String text = getLine(currLine);
if (currChar < text.length()) {
setLine(currPage, currLine, text.substring(0, currChar) + text.substring(currChar + 1));
return;
}
List<String> page = getPage(currPage);
if (currLine < page.size() - 1) {
if (text.length() == 0) {
page.remove(currLine);
currChar = 0;
return;
}
text = getLine(currLine + 1);
if (text.length() == 0) {
page.remove(currLine + 1);
return;
}
}
return;
}
case Keyboard.KEY_RETURN: {
List<String> page = getPage(currPage);
if (page.size() < ItemRoutingTable.LINES_PER_PAGE) {
String line = getLine(currLine);
setLine(currPage, currLine, line.substring(0, currChar));
page.add(++currLine, line.substring(currChar));
currChar = 0;
}
return;
}
case Keyboard.KEY_END: {
currChar = getLine(currLine).length();
return;
}
case Keyboard.KEY_HOME: {
currChar = 0;
return;
}
case Keyboard.KEY_NEXT: {
currLine = getPage(currPage).size() - 1;
currChar = Math.min(currChar, getLine(currLine).length());
return;
}
case Keyboard.KEY_PRIOR: {
currLine = 0;
currChar = Math.min(currChar, getLine(currLine).length());
return;
}
case Keyboard.KEY_DOWN: {
List<String> page = getPage(currPage);
if (currLine < page.size() - 1)
currChar = getLine(++currLine).length();
return;
}
case Keyboard.KEY_UP: {
if (currLine > 0)
currChar = getLine(--currLine).length();
return;
}
case Keyboard.KEY_RIGHT: {
String line = getLine(currLine);
if (currChar < line.length())
currChar++;
return;
}
case Keyboard.KEY_LEFT: {
if (currChar > 0)
currChar--;
return;
}
}
if (ChatAllowedCharacters.isAllowedCharacter(c)) {
String text = getLine(currLine);
if (text.length() < ItemRoutingTable.LINE_LENGTH) {
StringBuilder builder = new StringBuilder(text);
setLine(currPage, currLine, builder.insert(currChar++, c).toString());
}
}
}
private void keyTypedInTitle(char c, int key) {
switch (key) {
case Keyboard.KEY_BACK:
if (bookTitle.length() > 0) {
bookTitle = bookTitle.substring(0, bookTitle.length() - 1);
updateButtons();
}
return;
case Keyboard.KEY_RETURN:
if (bookTitle.length() > 0) {
sendBookToServer();
mc.displayGuiScreen((GuiScreen) null);
}
return;
default:
if (this.bookTitle.length() < 16 && ChatAllowedCharacters.isAllowedCharacter(c)) {
this.bookTitle = this.bookTitle + Character.toString(c);
this.updateButtons();
this.bookModified = true;
}
}
}
private List<String> getPage(int page) {
if (bookPages.isEmpty())
initPages();
return bookPages.get(page);
}
private String getLine(int line) {
List<String> page = getPage(currPage);
return page.get(line);
}
private void setLine(int pageNum, int lineNum, String string) {
if (pageNum >= 0 && pageNum < bookPages.size()) {
List<String> page = bookPages.get(pageNum);
page.set(lineNum, string);
this.bookModified = true;
}
}
private void addToBook(String string) {
String currentText = getLine(currLine);
String newText = currentText + string;
if (newText.length() < ItemRoutingTable.LINE_LENGTH)
this.setLine(currPage, currLine, newText);
}
/**
* Draws the screen and all the components in it.
*/
@Override
public void drawScreen(int par1, int par2, float par3) {
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
this.mc.renderEngine.bindTexture(TEXTURE);
int xOffset = (this.width - this.bookImageWidth) / 2;
byte yOffset = 2;
this.drawTexturedModalRect(xOffset, yOffset, 0, 0, this.bookImageWidth, this.bookImageHeight);
if (this.editingTitle) {
String title = this.bookTitle;
if (this.editable)
if (this.updateCount / 6 % 2 == 0)
title = title + "" + EnumChatFormatting.BLACK + "_";
else
title = title + "" + EnumChatFormatting.GRAY + "_";
String s1 = StatCollector.translateToLocal("book.editTitle");
int l = this.fontRendererObj.getStringWidth(s1);
this.fontRendererObj.drawString(s1, xOffset + 36 + (116 - l) / 2, yOffset + 16 + 16, 0);
int i1 = this.fontRendererObj.getStringWidth(title);
this.fontRendererObj.drawString(title, xOffset + 36 + (116 - i1) / 2, yOffset + 48, 0);
String s2 = String.format(StatCollector.translateToLocal("book.byAuthor"), Railcraft.proxy.getPlayerUsername(player));
int j1 = this.fontRendererObj.getStringWidth(s2);
this.fontRendererObj.drawString(EnumChatFormatting.DARK_GRAY + s2, xOffset + 36 + (116 - j1) / 2, yOffset + 48 + 10, 0);
// String s3 = StatCollector.translateToLocal("book.finalizeWarning");
// this.fontRendererObj.drawSplitString(s3, xOffset + 36, yOffset + 80, 116, 0);
} else if (readingManual) {
// GuiTools.drawCenteredString(fontRendererObj, RailcraftLanguage.translate("routing.table.manual.title"), yOffset + 16, width);
fontRendererObj.drawString(LocalizationPlugin.translate("railcraft.gui.routing.table.manual.title"), xOffset + 45, yOffset + 16, 0);
String pageNumString = String.format(StatCollector.translateToLocal("book.pageIndicator"), currPage + 1, MANUAL_PAGES);
int pageNumStringWidth = this.fontRendererObj.getStringWidth(pageNumString);
this.fontRendererObj.drawString(pageNumString, xOffset - pageNumStringWidth + this.bookImageWidth - 44, yOffset + 16, 0);
if (currPage < 0 || currPage >= MANUAL_PAGES)
return;
String pageTag = "railcraft.gui.routing.table.manual.page" + (currPage + 1);
if (LocalizationPlugin.hasTag(pageTag)) {
String text = LocalizationPlugin.translate(pageTag);
this.fontRendererObj.drawSplitString(text, xOffset + 16, yOffset + 16 + 16, WRAP_WIDTH, 0);
}
} else {
String pageNumString = String.format(StatCollector.translateToLocal("book.pageIndicator"), currPage + 1, bookPages.size());
int pageNumStringWidth = this.fontRendererObj.getStringWidth(pageNumString);
this.fontRendererObj.drawString(pageNumString, xOffset - pageNumStringWidth + this.bookImageWidth - 44, yOffset + 16, 0);
if (currPage < 0 || currPage >= bookPages.size())
return;
StringBuilder text = new StringBuilder();
List<String> page = bookPages.get(currPage);
ListIterator<String> it = page.listIterator();
while (it.hasNext()) {
String line = it.next();
text.append(EnumChatFormatting.BLACK);
int start = text.length();
text.append(line).append(" ");
if (editable && it.previousIndex() == currLine)
if (updateCount / 6 % 2 == 0) {
text.insert(start + currChar, EnumChatFormatting.UNDERLINE.toString());
text.insert(start + currChar + 3, EnumChatFormatting.BLACK.toString());
}
text.append("\n");
}
this.fontRendererObj.drawSplitString(text.toString(), xOffset + 16, yOffset + 16 + 16, WRAP_WIDTH, 0);
}
super.drawScreen(par1, par2, par3);
}
}