package com.gpl.rpg.atcontentstudio.model.maps; import java.awt.Image; import java.awt.Point; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.swing.tree.TreeNode; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import com.gpl.rpg.atcontentstudio.model.GameSource; import com.gpl.rpg.atcontentstudio.model.GameSource.Type; import com.gpl.rpg.atcontentstudio.model.Project; import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode; import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataSet; import com.gpl.rpg.atcontentstudio.ui.DefaultIcons; public class Worldmap extends ArrayList implements ProjectTreeNode { private static final long serialVersionUID = 4590409256594556179L; public static final String DEFAULT_REL_PATH_IN_SOURCE = "res/xml/worldmap.xml"; public static final String DEFAULT_REL_PATH_IN_PROJECT = "maps"+File.separator+"worldmap.xml"; public File worldmapFile; public GameSource parent; public Map> segments = new LinkedHashMap>(); public Worldmap(GameSource gameSource) { this.parent = gameSource; if (getDataType() == Type.source) { worldmapFile = new File(parent.baseFolder, DEFAULT_REL_PATH_IN_SOURCE); } else { worldmapFile = new File(parent.baseFolder, DEFAULT_REL_PATH_IN_PROJECT); } if (worldmapFile.exists()) { loadFromFile(worldmapFile); } if (getDataType() == Type.source) { for (WorldmapSegment segment : this) { segment.writable = false; } } else { for (WorldmapSegment segment : this) { segment.writable = true; } } } private void loadFromFile(File file) { if (!file.exists()) return; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); Document doc; try { factory.setIgnoringComments(true); factory.setIgnoringElementContentWhitespace(true); factory.setExpandEntityReferences(false); DocumentBuilder builder = factory.newDocumentBuilder(); InputSource insrc = new InputSource(new FileInputStream(file)); insrc.setSystemId("http://worldmap/"); insrc.setEncoding("UTF-8"); doc = builder.parse(insrc); Element root = (Element) doc.getElementsByTagName("worldmap").item(0); if (root != null) { NodeList segmentsList = root.getElementsByTagName("segment"); if (segmentsList != null) { for (int i = 0; i < segmentsList.getLength(); i++) { Element segmentNode = (Element) segmentsList.item(i); String name = segmentNode.getAttribute("id"); add(new WorldmapSegment(this, name, segmentNode)); } } } } catch (SAXException e) { e.printStackTrace(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public Enumeration children() { return Collections.enumeration(this); } @Override public boolean getAllowsChildren() { return true; } @Override public TreeNode getChildAt(int arg0) { return get(arg0); } @Override public int getChildCount() { return size(); } @Override public int getIndex(TreeNode arg0) { return indexOf(arg0); } @Override public TreeNode getParent() { return parent; } @Override public boolean isLeaf() { return false; } @Override public void childrenAdded(List path) { path.add(0,this); parent.childrenAdded(path); } @Override public void childrenChanged(List path) { path.add(0,this); parent.childrenChanged(path); } @Override public void childrenRemoved(List path) { if (path.size() == 1 && this.getChildCount() == 1) { childrenRemoved(new ArrayList()); } else { path.add(0, this); parent.childrenRemoved(path); } } @Override public String getDesc() { return (needsSaving() ? "*" : "")+"Worldmap"; } @Override public void notifyCreated() { childrenAdded(new ArrayList()); } @Override public Project getProject() { return parent.getProject(); } @Override public Image getIcon() { return DefaultIcons.getMapClosedIcon(); } @Override public Image getLeafIcon() { return null; } @Override public Image getClosedIcon() { return DefaultIcons.getMapClosedIcon(); } @Override public Image getOpenIcon() { return DefaultIcons.getMapOpenIcon(); } @Override public GameDataSet getDataSet() { return null; } @Override public Type getDataType() { return parent.getDataType(); } public void save() { try { Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); doc.setXmlVersion("1.0"); Element root = doc.createElement("worldmap"); doc.appendChild(root); for (WorldmapSegment segment : this) { root.appendChild(segment.toXmlElement(doc)); } saveDocToFile(doc, worldmapFile); } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public WorldmapSegment getWorldmapSegment(String id) { for (WorldmapSegment s : this) { if (s.id.equals(id)) { return s; } } return null; } public void addSegment(WorldmapSegment node) { ProjectTreeNode higherEmptyParent = this; while (higherEmptyParent != null) { if (higherEmptyParent.getParent() != null && ((ProjectTreeNode)higherEmptyParent.getParent()).isEmpty()) higherEmptyParent = (ProjectTreeNode)higherEmptyParent.getParent(); else break; } if (higherEmptyParent == this && !this.isEmpty()) higherEmptyParent = null; add(node); node.parent = this; if (higherEmptyParent != null) higherEmptyParent.notifyCreated(); else node.notifyCreated(); } public static void saveDocToFile(Document doc, File f) { try { Transformer transformer = TransformerFactory.newInstance().newTransformer(); Result output = new StreamResult(new FileOutputStream(f)); Source input = new DOMSource(doc); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2"); transformer.transform(input, output); } catch (TransformerConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (TransformerFactoryConfigurationError e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (TransformerException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public boolean needsSaving() { for (ProjectTreeNode node : this) { if (node.needsSaving()) return true; } return false; } }