Example #1
0
        /// <summary>
        /// Returns a clone of this state where all members are deeply cloned
        /// except the view and cell references, which are copied with no
        /// cloning to the new instance.
        /// </summary>
        /// <returns></returns>
        new public mxCellState Clone()
        {
            mxCellState clone = new mxCellState(view, cell, style);

            if (absolutePoints != null)
            {
                clone.absolutePoints = new List <mxPoint>();

                foreach (mxPoint pt in absolutePoints)
                {
                    clone.absolutePoints.Add(pt.Clone());
                }
            }

            if (origin != null)
            {
                clone.origin = origin.Clone();
            }

            if (absoluteOffset != null)
            {
                clone.absoluteOffset = absoluteOffset.Clone();
            }

            if (labelBounds != null)
            {
                clone.labelBounds = labelBounds.Clone();
            }

            if (boundingBox != null)
            {
                clone.boundingBox = boundingBox.Clone();
            }

            clone.terminalDistance = terminalDistance;
            clone.segments         = segments;
            clone.length           = length;
            clone.x      = x;
            clone.y      = y;
            clone.width  = width;
            clone.height = height;

            return(clone);
        }
Example #2
0
        /// <summary>
        /// Draws the shadow.
        /// </summary>
        /// <param name="canvas"></param>
        /// <param name="state"></param>
        /// <param name="rotation"></param>
        /// <param name="flipH"></param>
        /// <param name="flipV"></param>
        /// <param name="bounds"></param>
        /// <param name="alpha"></param>
        protected void DrawShadow(mxGdiCanvas2D canvas, mxCellState state, double rotation, bool flipH,
			    bool flipV, mxRectangle bounds, double alpha, bool filled)
        {
            // Requires background in generic shape for shadow, looks like only one
            // fillAndStroke is allowed per current path, try working around that
            // Computes rotated shadow offset
            double rad = rotation * Math.PI / 180;
            double cos = Math.Cos(-rad);
            double sin = Math.Sin(-rad);
            mxPoint offset = mxUtils.GetRotatedPoint(new mxPoint(mxConstants.SHADOW_OFFSETX, mxConstants.SHADOW_OFFSETY), cos, sin);

            if (flipH)
            {
                offset.X *= -1;
            }

            if (flipV)
            {
                offset.Y *= -1;
            }

            // TODO: Use save/restore instead of negative offset to restore (requires fix for HTML canvas)
            canvas.Translate(offset.X, offset.Y);

            // Returns true if a shadow has been painted (path has been created)
            if (DrawShape(canvas, state, bounds, true))
            {
                canvas.Alpha = mxConstants.STENCIL_SHADOW_OPACITY * alpha;
                canvas.Shadow(mxConstants.STENCIL_SHADOWCOLOR, filled);
            }

            canvas.Translate(-offset.X, -offset.Y);
        }
Example #3
0
        /// <summary>
        /// Returns a rectangle that contains the offset in x and y and the horizontal
        /// and vertical scale in width and height used to draw this shape inside the
        /// given rectangle.
        /// </summary>
        /// <param name="state"></param>
        /// <param name="bounds"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        protected mxRectangle ComputeAspect(mxCellState state, mxRectangle bounds,
			    string direction)
        {
            double x0 = bounds.X;
            double y0 = bounds.Y;
            double sx = bounds.Width / w0;
            double sy = bounds.Height / h0;

            bool inverse = (direction != null && (direction.Equals("north") || direction
                    .Equals("south")));

            if (inverse)
            {
                sy = bounds.Width / h0;
                sx = bounds.Height / w0;

                double delta = (bounds.Width - bounds.Height) / 2;

                x0 += delta;
                y0 -= delta;
            }

            if (aspect.Equals("fixed"))
            {
                sy = Math.Min(sx, sy);
                sx = sy;

                // Centers the shape inside the available space
                if (inverse)
                {
                    x0 += (bounds.Height - this.w0 * sx) / 2;
                    y0 += (bounds.Width - this.h0 * sy) / 2;
                }
                else
                {
                    x0 += (bounds.Width - this.w0 * sx) / 2;
                    y0 += (bounds.Height - this.h0 * sy) / 2;
                }
            }

            return new mxRectangle(x0, y0, sx, sy);
        }
Example #4
0
        /// <summary>
        /// Gets the attribute for the given name from the given node. If the attribute
        /// does not exist then the text content of the node is evaluated and if it is
        /// a function it is invoked with <state> as the only argument and the return
        /// value is used as the attribute value to be returned.
        /// </summary>
        /// <param name="elt"></param>
        /// <param name="attribute"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        public string EvaluateAttribute(XmlElement elt, string attribute,
			    mxCellState state)
        {
            string result = elt.GetAttribute(attribute);

            if (result == null)
            {
                // JS functions as text content are currently not supported in .NET
            }

            return result;
        }
Example #5
0
        /// <summary>
        /// Parses the bounds, absolute points and label information from the style
        /// of the state into its respective fields and returns the label of the
        /// cell.
        /// </summary>
        public string ParseState(mxCellState state, bool edge)
        {
            Dictionary<string, object> style = state.Style;

            // Parses the bounds
            state.X = mxUtils.GetDouble(style, "x");
            state.Y = mxUtils.GetDouble(style, "y");
            state.Width = mxUtils.GetDouble(style, "width");
            state.Height = mxUtils.GetDouble(style, "height");

            // Parses the absolute points list
            List<mxPoint> pts = ParsePoints(mxUtils.GetString(style, "points"));

            if (pts.Count > 0)
            {
                state.AbsolutePoints = pts;
            }

            // Parses the label and label bounds
            string label = mxUtils.GetString(style, "label");

            if (label != null && label.Length > 0)
            {
                mxPoint offset = new mxPoint(mxUtils.GetDouble(style, "dx"),
                    mxUtils.GetDouble(style, "dy"));
                mxRectangle vertexBounds = (!edge) ? state : null;
                state.LabelBounds = mxUtils.GetLabelPaintBounds(label, style,
                    mxUtils.IsTrue(style, "html", false), offset, vertexBounds,
                    scale);
            }

            return label;
        }
