/*
* Freeplane - mind map editor
* Copyright (C) 2008 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitry Polivaev
*
* This file is created 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.nodestyle;
import java.awt.Color;
import java.io.IOException;
import org.freeplane.core.extension.IExtension;
import org.freeplane.core.io.IAttributeHandler;
import org.freeplane.core.io.IAttributeWriter;
import org.freeplane.core.io.IElementDOMHandler;
import org.freeplane.core.io.IElementWriter;
import org.freeplane.core.io.IExtensionAttributeWriter;
import org.freeplane.core.io.IExtensionElementWriter;
import org.freeplane.core.io.ITreeWriter;
import org.freeplane.core.io.ReadManager;
import org.freeplane.core.io.WriteManager;
import org.freeplane.core.util.ColorUtils;
import org.freeplane.core.util.FreeplaneVersion;
import org.freeplane.features.map.MapWriter;
import org.freeplane.features.map.NodeBuilder;
import org.freeplane.features.map.NodeModel;
import org.freeplane.n3.nanoxml.XMLElement;
class NodeStyleBuilder implements IElementDOMHandler, IExtensionElementWriter, IExtensionAttributeWriter,
IAttributeWriter, IElementWriter {
static class FontProperties {
String fontName;
Integer fontSize;
Boolean isBold;
Boolean isItalic;
}
private final NodeStyleController nsc;
public NodeStyleBuilder(final NodeStyleController nsc) {
this.nsc = nsc;
}
public Object createElement(final Object parent, final String tag, final XMLElement attributes) {
if (tag.equals("font")) {
return new FontProperties();
}
return null;
}
public void endElement(final Object parent, final String tag, final Object userObject, final XMLElement dom) {
if (parent instanceof NodeModel) {
final NodeModel node = (NodeModel) parent;
if (tag.equals("font")) {
final FontProperties fp = (FontProperties) userObject;
NodeStyleModel nodeStyleModel = NodeStyleModel.getModel(node);
if (nodeStyleModel == null) {
nodeStyleModel = new NodeStyleModel();
node.addExtension(nodeStyleModel);
}
nodeStyleModel.setFontFamilyName(fp.fontName);
nodeStyleModel.setFontSize(fp.fontSize);
nodeStyleModel.setItalic(fp.isItalic);
nodeStyleModel.setBold(fp.isBold);
return;
}
return;
}
}
private void registerAttributeHandlers(final ReadManager reader) {
final IAttributeHandler colorHandler = new IAttributeHandler() {
public void setAttribute(final Object userObject, final String value) {
if (value.length() == 7) {
final NodeModel node = (NodeModel) userObject;
NodeStyleModel.setColor(node, ColorUtils.stringToColor(value));
}
}
};
reader.addAttributeHandler(NodeBuilder.XML_NODE, "COLOR", colorHandler);
reader.addAttributeHandler(NodeBuilder.XML_STYLENODE, "COLOR", colorHandler);
final IAttributeHandler bgHandler = new IAttributeHandler() {
public void setAttribute(final Object userObject, final String value) {
if (value.length() == 7) {
final NodeModel node = (NodeModel) userObject;
NodeStyleModel.setBackgroundColor(node, ColorUtils.stringToColor(value));
}
}
};
reader.addAttributeHandler(NodeBuilder.XML_NODE, "BACKGROUND_COLOR", bgHandler);
reader.addAttributeHandler(NodeBuilder.XML_STYLENODE, "BACKGROUND_COLOR", bgHandler);
final IAttributeHandler styleHandler = new IAttributeHandler() {
public void setAttribute(final Object userObject, final String value) {
final NodeModel node = (NodeModel) userObject;
NodeStyleModel.setShape(node, value);
}
};
reader.addAttributeHandler(NodeBuilder.XML_NODE, "STYLE", styleHandler);
reader.addAttributeHandler(NodeBuilder.XML_STYLENODE, "STYLE", styleHandler);
reader.addAttributeHandler("font", "SIZE", new IAttributeHandler() {
public void setAttribute(final Object userObject, final String value) {
final FontProperties fp = (FontProperties) userObject;
fp.fontSize = Integer.parseInt(value.toString());
}
});
reader.addAttributeHandler("font", "NAME", new IAttributeHandler() {
public void setAttribute(final Object userObject, final String value) {
final FontProperties fp = (FontProperties) userObject;
fp.fontName = value;
}
});
reader.addAttributeHandler("font", "BOLD", new IAttributeHandler() {
public void setAttribute(final Object userObject, final String value) {
final FontProperties fp = (FontProperties) userObject;
fp.isBold = value.equals("true");
}
});
reader.addAttributeHandler("font", "ITALIC", new IAttributeHandler() {
public void setAttribute(final Object userObject, final String value) {
final FontProperties fp = (FontProperties) userObject;
fp.isItalic = value.equals("true");
}
});
final IAttributeHandler nodenumberingHandler = new IAttributeHandler() {
public void setAttribute(final Object userObject, final String value) {
final NodeModel node = (NodeModel) userObject;
NodeStyleModel.setNodeNumbering(node, value.equals("true"));
}
};
reader.addAttributeHandler(NodeBuilder.XML_NODE, "NUMBERED", nodenumberingHandler);
reader.addAttributeHandler(NodeBuilder.XML_STYLENODE, "NUMBERED", nodenumberingHandler);
final IAttributeHandler formatHandler = new IAttributeHandler() {
public void setAttribute(final Object userObject, final String value) {
final NodeModel node = (NodeModel) userObject;
NodeStyleModel.setNodeFormat(node, value);
}
};
reader.addAttributeHandler(NodeBuilder.XML_NODE, "FORMAT", formatHandler);
reader.addAttributeHandler(NodeBuilder.XML_STYLENODE, "FORMAT", formatHandler);
if (FreeplaneVersion.getVersion().isOlderThan(new FreeplaneVersion(1, 3, 0))) {
// compatibility for a view 1.2.X preview versions - remove after release 1.3
reader.addAttributeHandler(NodeBuilder.XML_NODE, "TEMPLATE", formatHandler);
reader.addAttributeHandler(NodeBuilder.XML_STYLENODE, "TEMPLATE", formatHandler);
}
final IAttributeHandler nodeMaxNodeWidthHandler = new IAttributeHandler() {
public void setAttribute(final Object userObject, final String value) {
final NodeModel node = (NodeModel) userObject;
NodeSizeModel.setNodeMaxNodeWidth(node, Integer.valueOf(value));
}
};
reader.addAttributeHandler(NodeBuilder.XML_NODE, "MAX_WIDTH", nodeMaxNodeWidthHandler);
reader.addAttributeHandler(NodeBuilder.XML_STYLENODE, "MAX_WIDTH", nodeMaxNodeWidthHandler);
final IAttributeHandler nodeMinWidthHandler = new IAttributeHandler() {
public void setAttribute(final Object userObject, final String value) {
final NodeModel node = (NodeModel) userObject;
NodeSizeModel.setNodeMinWidth(node, Integer.valueOf(value));
}
};
reader.addAttributeHandler(NodeBuilder.XML_NODE, "MIN_WIDTH", nodeMinWidthHandler);
reader.addAttributeHandler(NodeBuilder.XML_STYLENODE, "MIN_WIDTH", nodeMinWidthHandler);
}
/**
*/
public void registerBy(final ReadManager reader, final WriteManager writer) {
reader.addElementHandler("font", this);
registerAttributeHandlers(reader);
writer.addAttributeWriter(NodeBuilder.XML_NODE, this);
writer.addAttributeWriter(NodeBuilder.XML_STYLENODE, this);
writer.addElementWriter(NodeBuilder.XML_NODE, this);
writer.addElementWriter(NodeBuilder.XML_STYLENODE, this);
writer.addExtensionElementWriter(NodeStyleModel.class, this);
writer.addExtensionAttributeWriter(NodeStyleModel.class, this);
writer.addExtensionAttributeWriter(NodeSizeModel.class, this);
}
public void setAttributes(final String tag, final Object node, final XMLElement attributes) {
}
public void writeAttributes(final ITreeWriter writer, final Object userObject, final String tag) {
final boolean forceFormatting = Boolean.TRUE.equals(writer.getHint(MapWriter.WriterHint.FORCE_FORMATTING));
if (!forceFormatting) {
return;
}
final NodeModel node = (NodeModel) userObject;
writeAttributes(writer, node, (NodeStyleModel)null, true);
writeAttributes(writer, node, (NodeSizeModel)null, true);
}
public void writeAttributes(final ITreeWriter writer, final Object userObject, final IExtension extension) {
final boolean forceFormatting = Boolean.TRUE.equals(writer.getHint(MapWriter.WriterHint.FORCE_FORMATTING));
if (forceFormatting) {
return;
}
if(extension instanceof NodeStyleModel){
final NodeStyleModel style = (NodeStyleModel) extension;
writeAttributes(writer, null, style, false);
return;
}
if(extension instanceof NodeSizeModel){
final NodeSizeModel size = (NodeSizeModel) extension;
writeAttributes(writer, null, size, false);
return;
}
}
private void writeAttributes(final ITreeWriter writer, final NodeModel node, final NodeStyleModel style,
final boolean forceFormatting) {
final Color color = forceFormatting ? nsc.getColor(node) : style.getColor();
if (color != null) {
writer.addAttribute("COLOR", ColorUtils.colorToString(color));
}
final Color backgroundColor = forceFormatting ? nsc.getBackgroundColor(node) : style.getBackgroundColor();
if (backgroundColor != null) {
writer.addAttribute("BACKGROUND_COLOR", ColorUtils.colorToString(backgroundColor));
}
final String shape = forceFormatting ? nsc.getShape(node) : style.getShape();
if (shape != null) {
writer.addAttribute("STYLE", shape);
}
final Boolean numbered = forceFormatting ? nsc.getNodeNumbering(node) : style.getNodeNumbering();
if (numbered != null && numbered) {
writer.addAttribute("NUMBERED", numbered.toString());
}
final String format = forceFormatting ? nsc.getNodeFormat(node) : style.getNodeFormat();
if (format != null) {
writer.addAttribute("FORMAT", format);
}
}
private void writeAttributes(final ITreeWriter writer, final NodeModel node, final NodeSizeModel size,
final boolean forceFormatting) {
final int maxTextWidth = forceFormatting ? nsc.getMaxWidth(node) : size.getMaxNodeWidth();
if (maxTextWidth != NodeSizeModel.NOT_SET) {
writer.addAttribute("MAX_WIDTH", Integer.toString(maxTextWidth));
}
final int minTextWidth = forceFormatting ? nsc.getMinWidth(node) : size.getMinNodeWidth();
if (minTextWidth != NodeSizeModel.NOT_SET) {
writer.addAttribute("MIN_WIDTH", Integer.toString(minTextWidth));
}
}
public void writeContent(final ITreeWriter writer, final Object userObject, final String tag) throws IOException {
final boolean forceFormatting = Boolean.TRUE.equals(writer.getHint(MapWriter.WriterHint.FORCE_FORMATTING));
if (!forceFormatting) {
return;
}
final NodeModel node = (NodeModel) userObject;
writeContent(writer, node, null, true);
}
public void writeContent(final ITreeWriter writer, final Object userObject, final IExtension extension)
throws IOException {
final boolean forceFormatting = Boolean.TRUE.equals(writer.getHint(MapWriter.WriterHint.FORCE_FORMATTING));
if (forceFormatting) {
return;
}
final NodeStyleModel style = (NodeStyleModel) extension;
writeContent(writer, null, style, false);
}
private void writeContent(final ITreeWriter writer, final NodeModel node, final NodeStyleModel style,
final boolean forceFormatting) throws IOException {
if (forceFormatting || style != null) {
final XMLElement fontElement = new XMLElement();
fontElement.setName("font");
boolean isRelevant = forceFormatting;
final String fontFamilyName = forceFormatting ? nsc.getFontFamilyName(node) : style.getFontFamilyName();
if (fontFamilyName != null) {
fontElement.setAttribute("NAME", fontFamilyName);
isRelevant = true;
}
final Integer fontSize = forceFormatting ? Integer.valueOf(nsc.getFontSize(node)) : style.getFontSize();
if (fontSize != null) {
fontElement.setAttribute("SIZE", Integer.toString(fontSize));
isRelevant = true;
}
final Boolean bold = forceFormatting ? Boolean.valueOf(nsc.isBold(node)) : style.isBold();
if (bold != null) {
fontElement.setAttribute("BOLD", bold ? "true" : "false");
isRelevant = true;
}
final Boolean italic = forceFormatting ? Boolean.valueOf(nsc.isItalic(node)) : style.isItalic();
if (italic != null) {
fontElement.setAttribute("ITALIC", italic ? "true" : "false");
isRelevant = true;
}
if (isRelevant) {
writer.addElement(style, fontElement);
}
}
}
}