/*
* Licensed Materials - Property of Rogue Wave Software, Inc.
* © Copyright Rogue Wave Software, Inc. 2014, 2017
* © Copyright IBM Corp. 2009, 2014
* © Copyright ILOG 1996, 2009
* All Rights Reserved.
*
* Note to U.S. Government Users Restricted Rights:
* The Software and Documentation were developed at private expense and
* are "Commercial Items" as that term is defined at 48 CFR 2.101,
* consisting of "Commercial Computer Software" and
* "Commercial Computer Software Documentation", as such terms are
* used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
* as applicable.
*/
package xmlgrapher;
import java.awt.Color;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import ilog.views.IlvGrapher;
import ilog.views.IlvGraphic;
import ilog.views.IlvHandlesSelection;
import ilog.views.IlvLinkImage;
import ilog.views.IlvManagerView;
import ilog.views.IlvRect;
import ilog.views.IlvStroke;
import ilog.views.IlvTransformer;
import ilog.views.graphic.IlvIcon;
import ilog.views.graphic.IlvPolylineLinkImage;
/**
* A view that can display an XML file
* describing a network. This is a simplified version that reads the
* data from an XML file describing the locations using x/y coordinates.
*/
public class XmlGrapher extends IlvManagerView
{
// Indexes for Layers
final static int MAP_LAYER = 0;
final static int LINK_LAYER = 1;
final static int NODE_LAYER = 2;
// URL of XML file loaded
private URL _network;
// Size of node defined in XML file
private double _nodeSize = 35;
// Size of font defined in XML file
private int _fontSize = 12;
// URL of the map
private String _mapurl;
public static boolean verbose = false;
/**
* Creates an XmlGrapher.
*/
public XmlGrapher()
{
super(new IlvGrapher());
setAntialiasing(true);
setKeepingAspectRatio(true);
setBackground(Color.white);
// Settings parameters for selection handles
IlvHandlesSelection.defaultHandleColor = Color.black;
IlvHandlesSelection.defaultHandleBackgroundColor = Color.white;
IlvHandlesSelection.defaultHandleShape = IlvHandlesSelection.SQUARE_SHAPE;
}
/**
* Returns the URL of the XML file currenlty loaded.
*/
public URL getNetwork()
{
return _network;
}
/**
* Reads the XML network file.
* This method reads the XML file and populate
* the grapher.
*/
public void setNetwork(URL url)
{
this._network = url;
verbose ("setting Network " + _network);
getManager().setContentsAdjusting(true);
try {
// Deletes everything in the grapher.
getManager().deleteAll(false);
for (int i = 0 ; i < getManager().getLayersCount(); i++)
getManager().removeLayer(0, false);
// Creates 3 layers, Map, Nodes and Links
getManager().setNumberOfLayer(3);
try {
verbose ("Reading XML file");
//parse XML file
Document doc =
DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(url.toString());
Element root = doc.getDocumentElement();
// Alpha (transparency) for the map layer
float mapAlpha = (float) getDoubleAttribute(root, "map_alpha", 1.0f);
getManager().getManagerLayer(MAP_LAYER).setAlpha(mapAlpha);
// URL of the map file
_mapurl = root.getAttribute("map");
if (_mapurl != null && _mapurl.length() != 0) {
try {
setMap(new URL(_network, _mapurl));
} catch (MalformedURLException mue) {
setMap(null);
}
}
else
setMap(null);
// size of nodes and size of font
_nodeSize = getDoubleAttribute(root, "nodeSize", 35.f);
_fontSize = (int)getDoubleAttribute(root, "fontSize", 8);
// read <node> objects
for (Node node = root.getFirstChild();
node != null ;
node = node.getNextSibling()) {
if (node.getNodeName().equals("node")) {
addNode((Element)node);
}
}
// read <link> objects
for (Node node = root.getFirstChild();
node != null ;
node = node.getNextSibling()) {
if (node.getNodeName().equals("link")) {
addLink((Element)node);
}
}
verbose ("Nodes added");
} catch (Exception e) {
e.printStackTrace();
}
verbose ("Layout Done");
setTransformer(new IlvTransformer());
getManager().getManagerLayer(MAP_LAYER).setName("background Map");
getManager().getManagerLayer(LINK_LAYER).setName("Links");
getManager().getManagerLayer(NODE_LAYER).setName("Cities");
if (getParent()!=null)
repaint();
} finally {
getManager().setContentsAdjusting(false);
verbose ("setNetwork Done");
}
}
/**
* Creates the graphic link
* based on the XML link element.
* @param linkElement the XML link element
*/
private void addLink(Element linkElement)
{
Element origin = getOrigin(linkElement);
Element destination = getDestination(linkElement);
if (origin == null || destination == null)
throw new IllegalArgumentException("no origin or dest");
// Look for origin and destination nodes
String idf = origin.getAttribute("idref");
String idt = destination.getAttribute("idref");
IlvGraphic fromg = getManager().getObject(idf);
IlvGraphic tog = getManager().getObject(idt);
if (fromg == null)
throw new IllegalArgumentException("bad ids " + idf);
if (tog == null)
throw new IllegalArgumentException("bad ids " + idt);
// Create the link
IlvLinkImage link = new IlvPolylineLinkImage(fromg, tog, false, null);
// Sets the link style
setLinkStyle(link, getElement(linkElement, "style"));
// Sets the end-cap option
link.setEndCap(IlvStroke.CAP_BUTT);
// Adds the link
((IlvGrapher)getManager()).addLink(link, LINK_LAYER, false);
}
/**
* Creates the graphic object based
* on the XML node element.
* @param nodeElement the XML node element
*/
private void addNode(Element nodeElement)
{
String label = nodeElement.getAttribute("label");
String positionX = getLocation(nodeElement).getAttribute("x");
String positionY = getLocation(nodeElement).getAttribute("y");
String id = nodeElement.getAttribute("ID");
double x = Double.valueOf(positionX).doubleValue();
double y = Double.valueOf(positionY).doubleValue();
IlvRect r = new IlvRect(x, y, _nodeSize, _nodeSize);
// Creates the node
GrapherNode obj = new GrapherNode(r, label);
obj.setFontSize(_fontSize);
obj.setBackground(Color.lightGray);
((IlvGrapher)getManager()).addNode(obj, NODE_LAYER, false);
obj.setName(id);
}
/**
* Sets the style of the specified link based on the
* style element.
*/
private static void setLinkStyle(IlvLinkImage link, Element style)
{
link.setLineWidth(1);
link.setMaximumLineWidth(1);
if (style == null)
return;
String fill = style.getAttribute("fill");
if (fill != null) link.setForeground(stringToColor(fill));
String width = style.getAttribute("width");
if (width != null) {
try {
double w = Double.parseDouble(width);
if (w <=0) w = 1;
link.setLineWidth(w);
link.setMaximumLineWidth(w);
} catch (NumberFormatException e) {
}
}
}
/**
* Sets the map.
*/
public void setMap(URL url)
{
getManager().deleteAll(MAP_LAYER, true);
if (url == null)
return;
// Loads the image
Image img = Toolkit.getDefaultToolkit().getImage(url);
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(img, 0);
try {
tracker.waitForID(0);
} catch (InterruptedException e) {
return;
}
// Creates the IlvIcon
IlvIcon icon = new IlvIcon(img,
new IlvRect(0, 0,
img.getWidth(null),
img.getHeight(null)));
getManager().addObject(icon, MAP_LAYER, true);
getManager().setMovable(icon, false);
getManager().setSelectable(icon, false);
getManager().setEditable(icon, false);
}
/**
* Returns the location element from a node element.
*/
private static Element getLocation(Element node)
{
return getElement(node, "location");
}
/**
* Returns the origin element from a link element
*/
private static Element getOrigin(Element node)
{
return getElement(node, "origin");
}
/**
* Returns the destination element from a link element
*/
private static Element getDestination(Element node)
{
return getElement(node, "destination");
}
/**
* Returns the child element of the specified node element with
* the specified tag name.
*/
private static Element getElement(Element node, String tagName)
{
for (Node n = node.getFirstChild();
n != null ;
n = n.getNextSibling())
if (n.getNodeName().equals(tagName))
return (Element)n;
return null;
}
/**
* Converts an Color expressed as #RRGGBB to Awt Color.
*/
private static Color stringToColor(String color)
{
if (color == null)
return Color.black;
color.trim();
if (color.startsWith("#")) {
try {
color = color.substring(1);
if (color.length() == 6) {
int v = Integer.decode("0x"+color).intValue();
return new Color((v >> 32) & 0xFF, (v >> 8) & 0xFF, (v ) & 0xFF);
}
return Color.black;
} catch (NumberFormatException e) {
verbose("bad color");
return Color.black;
}
} else
return Color.black;
}
/**
* Gets an attribute name 'att' expressed in String
* and convert it to double.
*/
private static double getDoubleAttribute(Element node, String att, double def)
{
String s = node.getAttribute(att);
double d = def;
if (s == null || s.length() ==0)
return d;
try {
d = Double.parseDouble(s);
} catch (NumberFormatException e) {
}
return d;
}
private static void verbose(String msg)
{
if (verbose)
System.out.println(msg);
}
}