/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2009, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotoolkit.display2d.ext;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.awt.Paint;
import java.awt.Stroke;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.SwingConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.geotoolkit.display.PortrayalException;
import org.geotoolkit.display2d.canvas.J2DCanvas;
import org.geotoolkit.display2d.ext.grid.DefaultGridTemplate;
import org.geotoolkit.display2d.ext.grid.GraphicGridJ2D;
import org.geotoolkit.display2d.ext.grid.GridTemplate;
import org.geotoolkit.display2d.ext.image.DefaultImageTemplate;
import org.geotoolkit.display2d.ext.image.GraphicImageJ2D;
import org.geotoolkit.display2d.ext.image.ImageTemplate;
import org.geotoolkit.display2d.ext.legend.DefaultLegendTemplate;
import org.geotoolkit.display2d.ext.legend.GraphicLegendJ2D;
import org.geotoolkit.display2d.ext.legend.LegendTemplate;
import org.geotoolkit.display2d.ext.northarrow.DefaultNorthArrowTemplate;
import org.geotoolkit.display2d.ext.northarrow.GraphicNorthArrowJ2D;
import org.geotoolkit.display2d.ext.northarrow.NorthArrowTemplate;
import org.geotoolkit.display2d.ext.scalebar.DefaultScaleBarTemplate;
import org.geotoolkit.display2d.ext.scalebar.GraphicScaleBarJ2D;
import org.geotoolkit.display2d.ext.scalebar.ScaleBarTemplate;
import org.geotoolkit.display2d.ext.text.DefaultTextTemplate;
import org.geotoolkit.display2d.ext.text.GraphicTextJ2D;
import org.geotoolkit.display2d.ext.text.TextTemplate;
import org.geotoolkit.display2d.service.PortrayalExtension;
import org.apache.sis.referencing.CRS;
import org.geotoolkit.referencing.IdentifiedObjects;
import org.apache.sis.util.ObjectConverters;
import org.apache.sis.util.logging.Logging;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.util.FactoryException;
import org.apache.sis.measure.Units;
import org.apache.sis.util.UnconvertibleObjectException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
*
* @author Johann Sorel (Geomatys)
* @module
*/
public final class DecorationXMLParser {
private static final Logger LOGGER = Logging.getLogger("org.geotoolkit.display2d.ext");
private static final String TAG_DECORATION = "Decoration";
private static final String TAG_BACKGROUND = "Background";
private static final String TAG_PARAMETER = "Parameter";
private static final String TAG_MAIN = "Main";
private static final String TAG_SECOND = "Second";
private static final String ATT_NAME = "name";
private static final String PARAM_POSITION = "position";
private static final String PARAM_OFFSET_X = "offset-x";
private static final String PARAM_OFFSET_Y = "offset-y";
private static final String PARAM_STROKE_COLOR = "stroke-color";
private static final String PARAM_STROKE_OPACITY = "stroke-opacity";
private static final String PARAM_STROKE_WIDTH = "stroke-width";
private static final String PARAM_STROKE_DASHES = "stroke-dashes";
private static final String PARAM_FILL_COLOR = "fill-color";
private static final String PARAM_FILL_OPACITY = "fill-opacity";
private static final String PARAM_INSETS = "insets";
private static final String PARAM_ROUND = "round";
private static final String PARAM_HEIGHT = "height";
private static final String PARAM_WIDTH = "width";
private static final String PARAM_SOURCE = "source";
private static final String PARAM_TEXT = "text";
private static final String PARAM_FONT = "font";
private static final String PARAM_GAP = "gap";
private static final String PARAM_MAIN_FONT = "main-font";
private static final String PARAM_SECOND_FONT = "second-font";
private static final String PARAM_GLYPH_HEIGHT = "glyph-height";
private static final String PARAM_GLYPH_WIDTH = "glyph-width";
private static final String PARAM_LAYER_NAME = "layer-name";
private static final String PARAM_UNIT = "unit";
private static final String PARAM_CRS = "crs";
private static final String TYPE_IMAGE = "image";
private static final String TYPE_TEXT = "text";
private static final String TYPE_LEGEND = "legend";
private static final String TYPE_COMPAS = "compas";
private static final String TYPE_SCALE_NUMERIC = "scalebar-numeric";
private static final String TYPE_SCALE_GRAPHIC = "scalebar-graphic";
private static final String TYPE_GRID = "grid";
private static final String POSTION_NORTH = "north";
private static final String POSTION_NORTH_EAST = "north-east";
private static final String POSTION_NORTH_WEST = "north-west";
private static final String POSTION_SOUTH = "south";
private static final String POSTION_SOUTH_EAST = "south-east";
private static final String POSTION_SOUTH_WEST = "south-west";
private static final String POSTION_EAST = "east";
private static final String POSTION_WEST = "west";
private static final String POSTION_CENTER = "center";
private DecorationXMLParser() {
}
// Reading -----------------------------------------------------------------
public static PortrayalExtension read(final File configFile)
throws ParserConfigurationException, SAXException, IOException {
if (!configFile.exists()) {
return null;
}
final DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance();
final DocumentBuilder constructeur = fabrique.newDocumentBuilder();
final Document document = constructeur.parse(configFile);
return read(document.getDocumentElement());
}
public static PortrayalExtension read(final Node root)
throws ParserConfigurationException, SAXException, IOException {
final NodeList nodes = ((Element) root).getElementsByTagName(TAG_DECORATION);
final DecorationExtension ext = new DecorationExtension();
for (int i = 0, n = nodes.getLength(); i < n; i++) {
final Element decoNode = (Element) nodes.item(i);
parseDecoration(ext, decoNode);
}
return ext;
}
private static void parseDecoration(final DecorationExtension deco, final Element decoNode) {
final String type = decoNode.getAttribute(ATT_NAME);
final Map<String, String> params = parseParameters(decoNode);
final BackgroundTemplate background = parseBackground(decoNode);
final Map<String, Object> parsed = new HashMap<>();
//offsets are the same for everyone
parsed.put(PARAM_OFFSET_X, parseInteger(params.get(PARAM_OFFSET_X), 0));
parsed.put(PARAM_OFFSET_Y, parseInteger(params.get(PARAM_OFFSET_Y), 0));
if (type.equalsIgnoreCase(TYPE_COMPAS)) {
final NorthArrowTemplate template = new DefaultNorthArrowTemplate(
background,
parseURL(params.get(PARAM_SOURCE), DecorationXMLParser.class.getResource("/org/geotoolkit/icon/boussole.svg")),
new Dimension(
parseInteger(params.get(PARAM_WIDTH), 100),
parseInteger(params.get(PARAM_HEIGHT), 100)));
parsed.put(ATT_NAME, TYPE_COMPAS);
parsed.put(TYPE_COMPAS, template);
parsed.put(PARAM_POSITION, parsePosition(params.get(PARAM_POSITION), SwingConstants.NORTH_EAST));
} else if (type.equalsIgnoreCase(TYPE_GRID)) {
CoordinateReferenceSystem crs = null;
if (params.get(PARAM_CRS) != null) {
try {
crs = CRS.forCode(params.get(PARAM_CRS));
} catch (FactoryException ex) {
LOGGER.log(Level.WARNING, null, ex);
}
}
Stroke mainLineStroke = new BasicStroke(2);
Paint mainLinePaint = Color.DARK_GRAY;
Font mainLineFont = new Font("serial", Font.BOLD, 14);
Stroke secondLineStroke = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10, new float[]{5, 5}, 0);
Paint secondLinePaint = Color.GRAY;
Font secondLineFont = new Font("serial", Font.BOLD, 14);
NodeList nodes = decoNode.getElementsByTagName(TAG_MAIN);
for (int i = 0, n = nodes.getLength(); i < n; i++) {
final Element sub = (Element) nodes.item(i);
final Map<String, String> subParams = parseParameters(sub);
mainLineStroke = parseStroke(subParams.get(PARAM_STROKE_WIDTH), subParams.get(PARAM_STROKE_DASHES));
mainLinePaint = parseColor(subParams.get(PARAM_STROKE_COLOR), subParams.get(PARAM_STROKE_OPACITY), Color.DARK_GRAY);
mainLineFont = parseFont(subParams.get(PARAM_FONT));
}
nodes = decoNode.getElementsByTagName(TAG_SECOND);
for (int i = 0, n = nodes.getLength(); i < n; i++) {
final Element sub = (Element) nodes.item(i);
final Map<String, String> subParams = parseParameters(sub);
secondLineStroke = parseStroke(subParams.get(PARAM_STROKE_WIDTH), subParams.get(PARAM_STROKE_DASHES));
secondLinePaint = parseColor(subParams.get(PARAM_STROKE_COLOR), subParams.get(PARAM_STROKE_OPACITY), Color.DARK_GRAY);
secondLineFont = parseFont(subParams.get(PARAM_FONT));
}
final GridTemplate template = new DefaultGridTemplate(
crs,
mainLineStroke,
mainLinePaint,
secondLineStroke,
secondLinePaint,
mainLineFont,
mainLinePaint,
0,
new Color(0f, 0f, 0f, 0f),
secondLineFont,
secondLinePaint,
0,
new Color(0f, 0f, 0f, 0f));
parsed.put(ATT_NAME, TYPE_GRID);
parsed.put(TYPE_GRID, template);
} else if (type.equalsIgnoreCase(TYPE_IMAGE)) {
final URL source = parseURL(params.get(PARAM_SOURCE), null);
BufferedImage buffer;
try {
buffer = ImageIO.read(source);
} catch (Exception ex) {
LOGGER.log(Level.WARNING, null, ex);
buffer = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
}
final ImageTemplate template = new DefaultImageTemplate(background, buffer);
parsed.put(ATT_NAME, TYPE_IMAGE);
parsed.put(TYPE_IMAGE, template);
parsed.put(PARAM_POSITION, parsePosition(params.get(PARAM_POSITION), SwingConstants.NORTH_WEST));
} else if (type.equalsIgnoreCase(TYPE_LEGEND)) {
final LegendTemplate template = new DefaultLegendTemplate(
background,
parseInteger(params.get(PARAM_GAP), 2),
new Dimension(
parseInteger(params.get(PARAM_GLYPH_WIDTH), 30),
parseInteger(params.get(PARAM_GLYPH_HEIGHT), 20)),
parseFont(params.get(PARAM_SECOND_FONT)),
parseBoolean(params.get(PARAM_LAYER_NAME), true),
parseFont(params.get(PARAM_MAIN_FONT)));
parsed.put(ATT_NAME, TYPE_LEGEND);
parsed.put(TYPE_LEGEND, template);
parsed.put(PARAM_POSITION, parsePosition(params.get(PARAM_POSITION), SwingConstants.EAST));
} else if (type.equalsIgnoreCase(TYPE_SCALE_GRAPHIC)) {
String unit = params.get(PARAM_UNIT);
if (unit == null || unit.isEmpty()) {
unit = "km";
}
final ScaleBarTemplate template = new DefaultScaleBarTemplate(
background,
new Dimension(
parseInteger(params.get(PARAM_WIDTH), 250),
parseInteger(params.get(PARAM_HEIGHT), 30)),
10,
false,
5,
NumberFormat.getNumberInstance(),
Color.BLACK,
Color.BLACK,
Color.WHITE,
3,
true,
false,
new Font("Serial", Font.PLAIN, 12),
true,
Units.valueOf(unit));
parsed.put(ATT_NAME, TYPE_SCALE_GRAPHIC);
parsed.put(TYPE_SCALE_GRAPHIC, template);
parsed.put(PARAM_POSITION, parsePosition(params.get(PARAM_POSITION), SwingConstants.SOUTH_WEST));
} else if (type.equalsIgnoreCase(TYPE_SCALE_NUMERIC)) {
//not handle yet
} else if (type.equalsIgnoreCase(TYPE_TEXT)) {
String txt = params.get(PARAM_TEXT);
if (txt == null) {
txt = "";
}
final TextTemplate template = new DefaultTextTemplate(
background,
txt);
parsed.put(ATT_NAME, TYPE_TEXT);
parsed.put(TYPE_TEXT, template);
parsed.put(PARAM_POSITION, parsePosition(params.get(PARAM_POSITION), SwingConstants.SOUTH_WEST));
}
deco.decorations.add(parsed);
}
private static Map<String, String> parseParameters(final Element decoNode) {
final Map<String, String> params = new HashMap<String, String>();
final NodeList nodes = decoNode.getElementsByTagName(TAG_PARAMETER);
for (int i = 0, n = nodes.getLength(); i < n; i++) {
final Element paramNode = (Element) nodes.item(i);
params.put(
paramNode.getAttribute(ATT_NAME).trim().toLowerCase(),
paramNode.getTextContent().trim());
}
return params;
}
private static BackgroundTemplate parseBackground(final Element decoNode) {
final NodeList nodes = decoNode.getElementsByTagName(TAG_BACKGROUND);
if (nodes.getLength() > 0) {
final Element bgNode = (Element) nodes.item(0);
final Map<String, String> params = parseParameters(bgNode);
//parse values
final String strWidth = params.get(PARAM_STROKE_WIDTH);
final String strDashes = params.get(PARAM_STROKE_DASHES);
final String strStrokeColor = params.get(PARAM_STROKE_COLOR);
final String strStrokeOpacity = params.get(PARAM_STROKE_OPACITY);
final String strFillColor = params.get(PARAM_FILL_COLOR);
final String strFillOpacity = params.get(PARAM_FILL_OPACITY);
final String strInsets = params.get(PARAM_INSETS);
final String strRound = params.get(PARAM_ROUND);
final Color strokePaint = parseColor(strStrokeColor, strStrokeOpacity, Color.DARK_GRAY);
final Color fill = parseColor(strFillColor, strFillOpacity, Color.WHITE);
final int round = parseInteger(strRound, 12);
final Stroke stroke = parseStroke(strWidth, strDashes);
final Insets insets = parseInsets(strInsets, new Insets(5, 5, 5, 5));
return new DefaultBackgroundTemplate(stroke, strokePaint, fill, insets, round);
}
return null;
}
private static int parseInteger(final String str, final int fallback) {
if (str == null) {
return fallback;
}
try {
return Integer.parseInt(str);
} catch (NumberFormatException ex) {
LOGGER.log(Level.WARNING, "Not a valid integer : " + str, ex);
return fallback;
}
}
private static boolean parseBoolean(final String str, final boolean fallback) {
if (str == null) {
return fallback;
}
try {
return Boolean.parseBoolean(str);
} catch (NumberFormatException ex) {
LOGGER.log(Level.WARNING, "Not a valid boolean : " + str, ex);
return fallback;
}
}
private static float parseFloat(final String str, final int fallback) {
if (str == null) {
return fallback;
}
try {
return Float.parseFloat(str);
} catch (NumberFormatException ex) {
LOGGER.log(Level.WARNING, "Not a valid float : " + str, ex);
return fallback;
}
}
private static Font parseFont(final String strFont) {
return Font.decode(strFont);
}
private static Insets parseInsets(final String str, final Insets fallback) {
if (str == null) {
return fallback;
}
final String[] parts = str.split(",");
if (parts.length == 4) {
return new Insets(
parseInteger(parts[0], 5),
parseInteger(parts[1], 5),
parseInteger(parts[2], 5),
parseInteger(parts[3], 5));
} else {
return fallback;
}
}
private static Color parseColor(final String strColor, final String strOpacity, final Color fallback) {
if (strColor == null) {
return fallback;
}
Color color;
try {
color = ObjectConverters.convert(strColor, Color.class);
} catch (UnconvertibleObjectException e) {
Logging.recoverableException(LOGGER, DecorationXMLParser.class, "parseColor", e);
return null;
// TODO - do we really want to ignore?
}
if (color == null) {
return fallback;
}
if (strOpacity != null) {
float opa = parseFloat(strOpacity, 1);
if (opa < 0 || opa > 1) {
opa = 1;
}
color = new Color(color.getRed() / 256f, color.getGreen() / 256f, color.getBlue() / 256f, opa);
}
return color;
}
private static int parsePosition(final String str, final int fallback) {
if (POSTION_CENTER.equalsIgnoreCase(str)) {
return SwingConstants.CENTER;
} else if (POSTION_EAST.equalsIgnoreCase(str)) {
return SwingConstants.EAST;
} else if (POSTION_WEST.equalsIgnoreCase(str)) {
return SwingConstants.WEST;
} else if (POSTION_NORTH.equalsIgnoreCase(str)) {
return SwingConstants.NORTH;
} else if (POSTION_NORTH_EAST.equalsIgnoreCase(str)) {
return SwingConstants.NORTH_EAST;
} else if (POSTION_NORTH_WEST.equalsIgnoreCase(str)) {
return SwingConstants.NORTH_WEST;
} else if (POSTION_SOUTH.equalsIgnoreCase(str)) {
return SwingConstants.SOUTH;
} else if (POSTION_SOUTH_EAST.equalsIgnoreCase(str)) {
return SwingConstants.SOUTH_EAST;
} else if (POSTION_SOUTH_WEST.equalsIgnoreCase(str)) {
return SwingConstants.SOUTH_WEST;
} else {
return fallback;
}
}
private static URL parseURL(final String url, final URL fallback) {
if (url == null) {
return fallback;
}
try {
return new URL(url);
} catch (Exception ex) {
LOGGER.log(Level.WARNING, "Could not parse url", ex);
return fallback;
}
}
private static Stroke parseStroke(final String strWidth, final String strDashes) {
final int width = parseInteger(strWidth, 1);
if (strDashes != null && !strDashes.isEmpty()) {
final String[] parts = strDashes.split(",");
if (parts.length > 0) {
final float[] dashes = new float[parts.length];
for (int i = 0; i < parts.length; i++) {
dashes[i] = parseFloat(parts[i], 5);
}
return new BasicStroke(width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10, dashes, 0);
}
}
return new BasicStroke(width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);
}
// Writing -----------------------------------------------------------------
public static void write(final File file, final DecorationExtension extension) throws ParserConfigurationException {
final DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance();
final DocumentBuilder constructeur = fabrique.newDocumentBuilder();
final Document document = constructeur.newDocument();
final Element racine = document.createElement("config");
write(racine, document, extension);
}
public static void write(final Element node, final Document document,final DecorationExtension extension) {
Element el;
for (final Map<String, Object> params : extension.getParameters()) {
final String type = (String) params.get(ATT_NAME);
if (type.equalsIgnoreCase(TYPE_COMPAS)) {
final NorthArrowTemplate arrowTemplate = (NorthArrowTemplate) params.get(TYPE_COMPAS);
final Element deco = document.createElement(TAG_DECORATION);
deco.setAttribute(ATT_NAME, TYPE_COMPAS);
final Element bg = encode(document, arrowTemplate.getBackground());
if(bg != null) deco.appendChild(bg);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_POSITION);
el.setTextContent(encodePosition((Integer) params.get(PARAM_POSITION)));
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_OFFSET_X);
el.setTextContent(params.get(PARAM_OFFSET_X).toString());
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_OFFSET_Y);
el.setTextContent(params.get(PARAM_OFFSET_Y).toString());
deco.appendChild(el);
node.appendChild(deco);
}
else if (type.equalsIgnoreCase(TYPE_GRID)) {
final GridTemplate gridTemplate = (GridTemplate) params.get(TYPE_GRID);
final Element deco = document.createElement(TAG_DECORATION);
deco.setAttribute(ATT_NAME, TYPE_GRID);
try {
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_CRS);
el.setTextContent(IdentifiedObjects.lookupIdentifier(gridTemplate.getCRS(), true));
deco.appendChild(el);
} catch (FactoryException ex) {
LOGGER.log(Level.WARNING, null, ex);
}
final Element main = document.createElement(TAG_MAIN);
final BasicStroke mainStroke = (BasicStroke)gridTemplate.getMainLineStroke();
final Color paint = (Color)gridTemplate.getMainLinePaint();
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_FONT);
el.setTextContent(gridTemplate.getMainLabelFont().toString());
main.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_STROKE_WIDTH);
el.setTextContent(String.valueOf(mainStroke.getLineWidth()));
main.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_STROKE_DASHES);
el.setTextContent(encode(mainStroke.getDashArray()));
main.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_STROKE_COLOR);
el.setTextContent(encode(paint));
main.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_STROKE_OPACITY);
el.setTextContent(String.valueOf(paint.getAlpha()/255));
main.appendChild(el);
deco.appendChild(main);
final Element second = document.createElement(TAG_MAIN);
final BasicStroke secondStroke = (BasicStroke)gridTemplate.getLineStroke();
final Color secondPaint = (Color)gridTemplate.getLinePaint();
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_FONT);
el.setTextContent(gridTemplate.getMainLabelFont().toString());
second.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_STROKE_WIDTH);
el.setTextContent(String.valueOf(mainStroke.getLineWidth()));
second.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_STROKE_DASHES);
el.setTextContent(encode(mainStroke.getDashArray()));
second.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_STROKE_COLOR);
el.setTextContent(encode(paint));
second.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_STROKE_OPACITY);
el.setTextContent(String.valueOf(paint.getAlpha()/255));
second.appendChild(el);
deco.appendChild(second);
node.appendChild(deco);
}
// else if (type.equalsIgnoreCase(TYPE_IMAGE)) {
// final ImageTemplate imgTemplate = (ImageTemplate) params.get(TYPE_IMAGE);
// final PositionedGraphic2D imageDeco = new GraphicImageJ2D(canvas, imgTemplate);
// imageDeco.setPosition((Integer) params.get(PARAM_POSITION));
// imageDeco.setOffset((Integer) params.get(PARAM_OFFSET_X), (Integer) params.get(PARAM_OFFSET_Y));
//
// }
else if (type.equalsIgnoreCase(TYPE_LEGEND)) {
final LegendTemplate legendTemplate = (LegendTemplate) params.get(TYPE_LEGEND);
final Element deco = document.createElement(TAG_DECORATION);
deco.setAttribute(ATT_NAME, TYPE_LEGEND);
final Element bg = encode(document, legendTemplate.getBackground());
if(bg != null) deco.appendChild(bg);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_GAP);
el.setTextContent(String.valueOf(legendTemplate.getGapSize()));
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_LAYER_NAME);
el.setTextContent(String.valueOf(legendTemplate.isLayerVisible()));
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_MAIN_FONT);
el.setTextContent(legendTemplate.getLayerFont().toString());
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_SECOND_FONT);
el.setTextContent(legendTemplate.getRuleFont().toString());
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_GLYPH_HEIGHT);
el.setTextContent(String.valueOf(legendTemplate.getGlyphSize().height));
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_GLYPH_WIDTH);
el.setTextContent(String.valueOf(legendTemplate.getGlyphSize().width));
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_POSITION);
el.setTextContent(encodePosition((Integer) params.get(PARAM_POSITION)));
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_OFFSET_X);
el.setTextContent(params.get(PARAM_OFFSET_X).toString());
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_OFFSET_Y);
el.setTextContent(params.get(PARAM_OFFSET_Y).toString());
deco.appendChild(el);
node.appendChild(deco);
}
else if (type.equalsIgnoreCase(TYPE_SCALE_GRAPHIC)) {
final ScaleBarTemplate scalebarTemplate = (ScaleBarTemplate) params.get(TYPE_SCALE_GRAPHIC);
final Element deco = document.createElement(TAG_DECORATION);
deco.setAttribute(ATT_NAME, TYPE_SCALE_GRAPHIC);
final Element bg = encode(document, scalebarTemplate.getBackground());
if(bg != null) deco.appendChild(bg);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_HEIGHT);
el.setTextContent(String.valueOf(scalebarTemplate.getSize().height));
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_WIDTH);
el.setTextContent(String.valueOf(scalebarTemplate.getSize().width));
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_POSITION);
el.setTextContent(encodePosition((Integer) params.get(PARAM_POSITION)));
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_OFFSET_X);
el.setTextContent(params.get(PARAM_OFFSET_X).toString());
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_OFFSET_Y);
el.setTextContent(params.get(PARAM_OFFSET_Y).toString());
deco.appendChild(el);
node.appendChild(deco);
}
// else if (type.equalsIgnoreCase(TYPE_SCALE_NUMERIC)) {
// //not handle yet
// }
else if (type.equalsIgnoreCase(TYPE_TEXT)) {
final TextTemplate textTemplate = (TextTemplate) params.get(TYPE_TEXT);
final Element deco = document.createElement(TAG_DECORATION);
deco.setAttribute(ATT_NAME, TYPE_TEXT);
final Element bg = encode(document, textTemplate.getBackground());
if(bg != null) deco.appendChild(bg);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_TEXT);
el.setTextContent(textTemplate.getText());
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_POSITION);
el.setTextContent(encodePosition((Integer) params.get(PARAM_POSITION)));
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_OFFSET_X);
el.setTextContent(params.get(PARAM_OFFSET_X).toString());
deco.appendChild(el);
el = document.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_OFFSET_Y);
el.setTextContent(params.get(PARAM_OFFSET_Y).toString());
deco.appendChild(el);
node.appendChild(deco);
}
}
}
private static Element encode(final Document doc, final BackgroundTemplate template){
if(template == null) return null;
final Element bg = doc.createElement(TAG_BACKGROUND);
Element el;
//stroke shape -------------------------------
final BasicStroke stroke = (BasicStroke)template.getBackgroundStroke();
el = doc.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_STROKE_WIDTH);
el.setTextContent(String.valueOf(stroke.getLineWidth()));
bg.appendChild(el);
final float[] dashes = stroke.getDashArray();
el = doc.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_STROKE_DASHES);
el.setTextContent(encode(dashes));
bg.appendChild(el);
//stroke paint --------------------------
final Color stkColor = (Color)template.getBackgroundStrokePaint();
el = doc.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_STROKE_COLOR);
el.setTextContent(encode(stkColor));
bg.appendChild(el);
el = doc.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_STROKE_OPACITY);
el.setTextContent(String.valueOf(stkColor.getAlpha()/255));
bg.appendChild(el);
//inside paint -------------------------------
final Color fill = (Color)template.getBackgroundPaint();
el = doc.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_FILL_COLOR);
el.setTextContent(encode(fill));
bg.appendChild(el);
el = doc.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_FILL_OPACITY);
el.setTextContent(String.valueOf(fill.getAlpha()/255));
bg.appendChild(el);
// insets ------------------------------------
final Insets insets = template.getBackgroundInsets();
el = doc.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_INSETS);
el.setTextContent(encode(insets));
bg.appendChild(el);
//round border -------------------------------
final int round = template.getRoundBorder();
el = doc.createElement(TAG_PARAMETER);
el.setAttribute(ATT_NAME, PARAM_ROUND);
el.setTextContent(String.valueOf(round));
bg.appendChild(el);
return bg;
}
private static String encode(final float dashes[]){
StringBuilder sb = new StringBuilder();
for(int i=0;i<dashes.length;i++){
sb.append(dashes[i]);
if(i < (dashes.length-1)){
sb.append(',');
}
}
return sb.toString();
}
private static String encode(final Color color){
String redCode = Integer.toHexString(color.getRed());
String greenCode = Integer.toHexString(color.getGreen());
String blueCode = Integer.toHexString(color.getBlue());
if (redCode.length() == 1) {
redCode = "0" + redCode;
}
if (greenCode.length() == 1) {
greenCode = "0" + greenCode;
}
if (blueCode.length() == 1) {
blueCode = "0" + blueCode;
}
final String colorCode = "#" + redCode + greenCode + blueCode;
return colorCode;
}
private static String encode(final Insets insets){
final StringBuilder sb = new StringBuilder();
sb.append(insets.top).append(',').append(insets.left).append(',').append(insets.bottom).append(',').append(insets.right);
return sb.toString();
}
private static String encodePosition(final int position){
switch(position){
case SwingConstants.CENTER : return POSTION_CENTER;
case SwingConstants.EAST : return POSTION_EAST;
case SwingConstants.WEST : return POSTION_WEST;
case SwingConstants.NORTH : return POSTION_NORTH;
case SwingConstants.NORTH_EAST : return POSTION_NORTH_EAST;
case SwingConstants.NORTH_WEST : return POSTION_NORTH_WEST;
case SwingConstants.SOUTH : return POSTION_SOUTH;
case SwingConstants.SOUTH_EAST : return POSTION_SOUTH_EAST;
case SwingConstants.SOUTH_WEST : return POSTION_SOUTH_WEST;
default : return POSTION_CENTER;
}
}
public static class DecorationExtension implements PortrayalExtension {
private final List<Map<String, Object>> decorations = new ArrayList<>();
List<Map<String, Object>> getParameters() {
return decorations;
}
@Override
public void completeCanvas(final J2DCanvas canvas) throws PortrayalException {
for (final Map<String, Object> params : decorations) {
final String type = (String) params.get(ATT_NAME);
if (type.equalsIgnoreCase(TYPE_COMPAS)) {
final NorthArrowTemplate arrowTemplate = (NorthArrowTemplate) params.get(TYPE_COMPAS);
final PositionedGraphic2D compasDeco = new GraphicNorthArrowJ2D(canvas, arrowTemplate);
compasDeco.setPosition((Integer) params.get(PARAM_POSITION));
compasDeco.setOffset((Integer) params.get(PARAM_OFFSET_X), (Integer) params.get(PARAM_OFFSET_Y));
canvas.getContainer().getRoot().getChildren().add(compasDeco);
} else if (type.equalsIgnoreCase(TYPE_GRID)) {
final GridTemplate gridTemplate = (GridTemplate) params.get(TYPE_GRID);
final GraphicGridJ2D girdDeco = new GraphicGridJ2D(canvas, gridTemplate);
canvas.getContainer().getRoot().getChildren().add(girdDeco);
} else if (type.equalsIgnoreCase(TYPE_IMAGE)) {
final ImageTemplate imgTemplate = (ImageTemplate) params.get(TYPE_IMAGE);
final PositionedGraphic2D imageDeco = new GraphicImageJ2D(canvas, imgTemplate);
imageDeco.setPosition((Integer) params.get(PARAM_POSITION));
imageDeco.setOffset((Integer) params.get(PARAM_OFFSET_X), (Integer) params.get(PARAM_OFFSET_Y));
canvas.getContainer().getRoot().getChildren().add(imageDeco);
} else if (type.equalsIgnoreCase(TYPE_LEGEND)) {
final LegendTemplate legendTemplate = (LegendTemplate) params.get(TYPE_LEGEND);
final GraphicLegendJ2D legendDeco = new GraphicLegendJ2D(canvas, legendTemplate);
legendDeco.setPosition((Integer) params.get(PARAM_POSITION));
legendDeco.setOffset((Integer) params.get(PARAM_OFFSET_X), (Integer) params.get(PARAM_OFFSET_Y));
canvas.getContainer().getRoot().getChildren().add(legendDeco);
} else if (type.equalsIgnoreCase(TYPE_SCALE_GRAPHIC)) {
final ScaleBarTemplate template = (ScaleBarTemplate) params.get(TYPE_SCALE_GRAPHIC);
final GraphicScaleBarJ2D scaleDeco = new GraphicScaleBarJ2D(canvas);
scaleDeco.setTemplate(template);
scaleDeco.setPosition((Integer) params.get(PARAM_POSITION));
scaleDeco.setOffset((Integer) params.get(PARAM_OFFSET_X), (Integer) params.get(PARAM_OFFSET_Y));
canvas.getContainer().getRoot().getChildren().add(scaleDeco);
} else if (type.equalsIgnoreCase(TYPE_SCALE_NUMERIC)) {
//not handle yet
} else if (type.equalsIgnoreCase(TYPE_TEXT)) {
final TextTemplate textTemplate = (TextTemplate) params.get(TYPE_TEXT);
final PositionedGraphic2D textDeco = new GraphicTextJ2D(canvas, textTemplate);
textDeco.setPosition((Integer) params.get(PARAM_POSITION));
textDeco.setOffset((Integer) params.get(PARAM_OFFSET_X), (Integer) params.get(PARAM_OFFSET_Y));
canvas.getContainer().getRoot().getChildren().add(textDeco);
}
}
}
}
}