Example #6
0
        /// <summary>
        /// Returns the nearest point in the list of absolute points or the center
        /// of the opposite terminal.
        /// </summary>
        /// <param name="vertex">Cell state that represents the vertex.</param>
        /// <param name="constraint">Connection constraint that represents the connection
        /// point constraint as returned by getConnectionConstraint.</param>
        public mxPoint GetConnectionPoint(mxCellState vertex, mxConnectionConstraint constraint)
        {
            mxPoint point = null;

            if (vertex != null &&
                constraint.Point != null)
            {
                point = new mxPoint(vertex.X + constraint.Point.X * vertex.Width,
                        vertex.Y + constraint.Point.Y * vertex.Height);
            }

            if (point != null &&
                constraint.Perimeter)
            {
                point = View.GetPerimeterPoint(vertex, point, false);
            }

            return point;
        }
Example #7
0
        /// <summary>
        /// Draws the given cell and label onto the specified canvas. No
        /// children or descendants are painted.
        /// </summary>
        public void DrawState(mxICanvas canvas, mxCellState state, String label)
        {
            Object cell = (state != null) ? state.Cell : null;

            if (cell != null && cell != model.Root && (model.IsVertex(cell) || model.IsEdge(cell)))
            {
                Object obj = canvas.DrawCell(state);
                Object lab = null;

                // Holds the current clipping region in case the label will
                // be clipped
                Region clip = null;
                Region newClip = new Region(state.GetRectangle());

                // Indirection for image canvas that contains a graphics canvas
                mxICanvas clippedCanvas = (mxUtils.GetString(state.Style, mxConstants.
                    STYLE_OVERFLOW, "").Equals("hidden")) ? canvas : null;

                if (clippedCanvas is mxImageCanvas)
                {
                    clippedCanvas = ((mxImageCanvas) clippedCanvas).GdiCanvas;
                    Point pt = ((mxImageCanvas) canvas).Translate;
                    newClip.Translate(pt.X, pt.Y);
                }

                if (clippedCanvas is mxGdiCanvas)
                {
                    Graphics g = ((mxGdiCanvas) clippedCanvas).Graphics;
                    clip = g.Clip;
                    g.Clip = newClip;
                }

                if (label != null && state.LabelBounds != null)
                {
                    lab = canvas.DrawLabel(label, state, false);
                }

                // Restores the previous clipping region
                if (clippedCanvas is mxGdiCanvas)
                {
                    ((mxGdiCanvas)clippedCanvas).Graphics.Clip = clip;
                }

                // Invokes the cellDrawn callback with the object which was created
                // by the canvas to represent the cell graphically
                if (obj != null)
                {
                    // LATER: Add inner callback for rendering
                    //CellDrawn(cell, obj, lab);
                }
            }
        }
Example #8
0
        /// <summary>
        /// Returns the bottom-most cell that intersects the given point (x, y) in
        /// the cell hierarchy that starts at the given parent.
        /// </summary>
        /// <param name="state"></param>
        /// <param name="rect"></param>
        /// <returns>Returns true if the given cell state and rectangle intersect.</returns>
        public bool Intersects(mxCellState state, Rectangle rect)
        {
            if (state != null)
            {
                // Checks if the label intersects
                if (state.LabelBounds != null
                        && state.LabelBounds.GetRectangle().IntersectsWith(rect))
                {
                    return true;
                }

                int pointCount = state.AbsolutePointCount();

                // Checks if the segments of the edge intersect
                if (pointCount > 0)
                {
                    mxRectangle tmp = new mxRectangle(rect);
                    tmp.Grow(tolerance);
                    rect = tmp.GetRectangle();

                    mxPoint p0 = state.AbsolutePoints[0];

                    for (int i = 0; i < pointCount; i++)
                    {
                        mxPoint p1 = state.AbsolutePoints[i];

                        // FIXME: Implement line intersection check
                        //if (rect.IntersectsLine(p0.X, p0.Y, p1.X, p1
                        //        .Y))
                        //    return true;

                        p0 = p1;
                    }
                }
                else
                {
                    // Checks if the bounds of the shape intersect
                    return state.GetRectangle().IntersectsWith(rect);
                }
            }

            return false;
        }
Example #9
0
        /// <summary>
        /// Updates the given state using the bounding box of the absolute points.
        /// Also updates terminal distance, length and segments.
        /// </summary>
        /// <param name="state">Cell state whose bounds should be updated.</param>
        public void UpdateEdgeBounds(mxCellState state)
        {
            List<mxPoint> points = state.AbsolutePoints;

            if (points != null && points.Count > 0)
            {
                mxPoint p0 = points[0];
                mxPoint pe = points[points.Count - 1];

                if (p0 == null || pe == null)
                {

                    // Note: This is an error that normally occurs
                    // if a connected edge has a null-terminal, ie.
                    // edge.source == null or edge.target == null.
                    states.Remove(state.Cell);
                }
                else
                {
                    if (p0.X != pe.X || p0.Y != pe.Y)
                    {
                        double dx = pe.X - p0.X;
                        double dy = pe.Y - p0.Y;
                        state.TerminalDistance = Math.Sqrt(dx * dx + dy * dy);
                    }
                    else
                    {
                        state.TerminalDistance = 0;
                    }

                    double length = 0;
                    double[] segments = new double[points.Count - 1];
                    mxPoint pt = p0;

                    if (pt != null)
                    {
                        double minX = pt.X;
                        double minY = pt.Y;
                        double maxX = minX;
                        double maxY = minY;

                        for (int i = 1; i < points.Count; i++)
                        {
                            mxPoint tmp = points[i];
                            if (tmp != null)
                            {
                                double dx = pt.X - tmp.X;
                                double dy = pt.Y - tmp.Y;

                                double segment = Math.Sqrt(dx * dx + dy * dy);
                                segments[i - 1] = segment;
                                length += segment;
                                pt = tmp;

                                minX = Math.Min(pt.X, minX);
                                minY = Math.Min(pt.Y, minY);
                                maxX = Math.Max(pt.X, maxX);
                                maxY = Math.Max(pt.Y, maxY);
                            }
                        }

                        state.Length = length;
                        state.Segments = segments;
                        double markerSize = 1; // TODO: include marker size

                        state.X = minX;
                        state.Y = minY;
                        state.Width = Math.Max(markerSize, maxX - minX);
                        state.Height = Math.Max(markerSize, maxY - minY);
                    }
                    else
                    {
                        state.Length = 0;
                    }
                }
            }
        }
