/* * Copyright 2016 Nathan Howard * * This file is part of OpenGrave * * OpenGrave 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. * * OpenGrave 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 OpenGrave. If not, see <http://www.gnu.org/licenses/>. */ package com.opengrave.og.resources; import java.io.IOException; import java.io.StringReader; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.*; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.opengrave.common.DebugExceptionHandler; import com.opengrave.og.gui.*; import com.opengrave.og.gui.ElementData.PositionTypeX; import com.opengrave.og.gui.ElementData.PositionTypeY; import com.opengrave.og.util.Vector4f; public class GUIXML { public static HashMap<String, Class<? extends UIElement>> types = new HashMap<String, Class<? extends UIElement>>(); private String fileName; private UnorderedContainer parent; private Vector4f defaultColour = new Vector4f(1f, 1f, 1f, 1f), activeColour = new Vector4f(1f, 1f, 1f, 1f), disabledColour = new Vector4f(1f, 1f, 1f, 1f), textColour = new Vector4f(0f, 0f, 0f, 1f); private boolean ignoreContainer = false; public UnorderedContainer getGUI() { return parent; } public GUIXML(String fileName) { this.fileName = fileName; this.parent = new UnorderedContainer(new ElementData()); build(); } public GUIXML(String fileName, ElementData ed) { ignoreContainer = true; this.fileName = fileName; this.parent = new UnorderedContainer(ed); build(); } private void build() { String contents = Resources.loadTextFile(fileName); Document doc = null; try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; builder = dbf.newDocumentBuilder(); doc = builder.parse(new InputSource(new StringReader(contents))); } catch (ParserConfigurationException e) { new DebugExceptionHandler(e, fileName); } catch (SAXException e) { new DebugExceptionHandler(e, fileName); } catch (IOException e) { new DebugExceptionHandler(e, fileName); } Node container = doc.getChildNodes().item(0); if (!ignoreContainer) { doGlobal(container); } else { defaultColour = parent.getElementData().activeColour; defaultColour = parent.getElementData().defaultColour; disabledColour = parent.getElementData().disabledColour; textColour = parent.getElementData().textColour; } doChildrenFor(parent, container); if (!ignoreContainer) { parent.getElementData().activeColour = activeColour; parent.getElementData().defaultColour = defaultColour; parent.getElementData().disabledColour = disabledColour; parent.getElementData().textColour = textColour; } } private void doGlobal(Node container) { NamedNodeMap attribs = container.getAttributes(); if (attribs != null) { for (int i = 0; i < attribs.getLength(); i++) { Attr a = (Attr) attribs.item(i); String key = a.getNodeName(); String val = a.getNodeValue(); switch (key.toLowerCase()) { case "colour": defaultColour = getColour(val); break; case "activecolour": activeColour = getColour(val); break; case "disabledcolour": disabledColour = getColour(val); break; case "textcolour": textColour = getColour(val); break; } } } } private void doChildrenFor(UIParent parent, Node parentNode) { NodeList nodeList = parentNode.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); String nodeType = node.getNodeName(); if (nodeType.equalsIgnoreCase("include")) { NamedNodeMap attribs = node.getAttributes(); String fileName = ""; for (int c = 0; c < attribs.getLength(); c++) { Attr a = (Attr) attribs.item(c); String key = a.getNodeName(); String val = a.getNodeValue(); if (key.equalsIgnoreCase("file")) { fileName = val; } } if (fileName.length() > 1) { ElementData ed = new ElementData(); ed.defaultColour = this.defaultColour; ed.activeColour = this.activeColour; ed.disabledColour = this.disabledColour; ed.textColour = this.textColour; GUIXML included = new GUIXML(fileName, ed); for (UIElement e : included.getGUI().getChildren()) { parent.addChildEnd(e); } } } else if (types.containsKey(nodeType)) { UIElement ele = null; ElementData ed = new ElementData(); ed.defaultColour = this.defaultColour; ed.activeColour = this.activeColour; ed.disabledColour = this.disabledColour; ed.textColour = this.textColour; try { ele = types.get(nodeType).getConstructor(ElementData.class).newInstance(ed); } catch (InstantiationException e) { new DebugExceptionHandler(e, nodeType); } catch (IllegalAccessException e) { new DebugExceptionHandler(e, nodeType); } catch (IllegalArgumentException e) { new DebugExceptionHandler(e, nodeType); } catch (InvocationTargetException e) { new DebugExceptionHandler(e, nodeType); } catch (NoSuchMethodException e) { new DebugExceptionHandler(e, nodeType); } catch (SecurityException e) { new DebugExceptionHandler(e, nodeType); } if (ele != null) { setAttributes(ele, node); if (parent != null) { parent.addChildEnd(ele); } if (ele instanceof UIParent) { doChildrenFor((UIParent) ele, node); } } } } } private void setAttributes(UIElement ele, Node info) { NamedNodeMap attribs = info.getAttributes(); ElementData ed = ele.getElementData(); if (attribs != null) { for (int i = 0; i < attribs.getLength(); i++) { Attr a = (Attr) attribs.item(i); String key = a.getNodeName(); String val = a.getNodeValue(); ed.attributes.put(key.toLowerCase(), val); switch (key.toLowerCase()) { case "minimumheight": ed.minimum_height = Integer.parseInt(val); break; case "minimumwidth": ed.minimum_width = Integer.parseInt(val); break; case "maximumheight": ed.maximum_height = Integer.parseInt(val); break; case "maximumwidth": ed.maximum_width = Integer.parseInt(val); break; case "positionx": ed.x = Integer.parseInt(val); break; case "positiony": ed.y = Integer.parseInt(val); break; case "colour": ed.defaultColour = getColour(val); break; case "activecolour": ed.activeColour = getColour(val); break; case "disabledcolour": ed.disabledColour = getColour(val); break; case "textcolour": ed.textColour = getColour(val); break; case "id": ed.id = val; break; case "text": if (ele instanceof TextInterface) { TextInterface ti = (TextInterface) ele; ti.setString(val); } break; case "posxanchor": ed.positionTypeX = getPositioningTypeX(val); break; case "posyanchor": ed.positionTypeY = getPositioningTypeY(val); break; } } ele.attributesChanged(); } } private PositionTypeX getPositioningTypeX(String s) { if (s.equalsIgnoreCase("fixed")) { return PositionTypeX.FIXED; } else if (s.equalsIgnoreCase("center")) { return PositionTypeX.CENTER; } else if (s.equalsIgnoreCase("left")) { return PositionTypeX.LEFT; } else if (s.equalsIgnoreCase("right")) { return PositionTypeX.RIGHT; } return PositionTypeX.FIXED; } private PositionTypeY getPositioningTypeY(String s) { if (s.equalsIgnoreCase("fixed")) { return PositionTypeY.FIXED; } else if (s.equalsIgnoreCase("center")) { return PositionTypeY.CENTER; } else if (s.equalsIgnoreCase("top")) { return PositionTypeY.TOP; } else if (s.equalsIgnoreCase("bottom")) { return PositionTypeY.BOTTOM; } return PositionTypeY.FIXED; } public static Vector4f getColour(String val) { if (!val.substring(0, 1).equals("#")) { return new Vector4f(1f, 1f, 1f, 1f); } float r = 1f, g = 1f, b = 1f, a = 1f; String rS = "f", gS = "f", bS = "f", aS = "f"; float order = 1f; if (val.length() == 4) { // # and 1 byte each. Only RGB rS = val.substring(1, 2); gS = val.substring(2, 3); bS = val.substring(3, 4); aS = "f"; order = 15f; } else if (val.length() == 5) { // # and 1 byte each. RGBA rS = val.substring(1, 2); gS = val.substring(2, 3); bS = val.substring(3, 4); aS = val.substring(4, 5); order = 15f; } else if (val.length() == 7) { // # and 2 bytes each, RRGGBB, html style rS = val.substring(1, 3); gS = val.substring(3, 5); bS = val.substring(5, 7); aS = "ff"; order = 255f; } else if (val.length() == 9) { // # and 2 bytes each, RRGGBBAA rS = val.substring(1, 3); gS = val.substring(3, 5); bS = val.substring(5, 7); aS = val.substring(7, 9); order = 255f; } else { System.out.println("Unknown colour value : " + val); return new Vector4f(1f, 1f, 1f, 1f); } r = Integer.decode("0x" + rS) / order; g = Integer.decode("0x" + gS) / order; b = Integer.decode("0x" + bS) / order; a = Integer.decode("0x" + aS) / order; return new Vector4f(r, g, b, a); } public static void init() { types.put("main", UnorderedContainer.class); types.put("button", TextButton.class); types.put("scrollbox", ScrollBox.class); types.put("textinput", TextInput.class); types.put("numberinput", NumberRoller.class); types.put("vert", VerticalContainer.class); types.put("hori", HorizontalContainer.class); types.put("textarea", TextArea.class); types.put("image", Image.class); types.put("checkbox", CheckButton.class); types.put("floatinput", FloatNumberRoller.class); types.put("stringinput", StringRoller.class); types.put("checkgroup", CheckButtonGroupVertical.class); types.put("vector3", VectorInput3.class); types.put("sceneview", SceneView.class); types.put("scrollable", Scrollable.class); types.put("inputicon", ImageInput.class); } }