Java tutorial
/* * 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; } } }