Example #10
0
        /// <summary>
        /// Updates the bounding box in the given cell state.
        /// </summary>
        /// <param name="state">Cell state whose bounding box should be
        /// updated.</param>
        /// <returns></returns>
        public mxRectangle UpdateBoundingBox(mxCellState state)
        {
            // Gets the cell bounds and adds shadows and markers
            mxRectangle rect = new mxRectangle(state.GetRectangle());
            Dictionary<string, Object> style = state.Style;

            // Adds extra pixels for the marker and stroke assuming
            // that the border stroke is centered around the bounds
            // and the first pixel is drawn inside the bounds
            double strokeWidth = Math.Max(1, Math.Round(mxUtils.GetInt(style,
                    mxConstants.STYLE_STROKEWIDTH, 1)
                    * scale));
            strokeWidth -= Math.Max(1, strokeWidth / 2);

            if (graph.Model.IsEdge(state.Cell))
            {
                int ms = 0;

                if (style.ContainsKey(mxConstants.STYLE_ENDARROW)
                        || style.ContainsKey(mxConstants.STYLE_STARTARROW))
                {
                    ms = (int) Math.Round(mxConstants.DEFAULT_MARKERSIZE * scale);
                }

                // Adds the strokewidth
                rect.Grow(ms + strokeWidth);

                // Adds worst case border for an arrow shape
                if (mxUtils.GetString(style, mxConstants.STYLE_SHAPE, "").Equals(
                        mxConstants.SHAPE_ARROW))
                {
                    rect.Grow(mxConstants.ARROW_WIDTH / 2);
                }
            }
            else
            {
                rect.Grow(strokeWidth);
            }

            // Adds extra pixels for the shadow
            if (mxUtils.IsTrue(style, mxConstants.STYLE_SHADOW))
            {
                rect.Width += mxConstants.SHADOW_OFFSETX;
                rect.Height += mxConstants.SHADOW_OFFSETY;
            }

            // Adds oversize images in labels
            if (mxUtils.GetString(style, mxConstants.STYLE_SHAPE, "").Equals(
                    mxConstants.SHAPE_LABEL))
            {
                if (mxUtils.GetString(style, mxConstants.STYLE_IMAGE) != null)
                {
                    double w = mxUtils.GetInt(style,
                            mxConstants.STYLE_IMAGE_WIDTH,
                            mxConstants.DEFAULT_IMAGESIZE) * scale;
                    double h = mxUtils.GetInt(style,
                            mxConstants.STYLE_IMAGE_HEIGHT,
                            mxConstants.DEFAULT_IMAGESIZE) * scale;

                    double x = state.X;
                    double y = 0;

                    string imgAlign = mxUtils
                            .GetString(style, mxConstants.STYLE_IMAGE_ALIGN,
                                    mxConstants.ALIGN_LEFT);
                    string imgValign = mxUtils.GetString(style,
                            mxConstants.STYLE_IMAGE_VERTICAL_ALIGN,
                            mxConstants.ALIGN_MIDDLE);

                    if (imgAlign.Equals(mxConstants.ALIGN_RIGHT))
                    {
                        x += state.Width - w;
                    }
                    else if (imgAlign.Equals(mxConstants.ALIGN_CENTER))
                    {
                        x += (state.Width - w) / 2;
                    }

                    if (imgValign.Equals(mxConstants.ALIGN_TOP))
                    {
                        y = state.Y;
                    }
                    else if (imgValign.Equals(mxConstants.ALIGN_BOTTOM))
                    {
                        y = state.Y + state.Height - h;
                    }
                    else
                    {
                        y = state.Y + (state.Height - h) / 2;
                    }

                    rect.Add(new mxRectangle(x, y, w, h));
                }
            }

            // Adds the rotated bounds to the bounding box if the
            // shape is rotated
            double rotation = mxUtils.GetDouble(style, mxConstants.STYLE_ROTATION);
            mxRectangle bbox = mxUtils.GetBoundingBox(rect, rotation);

            // Add the rotated bounding box to the non-rotated so
            // that all handles are also covered
            if (bbox != null)
            {
                rect.Add(bbox);
            }

            // Unifies the cell bounds and the label bounds
            if (!mxUtils.GetString(style, mxConstants.STYLE_OVERFLOW, "").Equals("hidden"))
            {
                rect.Add(state.LabelBounds);
            }

            state.BoundingBox = rect;

            return rect;
        }
Example #11
0
        /// <summary>
        /// Transforms the given control point to an absolute point.
        /// </summary>
        public mxPoint TransformControlPoint(mxCellState state, mxPoint pt)
        {
            mxPoint orig = state.Origin;

            return new mxPoint(scale * (pt.X + translate.X + orig.X),
                scale * (pt.Y + translate.Y + orig.Y));
        }
Example #12
0
        /// <summary>
        /// Returns the given terminal or the port defined in the given edge state if a
        /// cell state exists for that port.
        /// </summary>
        public mxCellState GetTerminalPort(mxCellState state, mxCellState terminal, bool source)
        {
            string key = (source) ? mxConstants.STYLE_SOURCE_PORT
                    : mxConstants.STYLE_TARGET_PORT;
            string id = mxUtils.GetString(state.Style, key);

            if (id != null && graph.Model is mxGraphModel)
            {
                mxCellState tmp = GetState(((mxGraphModel)graph.Model).GetCell(id));

                // Only uses ports where a cell state exists
                if (tmp != null)
                {
                    terminal = tmp;
                }
            }

            return terminal;
        }
