/* * This file is part of Matter Overdrive * Copyright (c) 2015., Simeon Radivoev, All rights reserved. * * Matter Overdrive is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Matter Overdrive is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Matter Overdrive. If not, see <http://www.gnu.org/licenses>. */ package matteroverdrive.gui.pages; import matteroverdrive.MatterOverdrive; import matteroverdrive.Reference; import matteroverdrive.data.ScaleTexture; import matteroverdrive.gui.MOGuiBase; import matteroverdrive.gui.element.ElementBaseGroup; import matteroverdrive.gui.element.MOElementBase; import matteroverdrive.gui.element.MOElementButton; import matteroverdrive.guide.GuideElementPage; import matteroverdrive.guide.IGuideElement; import matteroverdrive.guide.MOGuideEntry; import matteroverdrive.guide.MatterOverdriveGuide; import matteroverdrive.init.MatterOverdriveItems; import matteroverdrive.network.packet.server.PacketDataPadCommands; import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.Level; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.io.InputStream; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import static org.lwjgl.opengl.GL11.*; /** * Created by Simeon on 4/3/2015. */ public class PageGuideDescription extends ElementBaseGroup { public static final ScaleTexture GUIDES_BG = new ScaleTexture(new ResourceLocation(Reference.PATH_ELEMENTS + "guides_bg.png"),166,142).setOffsets(80,80,72,69); public static final String SCROLL_RIGHT_ELEMENT_NAME = "scroll_right"; public static final String SCROLL_LEFT_ELEMENT_NAME = "scroll_left"; public static final String RETURN_ELEMENT_NAME = "return"; DocumentBuilderFactory builderFactory; DocumentBuilder builder; public static int tabID; public static int scroll; private static Stack<HistoryEntry> historyStack = new Stack<>(); List<IGuideElement> pages; MOElementButton bt_scroll_right; MOElementButton bt_scroll_left; public final MOElementButton bt_return; private ItemStack dataPadStack; public PageGuideDescription(MOGuiBase gui, int posX, int posY, int width, int height, String name) { super(gui, posX, posY, width, height); this.setName(name); pages = new ArrayList<>(); bt_scroll_right = new MOElementButton(gui,this,sizeX - 20,sizeY - 16,SCROLL_RIGHT_ELEMENT_NAME,0,0,10,0,10,10,""); bt_scroll_right.setTexture(Reference.PATH_ELEMENTS + "scroll_right.png",20,10); bt_scroll_left = new MOElementButton(gui,this,10,sizeY - 16,SCROLL_LEFT_ELEMENT_NAME,0,0,10,0,10,10,""); bt_scroll_left.setTexture(Reference.PATH_ELEMENTS + "scroll_left.png", 20, 10); bt_return = new MOElementButton(gui,this,sizeX/2 - 5,sizeY - 16,RETURN_ELEMENT_NAME,0,0,11,0,11,11,""); bt_return.setTexture(Reference.PATH_ELEMENTS + "return_arrow.png", 22, 11); builderFactory = DocumentBuilderFactory.newInstance(); builderFactory.setIgnoringElementContentWhitespace(true); try { builder = builderFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { e.printStackTrace(); } } @Override public void init() { super.init(); elements.add(bt_scroll_left); elements.add(bt_scroll_right); elements.add(bt_return); loadGuideInfo(MatterOverdriveItems.dataPad.getGuideID(dataPadStack)); } @Override public void drawForeground(int mouseX, int mouseY) { if(MatterOverdriveItems.dataPad.getGuideID(dataPadStack) >= 0) { boolean lastUnicodeFlag = Minecraft.getMinecraft().fontRenderer.getUnicodeFlag(); //set yunicode for smaller text and all characters Minecraft.getMinecraft().fontRenderer.setUnicodeFlag(true); if(tabID == 0) { DrawDescription(mouseX,mouseY); } Minecraft.getMinecraft().fontRenderer.setUnicodeFlag(lastUnicodeFlag); } super.drawForeground(mouseX, mouseY); } private void DrawDescription(int mouseX,int mouseY) { if (scroll < pages.size() && scroll >= 0) { MOGuideEntry guideEntry = MatterOverdriveGuide.getQuide(MatterOverdriveItems.dataPad.getGuideID(dataPadStack)); int x = posX; int y = posY; if (pages.get(scroll) != null && scroll < pages.size()) { glPushMatrix(); glTranslated(x, y, 0); IGuideElement element = pages.get(scroll); element.drawElement(sizeX,mouseX-x ,mouseY-y); glPopMatrix(); }else { drawNoInfo(); } }else { drawNoInfo(); } handleScrollButtons(); } private void drawNoInfo() { int noInfoWidth = getFontRenderer().getStringWidth("No Info..."); getFontRenderer().drawString("No Info...", sizeX / 2 - noInfoWidth / 2, sizeY / 2, Reference.COLOR_HOLO_RED.getColor()); } private void handleScrollButtons() { bt_scroll_left.setVisible(true); bt_scroll_right.setVisible(true); if(scroll >= pages.size()-1) { bt_scroll_right.setVisible(false); } if (scroll <= 0) { bt_scroll_left.setVisible(false); } } @Override public void handleElementButtonClick(MOElementBase element, String buttonName, int mouseButton) { if(element.equals(bt_scroll_left)) { scroll--; } else if(element.equals(bt_scroll_right)) { scroll++; } else if (element.equals(bt_return)) { undo(); } scroll = MathHelper.clamp_int(scroll,0, pages.size()-1); } public void OpenGuide(int id,boolean writeToHistory) { OpenGuide(id,0,writeToHistory); } public void OpenGuide(int id,int page,boolean writeToHistory) { if (MatterOverdriveItems.dataPad.getGuideID(dataPadStack) != id) { if (writeToHistory) historyStack.push(new HistoryEntry(MatterOverdriveItems.dataPad.getGuideID(dataPadStack),scroll)); loadGuideInfo(id); MatterOverdriveItems.dataPad.setOpenGuide(dataPadStack, id); MatterOverdrive.packetPipeline.sendToServer(new PacketDataPadCommands(dataPadStack)); this.scroll = page; this.tabID = 0; } } private void undo() { if (historyStack.size() > 0) { HistoryEntry historyEntry = historyStack.pop(); OpenGuide(historyEntry.entry,false); scroll = historyEntry.scroll; } else { ((MOGuiBase)gui).setPage(0); } } private void loadGuideInfo(int guideID) { pages.clear(); if(guideID >= 0) { MOGuideEntry entry = MatterOverdriveGuide.getQuide(guideID); InputStream descriptionStream = entry.getDescriptionStream(); if (descriptionStream != null) { try { Document document = builder.parse(descriptionStream); document.normalize(); Element rootNode = (Element) document.getElementsByTagName("entry").item(0); NodeList pagesNodes = rootNode.getElementsByTagName("page"); Map<String,String> stylesheetMap = loadStyleSheetMap(rootNode); for (int i = 0; i < pagesNodes.getLength(); i++) { GuideElementPage page = new GuideElementPage(); page.setGUI((MOGuiBase)gui); page.loadElement(entry,(Element)pagesNodes.item(i),stylesheetMap,sizeX,sizeY); pages.add(page); } } catch (SAXException e) { MatterOverdrive.log.log(Level.ERROR, e, "XML for guide entry %s is not valid", entry.getDisplayName()); } catch (IOException e) { MatterOverdrive.log.log(Level.ERROR, e, "there was a problem reading language file for entry %s", entry.getDisplayName()); } }else { MatterOverdrive.log.warn("Guide Entry file for %s missing at: %s",entry.getDisplayName(),entry.getDescriptionPath("language")); } } } private Map<String,String> loadStyleSheetMap(Element element) { if (element.hasAttribute("stylesheet")) { try { Map<String,String> styleMap = new HashMap<>(); InputStream stylesheetStream = Minecraft.getMinecraft().getResourceManager().getResource(new ResourceLocation(element.getAttribute("stylesheet"))).getInputStream(); String rawStyle = IOUtils.toString(stylesheetStream, "UTF-8"); rawStyle = rawStyle.replaceAll("\\r|\\n|\\s+",""); rawStyle = rawStyle.replaceAll("(?s)/\\*.*?\\*/", ""); //remove comments Matcher matcher = Pattern.compile("([^\\}\\{]+)(\\{[^\\}]+\\})", Pattern.DOTALL | Pattern.MULTILINE).matcher(rawStyle); while (matcher.find()) { styleMap.put(matcher.group(1), matcher.group(2).substring(1,matcher.group(2).length()-1)); } return styleMap; } catch (IOException e) { MatterOverdrive.log.log(Level.ERROR,e,"There was a problem loading the stylesheet"); } } return null; } public void setDataPadStack(ItemStack stack) { dataPadStack = stack; } private class HistoryEntry { public final int entry; public final int scroll; public HistoryEntry(int entry,int scroll) { this.entry = entry; this.scroll = scroll; } } }