Package com.mxgraph.canvas

Source Code of com.mxgraph.canvas.mxVmlCanvas

/**
* $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<String, Object> style = state.getStyle();
    Element elem = null;

    if (state.getAbsolutePointCount() > 1)
    {
      List<mxPoint> 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<String, Object> cloned = new Hashtable<String, Object>(
            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<String, Object> 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<String, Object> 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<mxPoint> pts, Map<String, Object> 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<String, Object> style)
  {
    Element table = mxUtils.createTable(document, text, x, y, w, h, scale,
        style);
    appendVmlElement(table);

    return table;
  }

}
TOP

Related Classes of com.mxgraph.canvas.mxVmlCanvas

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.