Example #13
0
        /// <summary>
        /// Returns the y-coordinate of the center point for automatic routing.
        /// </summary>
        /// <returns>Returns the y-coordinate of the routing center point.</returns>
        public double GetRoutingCenterY(mxCellState state)
        {
            float f = (state.Style != null) ? mxUtils.GetFloat(state.
                Style, mxConstants.STYLE_ROUTING_CENTER_Y) : 0;

            return state.GetCenterY() + f * state.Height;
        }
Example #14
0
        /// <summary>
        /// Returns the absolute point on the edge for the given relative
        /// geometry as a point. The edge is represented by the given cell state.
        /// </summary>
        /// <param name="state">Represents the state of the parent edge.</param>
        /// <param name="geometry">Represents the relative location.</param>
        public mxPoint GetPoint(mxCellState state, mxGeometry geometry)
        {
            double x = state.GetCenterX();
            double y = state.GetCenterY();

            if (state.Segments != null && (geometry == null || geometry.Relative))
            {
                double gx = (geometry != null) ? geometry.X / 2 : 0;
                int pointCount = state.AbsolutePoints.Count;
                double dist = (gx + 0.5) * state.Length;
                double[] segments = state.Segments;
                double segment = segments[0];
                double length = 0;
                int index = 1;

                while (dist > length + segment && index < pointCount - 1)
                {
                    length += segment;
                    segment = segments[index++];
                }

                double factor = (segment == 0) ? 0 : (dist - length) / segment;
                mxPoint p0 = state.AbsolutePoints[index - 1];
                mxPoint pe = state.AbsolutePoints[index];

                if (p0 != null &&
                    pe != null)
                {
                    double gy = 0;
                    double offsetX = 0;
                    double offsetY = 0;

                    if (geometry != null)
                    {
                        gy = geometry.Y;
                        mxPoint offset = geometry.Offset;

                        if (offset != null)
                        {
                            offsetX = offset.X;
                            offsetY = offset.Y;
                        }
                    }

                    double dx = pe.X - p0.X;
                    double dy = pe.Y - p0.Y;
                    double nx = (segment == 0) ? 0 : dy / segment;
                    double ny = (segment == 0) ? 0 : dx / segment;

                    x = p0.X + dx * factor + (nx * gy + offsetX) * scale;
                    y = p0.Y + dy * factor - (ny * gy - offsetY) * scale;
                }
            }
            else if (geometry != null)
            {
                mxPoint offset = geometry.Offset;

                if (offset != null)
                {
                    x += offset.X;
                    y += offset.Y;
                }
            }

            return new mxPoint(x, y);
        }
Example #15
0
 /// <summary>
 /// Returns the absolute center point along the given edge.
 /// </summary>
 public mxPoint GetPoint(mxCellState state)
 {
     return GetPoint(state, null);
 }
Example #16
0
 /// <summary>
 /// see com.mxgraph.mxICanvas.DrawLabel()
 /// </summary>
 public abstract Object DrawLabel(string text, mxCellState state, bool html);
Example #17
0
        /// <summary>
        /// Sets the fixed source or target terminal point on the given edge.
        /// </summary>
        /// <param name="edge">State whose terminal point should be updated.</param>
        /// <param name="terminal">State which represents the actual terminal.</param>
        /// <param name="source">Boolean that specifies if the terminal is the source.</param>
        /// <param name="constraint">Constraint that specifies the connection.</param>
        public void UpdateFixedTerminalPoint(mxCellState edge, mxCellState terminal,
            bool source, mxConnectionConstraint constraint)
        {
            mxPoint pt = null;

            if (constraint != null)
            {
                pt = graph.GetConnectionPoint(terminal, constraint);
            }

            if (pt == null && terminal == null)
            {
                mxPoint orig = edge.Origin;
                mxGeometry geo = graph.GetCellGeometry(edge.Cell);
                pt = geo.GetTerminalPoint(source);

                if (pt != null)
                {
                    pt = new mxPoint(scale * (translate.X + pt.X + orig.X),
                                     scale * (translate.Y + pt.Y + orig.Y));
                }
            }

            edge.SetAbsoluteTerminalPoint(pt, source);
        }
Example #18
0
        /// <summary>
        /// Returns true if perimeter points should be computed such that the
        /// resulting edge has only horizontal or vertical segments. 
        /// </summary>
        /// <param name="edge">Cell state that represents the edge.</param>
        /// <returns>True if the edge is orthogonal.</returns>
        public bool IsOrthogonal(mxCellState edge)
        {
            if (edge.Style.ContainsKey(mxConstants.STYLE_ORTHOGONAL))
            {
                return mxUtils.IsTrue(edge.Style, mxConstants.STYLE_ORTHOGONAL);
            }

            mxEdgeStyleFunction tmp = view.GetEdgeStyle(edge, null, null, null);

            return tmp == mxEdgeStyle.ElbowConnector ||
                tmp == mxEdgeStyle.SideToSide ||
                tmp == mxEdgeStyle.TopToBottom ||
                tmp == mxEdgeStyle.EntityRelation;
        }
Example #19
0
 /// <summary>
 /// Sets the initial absolute terminal points in the given state before the edge
 /// style is computed.
 /// </summary>
 /// <param name="edge">Cell state whose initial terminal points should be updated.</param>
 /// <param name="source">Cell state which represents the source terminal.</param>
 /// <param name="target">Cell state which represents the target terminal.</param>
 public void UpdateFixedTerminalPoints(mxCellState edge, mxCellState source, mxCellState target)
 {
     UpdateFixedTerminalPoint(edge, source, true,
         graph.GetConnectionConstraint(edge, source, true));
     UpdateFixedTerminalPoint(edge, target, false,
         graph.GetConnectionConstraint(edge, target, false));
 }
Example #20
0
        /// <summary>
        /// Returns a connection constraint that describes the given connection
        /// point. This result can then be passed to getConnectionPoint.
        /// </summary>
        /// <param name="edge">Cell state that represents the edge.</param>
        /// <param name="terminal">Cell state that represents the terminal.</param>
        /// <param name="source">Boolean indicating if the terminal is the source or target.</param>
        /// <returns></returns>
        public mxConnectionConstraint GetConnectionConstraint(mxCellState edge, mxCellState terminal, bool source)
        {
            mxPoint point = null;
            string key = (source) ? mxConstants.STYLE_EXIT_X : mxConstants.STYLE_ENTRY_X;

            if (edge.Style.ContainsKey(key))
            {
                double x = mxUtils.GetDouble(edge.Style, key);
                key = (source) ? mxConstants.STYLE_EXIT_Y : mxConstants.STYLE_ENTRY_Y;

                if (edge.Style.ContainsKey(key))
                {
                    double y = mxUtils.GetDouble(edge.Style, key);
                    point = new mxPoint(x, y);
                }
            }

            bool perimeter = false;

            if (point != null)
            {
                perimeter = mxUtils.IsTrue(edge.Style, (source) ?
                    mxConstants.STYLE_EXIT_PERIMETER :
                    mxConstants.STYLE_ENTRY_PERIMETER, true);
            }

            return new mxConnectionConstraint(point, perimeter);
        }
Example #21
0
 /// <summary>
 /// Updates the absolute terminal point in the given state for the given
 /// start and end state, where start is the source if source is true.
 /// </summary>
 /// <param name="edge">State whose terminal point should be updated.</param>
 /// <param name="start">for the terminal on "this" side of the edge.</param>
 /// <param name="end">for the terminal on the other side of the edge.</param>
 /// <param name="source">Boolean indicating if start is the source terminal state.</param>
 public void UpdateFloatingTerminalPoint(mxCellState edge, mxCellState start,
     mxCellState end, bool source)
 {
     start = GetTerminalPort(edge, start, source);
     mxPoint next = GetNextPoint(edge, end, source);
     double border = mxUtils.GetDouble(edge.Style, mxConstants.STYLE_PERIMETER_SPACING);
     border += mxUtils.GetDouble(edge.Style, (source) ?
         mxConstants.STYLE_SOURCE_PERIMETER_SPACING :
         mxConstants.STYLE_TARGET_PERIMETER_SPACING);
     mxPoint pt = GetPerimeterPoint(start, next, graph.IsOrthogonal(edge), border);
     edge.SetAbsoluteTerminalPoint(pt, source);
 }
Example #22
0
        /// <summary>
        /// Parses the given element and paints it onto the canvas.
        /// </summary>
        /// <param name="tagName">Name of the node to be parsed.</param>
        /// <param name="attrs">Attributes of the node to be parsed.</param>
        public void ParseElement(string tagName, Dictionary<string, Object> attrs)
        {
            if (canvas == null && tagName.ToLower().Equals("graph"))
            {
                scale = mxUtils.GetDouble(attrs, "scale", 1);
                canvas = CreateCanvas(attrs);

                if (canvas != null)
                {
                    canvas.Scale = scale;
                }
            }
            else if (canvas != null)
            {
                bool edge = tagName.ToLower().Equals("edge");
                bool group = tagName.ToLower().Equals("group");
                bool vertex = tagName.ToLower().Equals("vertex");

                if ((edge && attrs.ContainsKey("points")) ||
                    ((vertex || group) && attrs.ContainsKey("x") &&
                    attrs.ContainsKey("y") && attrs.ContainsKey("width") &&
                    attrs.ContainsKey("height")))
                {
                    mxCellState state = new mxCellState(null, null, attrs);

                    string label = ParseState(state, edge);
                    canvas.DrawCell(state);
                    canvas.DrawLabel(label, state, false);
                }
            }
        }
Example #23
0
        /// <summary>
        /// Updates the terminal points in the given state after the edge style was
        /// computed for the edge.
        /// </summary>
        /// <param name="state">State whose terminal points should be updated.</param>
        /// <param name="source">State that represents the source terminal.</param>
        /// <param name="target">State that represents the target terminal.</param>
        public void UpdateFloatingTerminalPoints(mxCellState state, mxCellState source, mxCellState target)
        {
            mxPoint p0 = state.AbsolutePoints[0];
            mxPoint pe = state.AbsolutePoints[state.AbsolutePointCount() - 1];

            if (pe == null && target != null)
            {
                UpdateFloatingTerminalPoint(state, target, source, false);
            }

            if (p0 == null && source != null)
            {
                UpdateFloatingTerminalPoint(state, source, target, true);
            }
        }
Example #24
0
        /**
         * Draws this stencil inside the given bounds.
         */
        public bool DrawShape(mxGdiCanvas2D canvas, mxCellState state,
			    mxRectangle bounds, bool background)
        {
            XmlNode elt = (background) ? bgNode : fgNode;

            if (elt != null)
            {
                String direction = mxUtils.GetString(state.Style,
                        mxConstants.STYLE_DIRECTION, null);
                mxRectangle aspect = ComputeAspect(state, bounds, direction);
                double minScale = Math.Min(aspect.Width, aspect.Height);
                double sw = strokewidth.Equals("inherit") ? mxUtils.GetDouble(
                        state.Style, mxConstants.STYLE_STROKEWIDTH, 1)
                        * state.View.Scale : double
                        .Parse(strokewidth) * minScale;
                lastMoveX = 0;
                lastMoveY = 0;
                canvas.StrokeWidth = sw;

                XmlNode tmp = elt.FirstChild;

                while (tmp != null)
                {
                    if (tmp.NodeType == XmlNodeType.Element)
                    {
                        DrawElement(canvas, state, (XmlElement) tmp, aspect);
                    }

                    tmp = tmp.NextSibling;
                }

                return true;
            }

            return false;
        }
Example #25
0
        /// <summary>
        /// see com.mxgraph.mxICanvas.DrawCell()
        /// </summary>
        public override Object DrawCell(mxCellState state)
        {
            Dictionary<string, object> style = state.Style;
            GraphicsState graphicsState = g.Save();

            // Applies the local translation
            g.TranslateTransform(translate.X, translate.Y);

            // Checks if the cell is an edge
            if (state.AbsolutePointCount() > 1)
            {
                DrawLine(state.AbsolutePoints, style);
            }
            else
            {
                Rectangle bounds = state.GetRectangle();
                int x = bounds.X;
                int y = bounds.Y;
                int w = bounds.Width;
                int h = bounds.Height;

                // Applies the rotation on the graphics object and stores
                // the previous transform so that it can be restored
                float rotation = mxUtils.GetFloat(style, mxConstants.STYLE_ROTATION);

                if (rotation != 0)
                {
                    int cx = x + w / 2;
                    int cy = y + h / 2;

                    g.TranslateTransform(cx, cy);
                    g.RotateTransform(rotation);
                    g.TranslateTransform(-cx, -cy);
                }

                // Draws a swimlane if start is > 0
                string shape = mxUtils.GetString(style, mxConstants.STYLE_SHAPE, "");

                if (!shape.Equals(mxConstants.SHAPE_SWIMLANE))
                {
                    // NOTE: Should draw built-in shapes first
                    mxStencil stencil = mxStencilRegistry.GetStencil(shape);

                    if (stencil != null)
                    {
                        stencil.PaintShape(this, state);
                    }
                    else
                    {
                        DrawShape(x, y, w, h, style);
                    }
                }
                else
                {
                    int start = (int)Math.Round(mxUtils.GetDouble(style,
                        mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE) * scale);

                    // Removes some styles to draw the content area
                    Dictionary<string, Object> cloned = new Dictionary<string, Object>(style);
                    cloned.Remove(mxConstants.STYLE_FILLCOLOR);
                    cloned.Remove(mxConstants.STYLE_ROUNDED);

                    if (mxUtils.IsTrue(style, mxConstants.STYLE_HORIZONTAL, true))
                    {
                        DrawShape(x, y, w, Math.Min(h, start), style);
                        DrawShape(x, y + start, w, h - start, cloned);
                    }
                    else
                    {
                        DrawShape(x, y, Math.Min(w, start), h, style);
                        DrawShape(x + start, y, w - start, h, cloned);
                    }
                }
            }

            // Resets all changes to the graphics configuration
            g.Restore(graphicsState);

            return null;
        }
Example #26
0
        /// <summary>
        /// Paints the stencil for the given state.
        /// </summary>
        public void PaintShape(mxGdiCanvas gc, mxCellState state)
        {
            mxGdiCanvas2D canvas = CreateCanvas(gc);
            Dictionary<string, object> style = state.Style;

            double rotation = mxUtils.GetDouble(style, mxConstants.STYLE_ROTATION,
                    0);
            String direction = mxUtils.GetString(style,
                    mxConstants.STYLE_DIRECTION, null);

            // Default direction is east (ignored if rotation exists)
            if (direction != null)
            {
                if (direction.Equals("north"))
                {
                    rotation += 270;
                }
                else if (direction.Equals("west"))
                {
                    rotation += 180;
                }
                else if (direction.Equals("south"))
                {
                    rotation += 90;
                }
            }

            // New styles for shape flipping the stencil
            bool flipH = mxUtils.IsTrue(style, mxConstants.STYLE_STENCIL_FLIPH,
                    false);
            bool flipV = mxUtils.IsTrue(style, mxConstants.STYLE_STENCIL_FLIPV,
                    false);

            if (flipH && flipV)
            {
                rotation += 180;
                flipH = false;
                flipV = false;
            }

            // Saves the global state for each cell
            canvas.Save();

            // Adds rotation and horizontal/vertical flipping
            rotation = rotation % 360;

            if (rotation != 0 || flipH || flipV)
            {
                canvas.Rotate(rotation, flipH, flipV, state.GetCenterX(),
                        state.GetCenterY());
            }

            // Note: Overwritten in mxStencil.paintShape (can depend on aspect)
            double scale = state.View.Scale;
            double sw = mxUtils.GetDouble(style, mxConstants.STYLE_STROKEWIDTH, 1)
                    * scale;
            canvas.StrokeWidth = sw;

            double alpha = mxUtils.GetDouble(style, mxConstants.STYLE_OPACITY, 100) / 100;
            String gradientColor = mxUtils.GetString(style,
                    mxConstants.STYLE_GRADIENTCOLOR, null);

            // Converts colors with special keyword none to null
            if (gradientColor != null && gradientColor.Equals(mxConstants.NONE))
            {
                gradientColor = null;
            }

            String fillColor = mxUtils.GetString(style,
                    mxConstants.STYLE_FILLCOLOR, null);

            if (fillColor != null && fillColor.Equals(mxConstants.NONE))
            {
                fillColor = null;
            }

            String strokeColor = mxUtils.GetString(style,
                    mxConstants.STYLE_STROKECOLOR, null);

            if (strokeColor != null && strokeColor.Equals(mxConstants.NONE))
            {
                strokeColor = null;
            }

            // Draws the shadow if the fillColor is not transparent
            if (mxUtils.IsTrue(style, mxConstants.STYLE_SHADOW, false))
            {
                DrawShadow(canvas, state, rotation, flipH, flipV, state, alpha, fillColor != null);
            }

            canvas.Alpha = alpha;

            // Sets the dashed state
            if (mxUtils.IsTrue(style, mxConstants.STYLE_DASHED, false))
            {
                canvas.Dashed = true;
            }

            // Draws background and foreground
            if (strokeColor != null || fillColor != null)
            {
                if (strokeColor != null)
                {
                    canvas.StrokeColor = strokeColor;
                }

                if (fillColor != null)
                {
                    if (gradientColor != null
                            && !gradientColor.Equals("transparent"))
                    {
                        canvas.SetGradient(fillColor, gradientColor, state.X,
                                state.Y, state.Width, state.Height,
                                direction);
                    }
                    else
                    {
                        canvas.FillColor = fillColor;
                    }
                }

                // Draws background and foreground of shape
                DrawShape(canvas, state, state, true);
                DrawShape(canvas, state, state, false);
            }
        }
Example #27
0
        /// <summary>
        /// see com.mxgraph.mxICanvas.DrawLabel()
        /// </summary>
        public override Object DrawLabel(string text, mxCellState state, bool html)
        {
            Dictionary<string, object> style = state.Style;
            GraphicsState graphicsState = g.Save();

            // Applies the local translation
            g.TranslateTransform(translate.X, translate.Y);

            Rectangle bounds = (state.LabelBounds != null) ? state.LabelBounds.GetRectangle() : state.GetRectangle();
            DrawText(text, bounds.X, bounds.Y, bounds.Width, bounds.Height, style);

            // Resets all changes to the graphics configuration
            g.Restore(graphicsState);

            return null;
        }
Example #28
0
        /// <summary>
        /// Draws the given element.
        /// </summary>
        /// <param name="canvas"></param>
        /// <param name="state"></param>
        /// <param name="node"></param>
        /// <param name="aspect"></param>
        protected void DrawElement(mxGdiCanvas2D canvas, mxCellState state,
                XmlElement node, mxRectangle aspect)
        {
            string name = node.Name;
            double x0 = aspect.X;
            double y0 = aspect.Y;
            double sx = aspect.Width;
            double sy = aspect.Height;
            double minScale = Math.Min(sx, sy);

            // LATER: Move to lookup table
            if (name.Equals("save"))
            {
                canvas.Save();
            }
            else if (name.Equals("restore"))
            {
                canvas.Restore();
            }
            else if (name.Equals("path"))
            {
                canvas.Begin();

                // Renders the elements inside the given path
                XmlNode childNode = node.FirstChild;

                while (childNode != null)
                {
                    if (childNode.NodeType == XmlNodeType.Element)
                    {
                        DrawElement(canvas, state, (XmlElement) childNode, aspect);
                    }

                    childNode = childNode.NextSibling;
                }
            }
            else if (name.Equals("close"))
            {
                canvas.Close();
            }
            else if (name.Equals("move"))
            {
                lastMoveX = x0 + GetDouble(node, "x") * sx;
                lastMoveY = y0 + GetDouble(node, "y") * sy;
                canvas.MoveTo(lastMoveX, lastMoveY);
            }
            else if (name.Equals("line"))
            {
                lastMoveX = x0 + GetDouble(node, "x") * sx;
                lastMoveY = y0 + GetDouble(node, "y") * sy;
                canvas.LineTo(lastMoveX, lastMoveY);
            }
            else if (name.Equals("quad"))
            {
                lastMoveX = x0 + GetDouble(node, "x2") * sx;
                lastMoveY = y0 + GetDouble(node, "y2") * sy;
                canvas.QuadTo(x0 + GetDouble(node, "x1") * sx,
                        y0 + GetDouble(node, "y1") * sy, lastMoveX, lastMoveY);
            }
            else if (name.Equals("curve"))
            {
                lastMoveX = x0 + GetDouble(node, "x3") * sx;
                lastMoveY = y0 + GetDouble(node, "y3") * sy;
                canvas.CurveTo(x0 + GetDouble(node, "x1") * sx,
                        y0 + GetDouble(node, "y1") * sy, x0 + GetDouble(node, "x2")
                                * sx, y0 + GetDouble(node, "y2") * sy, lastMoveX,
                        lastMoveY);
            }
            else if (name.Equals("arc"))
            {
                // Arc from stencil is turned into curves in image output
                double r1 = GetDouble(node, "rx") * sx;
                double r2 = GetDouble(node, "ry") * sy;
                double angle = GetDouble(node, "x-axis-rotation");
                double largeArcFlag = GetDouble(node, "large-arc-flag");
                double sweepFlag = GetDouble(node, "sweep-flag");
                double x = x0 + GetDouble(node, "x") * sx;
                double y = y0 + GetDouble(node, "y") * sy;

                double[] curves = mxUtils.ArcToCurves(this.lastMoveX,
                        this.lastMoveY, r1, r2, angle, largeArcFlag, sweepFlag, x,
                        y);

                for (int i = 0; i < curves.Length; i += 6)
                {
                    canvas.CurveTo(curves[i], curves[i + 1], curves[i + 2],
                            curves[i + 3], curves[i + 4], curves[i + 5]);

                    lastMoveX = curves[i + 4];
                    lastMoveY = curves[i + 5];
                }
            }
            else if (name.Equals("rect"))
            {
                canvas.Rect(x0 + GetDouble(node, "x") * sx,
                        y0 + GetDouble(node, "y") * sy, GetDouble(node, "w") * sx,
                        GetDouble(node, "h") * sy);
            }
            else if (name.Equals("roundrect"))
            {
                double arcsize = GetDouble(node, "arcsize");

                if (arcsize == 0)
                {
                    arcsize = mxConstants.RECTANGLE_ROUNDING_FACTOR * 100;
                }

                double w = GetDouble(node, "w") * sx;
                double h = GetDouble(node, "h") * sy;
                double factor = arcsize / 100;
                double r = Math.Min(w * factor, h * factor);

                canvas.Roundrect(x0 + GetDouble(node, "x") * sx,
                        y0 + GetDouble(node, "y") * sy, GetDouble(node, "w") * sx,
                        GetDouble(node, "h") * sy, r, r);
            }
            else if (name.Equals("ellipse"))
            {
                canvas.Ellipse(x0 + GetDouble(node, "x") * sx,
                        y0 + GetDouble(node, "y") * sy, GetDouble(node, "w") * sx,
                        GetDouble(node, "h") * sy);
            }
            else if (name.Equals("image"))
            {
                string src = EvaluateAttribute(node, "src", state);

                canvas.Image(x0 + GetDouble(node, "x") * sx,
                        y0 + GetDouble(node, "y") * sy, GetDouble(node, "w") * sx,
                        GetDouble(node, "h") * sy, src, false,
                        GetString(node, "flipH", "0").Equals("1"),
                        GetString(node, "flipV", "0").Equals("1"));
            }
            else if (name.Equals("text"))
            {
                String str = EvaluateAttribute(node, "str", state);

                canvas.Text(x0 + GetDouble(node, "x") * sx,
                        y0 + GetDouble(node, "y") * sy, 0, 0, str,
                        node.GetAttribute("align"), node.GetAttribute("valign"),
                        GetString(node, "vertical", "0").Equals("1"), false, "");
            }
            else if (name.Equals("include-shape"))
            {
                mxStencil stencil = mxStencilRegistry.GetStencil(node
                        .GetAttribute("name"));

                if (stencil != null)
                {
                    double x = x0 + GetDouble(node, "x") * sx;
                    double y = y0 + GetDouble(node, "y") * sy;
                    double w = GetDouble(node, "w") * sx;
                    double h = GetDouble(node, "h") * sy;

                    mxRectangle tmp = new mxRectangle(x, y, w, h);
                    stencil.DrawShape(canvas, state, tmp, true);
                    stencil.DrawShape(canvas, state, tmp, false);
                }
            }
            else if (name.Equals("fillstroke"))
            {
                canvas.FillAndStroke();
            }
            else if (name.Equals("fill"))
            {
                canvas.Fill();
            }
            else if (name.Equals("stroke"))
            {
                canvas.Stroke();
            }
            else if (name.Equals("strokewidth"))
            {
                canvas.StrokeWidth = GetDouble(node, "width") * minScale;
            }
            else if (name.Equals("dashed"))
            {
                canvas.Dashed = node.GetAttribute("dashed") == "1";
            }
            else if (name.Equals("dashpattern"))
            {
                string value = node.GetAttribute("pattern");

                if (value != null)
                {
                    string[] tmp = value.Split(' ');
                    StringBuilder pat = new StringBuilder();

                    for (int i = 0; i < tmp.Length; i++)
                    {
                        if (tmp[i].Length > 0)
                        {
                            pat.Append(double.Parse(tmp[i]) * minScale);
                            pat.Append(" ");
                        }
                    }

                    value = pat.ToString();
                }

                canvas.DashPattern = value;
            }
            else if (name.Equals("strokecolor"))
            {
                canvas.StrokeColor = node.GetAttribute("color");
            }
            else if (name.Equals("linecap"))
            {
                canvas.LineCap = node.GetAttribute("cap");
            }
            else if (name.Equals("linejoin"))
            {
                canvas.LineJoin = node.GetAttribute("join");
            }
            else if (name.Equals("miterlimit"))
            {
                canvas.MiterLimit = GetDouble(node, "limit");
            }
            else if (name.Equals("fillcolor"))
            {
                canvas.FillColor = node.GetAttribute("color");
            }
            else if (name.Equals("fontcolor"))
            {
                canvas.FontColor = node.GetAttribute("color");
            }
            else if (name.Equals("fontstyle"))
            {
                canvas.FontStyle = GetInt(node, "style", 0);
            }
            else if (name.Equals("fontfamily"))
            {
                canvas.FontFamily = node.GetAttribute("family");
            }
            else if (name.Equals("fontsize"))
            {
                canvas.FontSize = GetDouble(node, "size") * minScale;
            }
        }
Example #29
0
 /// <summary>
 /// see com.mxgraph.mxICanvas.DrawCell()
 /// </summary>
 public abstract Object DrawCell(mxCellState state);
Example #30
0
        /// <summary>
        /// Returns a clone of this state where all members are deeply cloned
        /// except the view and cell references, which are copied with no
        /// cloning to the new instance.
        /// </summary>
        /// <returns></returns>
        public new mxCellState Clone()
        {
            mxCellState clone = new mxCellState(view, cell, style);

            if (absolutePoints != null)
            {
                clone.absolutePoints = new List<mxPoint>();

                foreach (mxPoint pt in absolutePoints)
                {
                    clone.absolutePoints.Add(pt.Clone());
                }
            }

            if (origin != null)
            {
                clone.origin = origin.Clone();
            }

            if (absoluteOffset != null)
            {
                clone.absoluteOffset = absoluteOffset.Clone();
            }

            if (labelBounds != null)
            {
                clone.labelBounds = labelBounds.Clone();
            }

            if (boundingBox != null)
            {
                clone.boundingBox = boundingBox.Clone();
            }

            clone.terminalDistance = terminalDistance;
            clone.segments = segments;
            clone.length = length;
            clone.x = x;
            clone.y = y;
            clone.width = width;
            clone.height = height;

            return clone;
        }
Example #31
0
        /// <summary>
        /// Returns a point that defines the location of the intersection point between
        /// the perimeter and the line between the center of the shape and the given point.
        /// </summary>
        /// <param name="terminal">State for the source or target terminal.</param>
        /// <param name="next">Point that lies outside of the given terminal.</param>
        /// <param name="orthogonal">Specifies if the orthogonal projection onto
        /// the perimeter should be returned. If this is false then the intersection
        /// of the perimeter and the line between the next and the center point is
        /// returned.</param>
        /// <param name="border">Optional border between the perimeter and the shape.</param>
        public mxPoint GetPerimeterPoint(mxCellState terminal, mxPoint next, bool orthogonal, double border)
        {
            mxPoint point = null;

            if (terminal != null)
            {
                mxPerimeterFunction perimeter = GetPerimeterFunction(terminal);

                if (perimeter != null && next != null)
                {
                    mxRectangle bounds = GetPerimeterBounds(terminal, border);

                    if (bounds.Width > 0 || bounds.Height > 0)
                    {
                        point = perimeter(bounds, terminal, next, orthogonal);
                    }
                }

                if (point == null)
                {
                    point = GetPoint(terminal);
                }
            }

            return point;
        }