com.mxgraph.canvas.mxVmlCanvas Maven / Gradle / Ivy
/**
* $Id: mxVmlCanvas.java,v 1.53 2011-03-17 10:40:57 gaudenz Exp $
* Copyright (c) 2007, Gaudenz Alder
*/
package com.mxgraph.canvas;
import java.awt.Rectangle;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxPoint;
import com.mxgraph.util.mxRectangle;
import com.mxgraph.util.mxUtils;
import com.mxgraph.view.mxCellState;
/**
* An implementation of a canvas that uses VML for painting.
*/
public class mxVmlCanvas extends mxBasicCanvas
{
/**
* Holds the HTML document that represents the canvas.
*/
protected Document document;
/**
* Constructs a new VML canvas for the specified dimension and scale.
*/
public mxVmlCanvas()
{
this(null);
}
/**
* Constructs a new VML canvas for the specified bounds, scale and
* background color.
*/
public mxVmlCanvas(Document document)
{
setDocument(document);
}
/**
*
*/
public void setDocument(Document document)
{
this.document = document;
}
/**
* Returns a reference to the document that represents the canvas.
*
* @return Returns the document.
*/
public Document getDocument()
{
return document;
}
/**
*
*/
public void appendVmlElement(Element node)
{
if (document != null)
{
Node body = document.getDocumentElement().getFirstChild()
.getNextSibling();
if (body != null)
{
body.appendChild(node);
}
}
}
/* (non-Javadoc)
* @see com.mxgraph.canvas.mxICanvas#drawCell()
*/
public Object drawCell(mxCellState state)
{
Map style = state.getStyle();
Element elem = null;
if (state.getAbsolutePointCount() > 1)
{
List pts = state.getAbsolutePoints();
// Transpose all points by cloning into a new array
pts = mxUtils.translatePoints(pts, translate.x, translate.y);
// Draws the line
elem = drawLine(pts, style);
Element strokeNode = document.createElement("v:stroke");
// Draws the markers
String start = mxUtils.getString(style,
mxConstants.STYLE_STARTARROW);
String end = mxUtils.getString(style, mxConstants.STYLE_ENDARROW);
if (start != null || end != null)
{
if (start != null)
{
strokeNode.setAttribute("startarrow", start);
String startWidth = "medium";
String startLength = "medium";
double startSize = mxUtils.getFloat(style,
mxConstants.STYLE_STARTSIZE,
mxConstants.DEFAULT_MARKERSIZE)
* scale;
if (startSize < 6)
{
startWidth = "narrow";
startLength = "short";
}
else if (startSize > 10)
{
startWidth = "wide";
startLength = "long";
}
strokeNode.setAttribute("startarrowwidth", startWidth);
strokeNode.setAttribute("startarrowlength", startLength);
}
if (end != null)
{
strokeNode.setAttribute("endarrow", end);
String endWidth = "medium";
String endLength = "medium";
double endSize = mxUtils.getFloat(style,
mxConstants.STYLE_ENDSIZE,
mxConstants.DEFAULT_MARKERSIZE)
* scale;
if (endSize < 6)
{
endWidth = "narrow";
endLength = "short";
}
else if (endSize > 10)
{
endWidth = "wide";
endLength = "long";
}
strokeNode.setAttribute("endarrowwidth", endWidth);
strokeNode.setAttribute("endarrowlength", endLength);
}
}
if (mxUtils.isTrue(style, mxConstants.STYLE_DASHED))
{
strokeNode.setAttribute("dashstyle", "2 2");
}
elem.appendChild(strokeNode);
}
else
{
int x = (int) state.getX() + translate.x;
int y = (int) state.getY() + translate.y;
int w = (int) state.getWidth();
int h = (int) state.getHeight();
if (!mxUtils.getString(style, mxConstants.STYLE_SHAPE, "").equals(
mxConstants.SHAPE_SWIMLANE))
{
elem = drawShape(x, y, w, h, style);
if (mxUtils.isTrue(style, mxConstants.STYLE_DASHED))
{
Element strokeNode = document.createElement("v:stroke");
strokeNode.setAttribute("dashstyle", "2 2");
elem.appendChild(strokeNode);
}
}
else
{
int start = (int) Math.round(mxUtils.getInt(style,
mxConstants.STYLE_STARTSIZE,
mxConstants.DEFAULT_STARTSIZE)
* scale);
// Removes some styles to draw the content area
Map cloned = new Hashtable(
style);
cloned.remove(mxConstants.STYLE_FILLCOLOR);
cloned.remove(mxConstants.STYLE_ROUNDED);
if (mxUtils.isTrue(style, mxConstants.STYLE_HORIZONTAL, true))
{
elem = drawShape(x, y, w, start, style);
drawShape(x, y + start, w, h - start, cloned);
}
else
{
elem = drawShape(x, y, start, h, style);
drawShape(x + start, y, w - start, h, cloned);
}
}
}
return elem;
}
/*
* (non-Javadoc)
* @see com.mxgraph.canvas.mxICanvas#drawLabel()
*/
public Object drawLabel(String label, mxCellState state, boolean html)
{
mxRectangle bounds = state.getLabelBounds();
if (drawLabels && bounds != null)
{
int x = (int) bounds.getX() + translate.x;
int y = (int) bounds.getY() + translate.y;
int w = (int) bounds.getWidth();
int h = (int) bounds.getHeight();
Map style = state.getStyle();
return drawText(label, x, y, w, h, style);
}
return null;
}
/**
* Draws the shape specified with the STYLE_SHAPE key in the given style.
*
* @param x X-coordinate of the shape.
* @param y Y-coordinate of the shape.
* @param w Width of the shape.
* @param h Height of the shape.
* @param style Style of the the shape.
*/
public Element drawShape(int x, int y, int w, int h,
Map style)
{
String fillColor = mxUtils
.getString(style, mxConstants.STYLE_FILLCOLOR);
String strokeColor = mxUtils.getString(style,
mxConstants.STYLE_STROKECOLOR);
float strokeWidth = (float) (mxUtils.getFloat(style,
mxConstants.STYLE_STROKEWIDTH, 1) * scale);
// Draws the shape
String shape = mxUtils.getString(style, mxConstants.STYLE_SHAPE);
Element elem = null;
if (shape.equals(mxConstants.SHAPE_IMAGE))
{
String img = getImageForStyle(style);
if (img != null)
{
elem = document.createElement("v:img");
elem.setAttribute("src", img);
}
}
else if (shape.equals(mxConstants.SHAPE_LINE))
{
String direction = mxUtils.getString(style,
mxConstants.STYLE_DIRECTION, mxConstants.DIRECTION_EAST);
String points = null;
if (direction.equals(mxConstants.DIRECTION_EAST)
|| direction.equals(mxConstants.DIRECTION_WEST))
{
int mid = Math.round(h / 2);
points = "m 0 " + mid + " l " + w + " " + mid;
}
else
{
int mid = Math.round(w / 2);
points = "m " + mid + " 0 L " + mid + " " + h;
}
elem = document.createElement("v:shape");
elem.setAttribute("coordsize", w + " " + h);
elem.setAttribute("path", points + " x e");
}
else if (shape.equals(mxConstants.SHAPE_ELLIPSE))
{
elem = document.createElement("v:oval");
}
else if (shape.equals(mxConstants.SHAPE_DOUBLE_ELLIPSE))
{
elem = document.createElement("v:shape");
elem.setAttribute("coordsize", w + " " + h);
int inset = (int) ((3 + strokeWidth) * scale);
String points = "ar 0 0 " + w + " " + h + " 0 " + (h / 2) + " "
+ (w / 2) + " " + (h / 2) + " e ar " + inset + " " + inset
+ " " + (w - inset) + " " + (h - inset) + " 0 " + (h / 2)
+ " " + (w / 2) + " " + (h / 2);
elem.setAttribute("path", points + " x e");
}
else if (shape.equals(mxConstants.SHAPE_RHOMBUS))
{
elem = document.createElement("v:shape");
elem.setAttribute("coordsize", w + " " + h);
String points = "m " + (w / 2) + " 0 l " + w + " " + (h / 2)
+ " l " + (w / 2) + " " + h + " l 0 " + (h / 2);
elem.setAttribute("path", points + " x e");
}
else if (shape.equals(mxConstants.SHAPE_TRIANGLE))
{
elem = document.createElement("v:shape");
elem.setAttribute("coordsize", w + " " + h);
String direction = mxUtils.getString(style,
mxConstants.STYLE_DIRECTION, "");
String points = null;
if (direction.equals(mxConstants.DIRECTION_NORTH))
{
points = "m 0 " + h + " l " + (w / 2) + " 0 " + " l " + w + " "
+ h;
}
else if (direction.equals(mxConstants.DIRECTION_SOUTH))
{
points = "m 0 0 l " + (w / 2) + " " + h + " l " + w + " 0";
}
else if (direction.equals(mxConstants.DIRECTION_WEST))
{
points = "m " + w + " 0 l " + w + " " + (h / 2) + " l " + w
+ " " + h;
}
else
// east
{
points = "m 0 0 l " + w + " " + (h / 2) + " l 0 " + h;
}
elem.setAttribute("path", points + " x e");
}
else if (shape.equals(mxConstants.SHAPE_HEXAGON))
{
elem = document.createElement("v:shape");
elem.setAttribute("coordsize", w + " " + h);
String direction = mxUtils.getString(style,
mxConstants.STYLE_DIRECTION, "");
String points = null;
if (direction.equals(mxConstants.DIRECTION_NORTH)
|| direction.equals(mxConstants.DIRECTION_SOUTH))
{
points = "m " + (int) (0.5 * w) + " 0 l " + w + " "
+ (int) (0.25 * h) + " l " + w + " " + (int) (0.75 * h)
+ " l " + (int) (0.5 * w) + " " + h + " l 0 "
+ (int) (0.75 * h) + " l 0 " + (int) (0.25 * h);
}
else
{
points = "m " + (int) (0.25 * w) + " 0 l " + (int) (0.75 * w)
+ " 0 l " + w + " " + (int) (0.5 * h) + " l "
+ (int) (0.75 * w) + " " + h + " l " + (int) (0.25 * w)
+ " " + h + " l 0 " + (int) (0.5 * h);
}
elem.setAttribute("path", points + " x e");
}
else if (shape.equals(mxConstants.SHAPE_CLOUD))
{
elem = document.createElement("v:shape");
elem.setAttribute("coordsize", w + " " + h);
String points = "m " + (int) (0.25 * w) + " " + (int) (0.25 * h)
+ " c " + (int) (0.05 * w) + " " + (int) (0.25 * h) + " 0 "
+ (int) (0.5 * h) + " " + (int) (0.16 * w) + " "
+ (int) (0.55 * h) + " c 0 " + (int) (0.66 * h) + " "
+ (int) (0.18 * w) + " " + (int) (0.9 * h) + " "
+ (int) (0.31 * w) + " " + (int) (0.8 * h) + " c "
+ (int) (0.4 * w) + " " + (h) + " " + (int) (0.7 * w) + " "
+ (h) + " " + (int) (0.8 * w) + " " + (int) (0.8 * h)
+ " c " + (w) + " " + (int) (0.8 * h) + " " + (w) + " "
+ (int) (0.6 * h) + " " + (int) (0.875 * w) + " "
+ (int) (0.5 * h) + " c " + (w) + " " + (int) (0.3 * h)
+ " " + (int) (0.8 * w) + " " + (int) (0.1 * h) + " "
+ (int) (0.625 * w) + " " + (int) (0.2 * h) + " c "
+ (int) (0.5 * w) + " " + (int) (0.05 * h) + " "
+ (int) (0.3 * w) + " " + (int) (0.05 * h) + " "
+ (int) (0.25 * w) + " " + (int) (0.25 * h);
elem.setAttribute("path", points + " x e");
}
else if (shape.equals(mxConstants.SHAPE_ACTOR))
{
elem = document.createElement("v:shape");
elem.setAttribute("coordsize", w + " " + h);
double width3 = w / 3;
String points = "m 0 " + (h) + " C 0 " + (3 * h / 5) + " 0 "
+ (2 * h / 5) + " " + (w / 2) + " " + (2 * h / 5) + " c "
+ (int) (w / 2 - width3) + " " + (2 * h / 5) + " "
+ (int) (w / 2 - width3) + " 0 " + (w / 2) + " 0 c "
+ (int) (w / 2 + width3) + " 0 " + (int) (w / 2 + width3)
+ " " + (2 * h / 5) + " " + (w / 2) + " " + (2 * h / 5)
+ " c " + (w) + " " + (2 * h / 5) + " " + (w) + " "
+ (3 * h / 5) + " " + (w) + " " + (h);
elem.setAttribute("path", points + " x e");
}
else if (shape.equals(mxConstants.SHAPE_CYLINDER))
{
elem = document.createElement("v:shape");
elem.setAttribute("coordsize", w + " " + h);
double dy = Math.min(40, Math.floor(h / 5));
String points = "m 0 " + (int) (dy) + " C 0 " + (int) (dy / 3)
+ " " + (w) + " " + (int) (dy / 3) + " " + (w) + " "
+ (int) (dy) + " L " + (w) + " " + (int) (h - dy) + " C "
+ (w) + " " + (int) (h + dy / 3) + " 0 "
+ (int) (h + dy / 3) + " 0 " + (int) (h - dy) + " x e"
+ " m 0 " + (int) (dy) + " C 0 " + (int) (2 * dy) + " "
+ (w) + " " + (int) (2 * dy) + " " + (w) + " " + (int) (dy);
elem.setAttribute("path", points + " e");
}
else
{
if (mxUtils.isTrue(style, mxConstants.STYLE_ROUNDED, false))
{
elem = document.createElement("v:roundrect");
elem.setAttribute("arcsize",
(mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) + "%");
}
else
{
elem = document.createElement("v:rect");
}
}
String s = "position:absolute;left:" + String.valueOf(x) + "px;top:"
+ String.valueOf(y) + "px;width:" + String.valueOf(w)
+ "px;height:" + String.valueOf(h) + "px;";
// Applies rotation
double rotation = mxUtils.getDouble(style, mxConstants.STYLE_ROTATION);
if (rotation != 0)
{
s += "rotation:" + rotation + ";";
}
elem.setAttribute("style", s);
// Adds the shadow element
if (mxUtils.isTrue(style, mxConstants.STYLE_SHADOW, false)
&& fillColor != null)
{
Element shadow = document.createElement("v:shadow");
shadow.setAttribute("on", "true");
shadow.setAttribute("color", mxConstants.W3C_SHADOWCOLOR);
elem.appendChild(shadow);
}
float opacity = mxUtils.getFloat(style, mxConstants.STYLE_OPACITY, 100);
// Applies opacity to fill
if (fillColor != null)
{
Element fill = document.createElement("v:fill");
fill.setAttribute("color", fillColor);
if (opacity != 100)
{
fill.setAttribute("opacity", String.valueOf(opacity / 100));
}
elem.appendChild(fill);
}
else
{
elem.setAttribute("filled", "false");
}
// Applies opacity to stroke
if (strokeColor != null)
{
elem.setAttribute("strokecolor", strokeColor);
Element stroke = document.createElement("v:stroke");
if (opacity != 100)
{
stroke.setAttribute("opacity", String.valueOf(opacity / 100));
}
elem.appendChild(stroke);
}
else
{
elem.setAttribute("stroked", "false");
}
elem.setAttribute("strokeweight", String.valueOf(strokeWidth) + "px");
appendVmlElement(elem);
return elem;
}
/**
* Draws the given lines as segments between all points of the given list
* of mxPoints.
*
* @param pts List of points that define the line.
* @param style Style to be used for painting the line.
*/
public Element drawLine(List pts, Map style)
{
String strokeColor = mxUtils.getString(style,
mxConstants.STYLE_STROKECOLOR);
float strokeWidth = (float) (mxUtils.getFloat(style,
mxConstants.STYLE_STROKEWIDTH, 1) * scale);
Element elem = document.createElement("v:shape");
if (strokeColor != null && strokeWidth > 0)
{
mxPoint pt = pts.get(0);
Rectangle r = new Rectangle(pt.getPoint());
StringBuilder buf = new StringBuilder("m " + Math.round(pt.getX())
+ " " + Math.round(pt.getY()));
for (int i = 1; i < pts.size(); i++)
{
pt = pts.get(i);
buf.append(" l " + Math.round(pt.getX()) + " "
+ Math.round(pt.getY()));
r = r.union(new Rectangle(pt.getPoint()));
}
String d = buf.toString();
elem.setAttribute("path", d);
elem.setAttribute("filled", "false");
elem.setAttribute("strokecolor", strokeColor);
elem.setAttribute("strokeweight", String.valueOf(strokeWidth)
+ "px");
String s = "position:absolute;" + "left:" + String.valueOf(r.x)
+ "px;" + "top:" + String.valueOf(r.y) + "px;" + "width:"
+ String.valueOf(r.width) + "px;" + "height:"
+ String.valueOf(r.height) + "px;";
elem.setAttribute("style", s);
elem.setAttribute("coordorigin",
String.valueOf(r.x) + " " + String.valueOf(r.y));
elem.setAttribute("coordsize", String.valueOf(r.width) + " "
+ String.valueOf(r.height));
}
appendVmlElement(elem);
return elem;
}
/**
* Draws the specified text either using drawHtmlString or using drawString.
*
* @param text Text to be painted.
* @param x X-coordinate of the text.
* @param y Y-coordinate of the text.
* @param w Width of the text.
* @param h Height of the text.
* @param style Style to be used for painting the text.
*/
public Element drawText(String text, int x, int y, int w, int h,
Map style)
{
Element table = mxUtils.createTable(document, text, x, y, w, h, scale,
style);
appendVmlElement(table);
return table;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy