/* * Freeplane - mind map editor * Copyright (C) 2008 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitry Polivaev * * This file is modified by Dimitry Polivaev in 2008. * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package org.freeplane.features.link; import java.awt.Color; import java.awt.Point; import java.io.IOException; import java.net.URI; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import org.freeplane.core.extension.IExtension; import org.freeplane.core.io.IAttributeHandler; import org.freeplane.core.io.IElementDOMHandler; import org.freeplane.core.io.IExtensionAttributeWriter; import org.freeplane.core.io.IExtensionElementWriter; import org.freeplane.core.io.IReadCompletionListener; import org.freeplane.core.io.ITreeWriter; import org.freeplane.core.io.ReadManager; import org.freeplane.core.io.WriteManager; import org.freeplane.core.io.xml.TreeXmlReader; import org.freeplane.core.io.xml.TreeXmlWriter; import org.freeplane.core.util.ColorUtils; import org.freeplane.features.link.ConnectorModel.Shape; import org.freeplane.features.map.NodeBuilder; import org.freeplane.features.map.NodeModel; import org.freeplane.n3.nanoxml.XMLElement; class LinkBuilder implements IElementDOMHandler, IReadCompletionListener, IExtensionElementWriter, IExtensionAttributeWriter { private static final String FORMAT_AS_HYPERLINK = "FORMAT_AS_HYPERLINK"; private static final String LINK = "LINK"; final private HashSet<NodeLinkModel> arrowLinks; private final LinkController linkController; public LinkBuilder(final LinkController linkController) { this.linkController = linkController; arrowLinks = new HashSet<NodeLinkModel>(); } protected NodeLinkModel createArrowLink(final NodeModel source, final String targetID) { return new ConnectorModel(source, targetID, linkController.getStandardConnectorColor(), linkController.getStandardConnectorAlpha(), linkController.getStandardConnectorShape(), linkController.getStandardConnectorWidth(), linkController.getStandardLabelFontFamily(), linkController.getStandardLabelFontSize()); } public Object createElement(final Object parent, final String tag, final XMLElement attributes) { if (tag.equals("arrowlink")) { return createArrowLink((NodeModel) parent, null); } return null; } /** * Completes the links within the getMap(). They are registered in the * registry. */ public void readingCompleted(final NodeModel topNode, final Map<String, String> newIds) { final Iterator<NodeLinkModel> iterator = arrowLinks.iterator(); while (iterator.hasNext()) { final NodeLinkModel arrowLink = iterator.next(); final String id = arrowLink.getTargetID(); final String newId = newIds.get(id); final String targetID = newId != null ? newId : id; if (targetID == null) { new NullPointerException().printStackTrace(); continue; } arrowLink.setTargetID(targetID); final NodeModel source = arrowLink.getSource(); NodeLinks.createLinkExtension(source).addArrowlink(arrowLink); } arrowLinks.clear(); } private void registerAttributeHandlers(final ReadManager reader) { reader.addAttributeHandler(NodeBuilder.XML_NODE, LINK, new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final NodeModel node = (NodeModel) userObject; linkController.loadLink(node, value); } }); final IAttributeHandler hyperlinkHandler = new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final NodeModel node = (NodeModel) userObject; linkController.loadLinkFormat(node, Boolean.parseBoolean(value)); } }; reader.addAttributeHandler(NodeBuilder.XML_NODE, FORMAT_AS_HYPERLINK, hyperlinkHandler); reader.addAttributeHandler(NodeBuilder.XML_STYLENODE, FORMAT_AS_HYPERLINK, hyperlinkHandler); reader.addAttributeHandler("arrowlink", "EDGE_LIKE", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; arrowLink.setShape(Shape.EDGE_LIKE); } }); reader.addAttributeHandler("arrowlink", "SHAPE", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; arrowLink.setShape(Shape.valueOf(value)); } }); reader.addAttributeHandler("arrowlink", "DASH", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; final String[] split = value.split(" "); int[] dash = new int[split.length]; int i = 0; for(String s : split){ dash[i++] = Integer.parseInt(s); } arrowLink.setDash(dash); } }); reader.addAttributeHandler("arrowlink", "DESTINATION", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; arrowLink.setTargetID(value); arrowLinks.add(arrowLink); } }); reader.addAttributeHandler("arrowlink", "SOURCE_LABEL", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; arrowLink.setSourceLabel(value.toString()); } }); reader.addAttributeHandler("arrowlink", "MIDDLE_LABEL", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; arrowLink.setMiddleLabel(value.toString()); } }); reader.addAttributeHandler("arrowlink", "TARGET_LABEL", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; arrowLink.setTargetLabel(value.toString()); } }); reader.addAttributeHandler("arrowlink", "STARTINCLINATION", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; arrowLink.setStartInclination(TreeXmlReader.xmlToPoint(value.toString())); } }); reader.addAttributeHandler("arrowlink", "ENDINCLINATION", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; arrowLink.setEndInclination(TreeXmlReader.xmlToPoint(value.toString())); } }); reader.addAttributeHandler("arrowlink", "STARTARROW", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; arrowLink.setStartArrow(ArrowType.valueOf(value.toUpperCase())); } }); reader.addAttributeHandler("arrowlink", "ENDARROW", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; arrowLink.setEndArrow(ArrowType.valueOf(value.toUpperCase())); } }); reader.addAttributeHandler("arrowlink", "WIDTH", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; arrowLink.setWidth(Integer.parseInt(value.toString())); } }); reader.addAttributeHandler("arrowlink", "FONT_FAMILY", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; arrowLink.setLabelFontFamily(value.toString()); } }); reader.addAttributeHandler("arrowlink", "FONT_SIZE", new IAttributeHandler() { public void setAttribute(final Object userObject, final String value) { final ConnectorModel arrowLink = (ConnectorModel) userObject; arrowLink.setLabelFontSize(Integer.parseInt(value.toString())); } }); } public void endElement(Object parent, String tag, Object element, XMLElement dom) { final ConnectorModel arrowLink = (ConnectorModel) element; final String color = dom.getAttribute("COLOR", null); final String transparency = dom.getAttribute("TRANSPARENCY", null); if(color != null){ arrowLink.setColor(ColorUtils.stringToColor(color)); if(transparency == null){ arrowLink.setAlpha(255); } } else{ arrowLink.setColor(linkController.getStandardConnectorColor()); } if(transparency != null){ arrowLink.setAlpha(Integer.parseInt(transparency)); } else if(color == null){ arrowLink.setAlpha(linkController.getStandardConnectorAlpha()); } } /** */ public void registerBy(final ReadManager reader, final WriteManager writer) { reader.addElementHandler("arrowlink", this); registerAttributeHandlers(reader); reader.addReadCompletionListener(this); writer.addExtensionAttributeWriter(NodeLinks.class, this); writer.addExtensionElementWriter(NodeLinks.class, this); } public void save(final ITreeWriter writer, final ConnectorModel model) throws IOException { final NodeModel target = model.getTarget(); if (target == null) { return; } final XMLElement arrowLink = new XMLElement(); arrowLink.setName("arrowlink"); final Shape shape = model.getShape(); arrowLink.setAttribute("SHAPE", shape.toString()); final Color color = model.getColor(); arrowLink.setAttribute("COLOR", ColorUtils.colorToString(color)); final int width = model.getWidth(); arrowLink.setAttribute("WIDTH", Integer.toString(width)); final int alpha = model.getAlpha(); arrowLink.setAttribute("TRANSPARENCY", Integer.toString(alpha)); final int[]dash = model.getDash(); if (dash != null) { StringBuilder sb = null; for(int i : dash){ if(sb == null){ sb = new StringBuilder(dash.length * 4); } else{ sb.append(' '); } sb.append(i); } if(sb != null){ arrowLink.setAttribute("DASH", sb.toString()); } } final int fontSize = model.getLabelFontSize(); arrowLink.setAttribute("FONT_SIZE", Integer.toString(fontSize)); final String fontFamily = model.getLabelFontFamily(); arrowLink.setAttribute("FONT_FAMILY", fontFamily); final String destinationLabel = target.createID(); if (destinationLabel != null) { arrowLink.setAttribute("DESTINATION", destinationLabel); } final String sourceLabel = model.getSourceLabel(); if (sourceLabel != null) { arrowLink.setAttribute("SOURCE_LABEL", sourceLabel); } final String targetLabel = model.getTargetLabel(); if (targetLabel != null) { arrowLink.setAttribute("TARGET_LABEL", targetLabel); } final String middleLabel = model.getMiddleLabel(); if (middleLabel != null) { arrowLink.setAttribute("MIDDLE_LABEL", middleLabel); } final Point startInclination = model.getStartInclination(); if (startInclination != null) { arrowLink.setAttribute("STARTINCLINATION", TreeXmlWriter.PointToXml(startInclination)); } final Point endInclination = model.getEndInclination(); if (endInclination != null) { arrowLink.setAttribute("ENDINCLINATION", TreeXmlWriter.PointToXml(endInclination)); } final String startArrow = model.getStartArrow().toString(); if (startArrow != null) { arrowLink.setAttribute("STARTARROW", startArrow); } final String endArrow = model.getEndArrow().toString(); if (endArrow != null) { arrowLink.setAttribute("ENDARROW", endArrow); } writer.addElement(model, arrowLink); } public void setAttributes(final String tag, final Object node, final XMLElement attributes) { } public void writeAttributes(final ITreeWriter writer, final Object userObject, final IExtension extension) { final NodeLinks links = (NodeLinks) extension; final URI link = links.getHyperLink(); if (link != null) { final String string = link.toString(); if (string.startsWith("#")) { if (((NodeModel) userObject).getMap().getNodeForID(string.substring(1)) == null) { return; } } writer.addAttribute(LINK, string); } final Boolean formatNodeAsHyperlink = links.formatNodeAsHyperlink(); if (formatNodeAsHyperlink != null) { writer.addAttribute(FORMAT_AS_HYPERLINK, formatNodeAsHyperlink.toString()); } } public void writeContent(final ITreeWriter writer, final Object node, final IExtension extension) throws IOException { final NodeLinks links = (NodeLinks) extension; final Iterator<LinkModel> iterator = links.getLinks().iterator(); while (iterator.hasNext()) { final LinkModel linkModel = iterator.next(); if (linkModel instanceof ConnectorModel) { final ConnectorModel arrowLinkModel = (ConnectorModel) linkModel; save(writer, arrowLinkModel); } } } }