Beispiel #1
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);
        }
Beispiel #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;
                // TODO: Implement new shadow
                //canvas.Shadow(mxConstants.STENCIL_SHADOWCOLOR, filled);
            }

            canvas.Translate(-offset.X, -offset.Y);
        }
Beispiel #3
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);
        }
Beispiel #4
0
        /// <summary>
        /// Creates an image for the given arguments.
        /// </summary>
        public static Image CreateImage(mxGraph graph, Object[] cells, double scale, Color? background,
            bool antiAlias, mxRectangle clip, mxGdiCanvas graphicsCanvas)
        {
            mxImageCanvas canvas = (mxImageCanvas) DrawCells(graph, cells, scale, clip,
                new ImageCanvasFactory(graphicsCanvas, background, antiAlias));

            return canvas.Destroy();
        }
Beispiel #5
0
        /// <summary>
        /// Creates an image for the given arguments.
        /// </summary>
        public static Image CreateImage(mxGraph graph, Object[] cells, double scale, Color?background,
                                        bool antiAlias, mxRectangle clip, mxGdiCanvas graphicsCanvas)
        {
            mxImageCanvas canvas = (mxImageCanvas)DrawCells(graph, cells, scale, clip,
                                                            new ImageCanvasFactory(graphicsCanvas, background, antiAlias));

            return(canvas.Destroy());
        }
Beispiel #6
0
        /// <summary>
        /// First validates all bounds and then validates all points recursively on
        /// all visible cells.
        /// </summary>
        public void Validate()
        {
            Object cell = graph.Model.Root;

            if (cell != null && states.Count == 0)
            {
                mxRectangle graphBounds = GetBoundingBox(ValidateCellState(ValidateCell(cell)));
                GraphBounds = (graphBounds != null) ? graphBounds : new mxRectangle();
            }
        }
Beispiel #7
0
        /// <summary>
        /// Returns the rectangle that should be used as the perimeter of the cell.
        /// </summary>
        /// <param name="border"></param>
        /// <returns>Returns the rectangle that defines the perimeter.</returns>
        public mxRectangle GetPerimeterBounds(double border)
        {
            mxRectangle bounds = new mxRectangle(this);

            if (border != 0)
            {
                bounds.Grow(border);
            }

            return(bounds);
        }
Beispiel #8
0
        /// <summary>
        /// Returns true if the given object equals this rectangle.
        /// </summary>
        /// <returns>Returns true if obj is equal.</returns>
        new public Boolean Equals(Object obj)
        {
            if (obj is mxRectangle)
            {
                mxRectangle rect = (mxRectangle)obj;

                return(rect.X == X &&
                       rect.Y == Y &&
                       rect.Width == Width &&
                       rect.Height == height);
            }

            return(false);
        }
Beispiel #9
0
        /// <summary>
        /// First validates all bounds and then validates all points recursively on
        /// all visible cells.
        /// </summary>
        public void Validate()
        {
            Object cell = graph.Model.Root;

            if (cell != null && states.Count == 0)
            {
                ValidateBounds(null, cell);
                GraphBounds = ValidatePoints(null, cell);

                if (GraphBounds == null)
                {
                    GraphBounds = new mxRectangle();
                }
            }
        }
Beispiel #10
0
        /// <summary>
        /// Adds the given rectangle to this rectangle.
        /// </summary>
        public void Add(mxRectangle rect)
        {
            if (rect != null)
            {
                double minX = Math.Min(x, rect.x);
                double minY = Math.Min(y, rect.y);
                double maxX = Math.Max(x + width, rect.x + rect.width);
                double maxY = Math.Max(y + height, rect.y + rect.height);

                x      = minX;
                y      = minY;
                width  = maxX - minX;
                height = maxY - minY;
            }
        }
        /* (non-Dotnetdoc)
         * see com.mxgraph.mxGraphViewReader.CreateCanvas()
         */
        override public mxICanvas CreateCanvas(Dictionary <string, Object> attrs)
        {
            int width  = 0;
            int height = 0;
            int dx     = 0;
            int dy     = 0;

            mxRectangle tmp = Clip;

            if (tmp != null)
            {
                dx    -= (int)tmp.X;
                dy    -= (int)tmp.Y;
                width  = (int)tmp.Width;
                height = (int)tmp.Height;
            }
            else
            {
                int x = (int)Math.Round(mxUtils.GetDouble(attrs, "x"));
                int y = (int)Math.Round(mxUtils.GetDouble(attrs, "y"));
                width = (int)(Math.Round(mxUtils.GetDouble(attrs, "width")))
                        + border + 3;
                height = (int)(Math.Round(mxUtils.GetDouble(attrs, "height")))
                         + border + 3;

                if (cropping)
                {
                    dx = -x + 3;
                    dy = -y + 3;
                }
                else
                {
                    width  += x;
                    height += y;
                }
            }

            mxImageCanvas canvas = new mxImageCanvas(new mxGdiCanvas(),
                                                     width, height, Background, AntiAlias);

            canvas.Translate = new Point(dx, dy);

            return(canvas);
        }
Beispiel #12
0
        /// <summary>
        /// Updates the label bounds in the given state.
        /// </summary>
        /// <param name="state"></param>
        public void UpdateLabelBounds(mxCellState state)
        {
            Object cell = state.Cell;
            Dictionary <string, Object> style = state.Style;

            if (mxUtils.GetString(style, mxConstants.STYLE_OVERFLOW, "").Equals("fill"))
            {
                state.LabelBounds = new mxRectangle(state);
            }
            else
            {
                string      label        = graph.GetLabel(cell);
                mxRectangle vertexBounds = (!graph.Model.IsEdge(cell)) ?
                                           state : null;
                state.LabelBounds = mxUtils.GetLabelPaintBounds(label,
                                                                style, false, state.AbsoluteOffset, vertexBounds,
                                                                scale);
            }
        }
Beispiel #13
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));
        }
Beispiel #14
0
        /// <summary>
        /// Returns the bounding box of the shape and the label for the given
        /// cell state and its children if recurse is true.
        /// </summary>
        /// <param name="state">Cell state whose bounding box should be returned.</param>
        /// <param name="recurse">Boolean indicating if the children should be included.</param>
        public mxRectangle GetBoundingBox(mxCellState state, Boolean recurse)
        {
            mxRectangle bbox = null;

            if (state != null)
            {
                if (state.BoundingBox != null)
                {
                    bbox = (mxRectangle)state.BoundingBox.Clone();
                }

                if (recurse)
                {
                    mxIGraphModel model      = graph.Model;
                    int           childCount = model.GetChildCount(state.Cell);

                    for (int i = 0; i < childCount; i++)
                    {
                        mxRectangle bounds = GetBoundingBox(
                            GetState(model.GetChildAt(state.Cell, i)), true);

                        if (bounds != null)
                        {
                            if (bbox == null)
                            {
                                bbox = bounds;
                            }
                            else
                            {
                                bbox.Add(bounds);
                            }
                        }
                    }
                }
            }

            return(bbox);
        }
Beispiel #15
0
        /// <summary>
        /// Constructs a copy of the given geometry.
        /// </summary>
        /// <param name="geometry">Geometry to construct a copy of.</param>
        public mxGeometry(mxGeometry geometry)
            : base(geometry.X, geometry.Y, geometry.Width, geometry
                   .Height)
        {
            if (geometry.points != null)
            {
                points = new List <mxPoint>(geometry.points.Count);

                foreach (mxPoint pt in geometry.points)
                {
                    points.Add(pt.Clone());
                }
            }

            if (geometry.sourcePoint != null)
            {
                sourcePoint = geometry.sourcePoint.Clone();
            }

            if (geometry.targetPoint != null)
            {
                targetPoint = geometry.targetPoint.Clone();
            }

            if (geometry.offset != null)
            {
                offset = geometry.offset.Clone();
            }

            if (geometry.alternateBounds != null)
            {
                alternateBounds = geometry.alternateBounds.Clone();
            }

            relative = geometry.relative;
        }
Beispiel #16
0
        /// <summary>
        /// Returns the bounding box for an array of cells or null, if no cells are
        /// specified.
        /// </summary>
        public mxRectangle GetBounds(Object[] cells, bool boundingBox)
        {
            mxRectangle result = null;

            if (cells != null && cells.Length > 0)
            {
                mxIGraphModel model = graph.Model;

                for (int i = 0; i < cells.Length; i++)
                {
                    if (model.IsVertex(cells[i]) || model.IsEdge(cells[i]))
                    {
                        mxCellState state = GetState(cells[i]);

                        if (state != null)
                        {
                            mxRectangle tmp = (boundingBox) ? state.BoundingBox : state;

                            if (tmp != null)
                            {
                                if (result == null)
                                {
                                    result = new mxRectangle(tmp);
                                }
                                else
                                {
                                    result.Add(tmp);
                                }
                            }
                        }
                    }
                }
            }

            return(result);
        }
Beispiel #17
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);
        }
Beispiel #18
0
        /// <summary>
        /// First validates all bounds and then validates all points recursively on
        /// all visible cells.
        /// </summary>
        public void Validate()
        {
            Object cell = graph.Model.Root;

            if (cell != null && states.Count == 0)
            {
                ValidateBounds(null, cell);
                GraphBounds = ValidatePoints(null, cell);

                if (GraphBounds == null)
                {
                    GraphBounds = new mxRectangle();
                }
            }
        }
Beispiel #19
0
 /// <summary>
 /// Constructs a copy of the given rectangle.
 /// </summary>
 /// <param name="rect">Rectangle to construct a copy of.</param>
 public mxRectangle(mxRectangle rect)
     : this(rect.X, rect.Y, rect.Width, rect.Height)
 {
 }
Beispiel #20
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);
        }
Beispiel #21
0
        /// <summary>
        /// Returns the bounds for the given cells.
        /// </summary>
        public mxRectangle GetBoundsForCells(Object[] cells, bool includeEdges,
                bool includeDescendants, bool boundingBox)
        {
            mxRectangle result = null;

            if (cells != null && cells.Length > 0)
            {
                for (int i = 0; i < cells.Length; i++)
                {
                    mxRectangle tmp = GetCellBounds(cells[i], includeEdges,
                        includeDescendants, boundingBox);

                    if (tmp != null)
                    {
                        if (result == null)
                        {
                            result = new mxRectangle(tmp);
                        }
                        else
                        {
                            result.Add(tmp);
                        }
                    }
                }
            }

            return result;
        }
Beispiel #22
0
        /// <summary>
        /// Returns the bounds for a label for the given location and size, taking
        /// into account the alignment and spacing in the specified style, as well
        /// as the width and height of the rectangle that contains the label.
        /// (For edge labels this width and height is 0.) The scale is used to scale
        /// the given size and the spacings in the specified style.
        /// </summary>
        public static mxRectangle GetScaledLabelBounds(double x, double y, mxRectangle size,
            double outerWidth, double outerHeight, Dictionary<string, Object> style, double scale)
        {
            // Adds an inset of 3 pixels
            double inset = mxConstants.LABEL_INSET* scale;

            // Scales the size of the label
            double width = size.Width * scale + 2 * inset;
            double height = size.Height * scale;

            // Gets the global spacing and orientation
            bool horizontal = IsTrue(style, mxConstants.STYLE_HORIZONTAL, true);
            int spacing = (int)(GetInt(style, mxConstants.STYLE_SPACING) * scale);

            // Gets the alignment settings
            Object align = GetString(style, mxConstants.STYLE_ALIGN,
                    mxConstants.ALIGN_CENTER);
            Object valign = GetString(style, mxConstants.STYLE_VERTICAL_ALIGN,
                    mxConstants.ALIGN_MIDDLE);

            // Gets the vertical spacing
            int top = (int)(GetInt(style, mxConstants.STYLE_SPACING_TOP) * scale);
            int bottom = (int)(GetInt(style,
                    mxConstants.STYLE_SPACING_BOTTOM) * scale);

            // Gets the horizontal spacing
            int left = (int)(GetInt(style, mxConstants.STYLE_SPACING_LEFT) * scale);
            int right = (int)(GetInt(style,
                    mxConstants.STYLE_SPACING_RIGHT) * scale);

            // Applies the orientation to the spacings
            if (!horizontal)
            {
                int tmp = top;
                top = right;
                right = bottom;
                bottom = left;
                left = tmp;

                double tmp2 = width;
                width = height;
                height = tmp2;
            }

            // Computes the position of the label for the horizontal alignment
            if ((horizontal && align.Equals(mxConstants.ALIGN_CENTER))
                    || (!horizontal && valign.Equals(mxConstants.ALIGN_MIDDLE)))
            {
                x += (outerWidth - width) / 2 + left - right;
            }
            else if ((horizontal && align.Equals(mxConstants.ALIGN_RIGHT))
                    || (!horizontal && valign.Equals(mxConstants.ALIGN_BOTTOM)))
            {
                x += outerWidth - width - spacing - right;
            }
            else
            {
                x += spacing + left;
            }

            // Computes the position of the label for the vertical alignment
            if ((!horizontal && align.Equals(mxConstants.ALIGN_CENTER))
                    || (horizontal && valign.Equals(mxConstants.ALIGN_MIDDLE)))
            {
                y += (outerHeight - height) / 2 + top - bottom;
            }
            else if ((!horizontal && align.Equals(mxConstants.ALIGN_LEFT))
                    || (horizontal && valign.Equals(mxConstants.ALIGN_BOTTOM)))
            {
                y += outerHeight - height - spacing - bottom;
            }
            else
            {
                y += spacing + top;
            }

            return new mxRectangle(x, y, width, height);
        }
Beispiel #23
0
        /// <summary>
        /// Returns the bounding box of the rotated rectangle.
        /// </summary>
        public static mxRectangle GetBoundingBox(mxRectangle rect, double rotation)
        {
            // TODO: Check use of GraphicsPath (see mxGdiCanvas.DrawText)
            mxRectangle result = null;

            if (rect != null && rotation != 0)
            {
                double rad = ToRadians(rotation);
                double cos = Math.Cos(rad);
                double sin = Math.Sin(rad);

                mxPoint cx = new mxPoint(rect.X + rect.Width / 2,
                    rect.Y + rect.Height / 2);

                mxPoint p1 = new mxPoint(rect.X, rect.Y);
                mxPoint p2 = new mxPoint(rect.X + rect.Width, rect.Y);
                mxPoint p3 = new mxPoint(p2.X, rect.Y + rect.Height);
                mxPoint p4 = new mxPoint(rect.X, p3.Y);

                p1 = GetRotatedPoint(p1, cos, sin, cx);
                p2 = GetRotatedPoint(p2, cos, sin, cx);
                p3 = GetRotatedPoint(p3, cos, sin, cx);
                p4 = GetRotatedPoint(p4, cos, sin, cx);

                result = new mxRectangle((int)p1.X, (int)p1.Y, 0,
                        0);
                result.Add(new mxRectangle(p2.X, p2.Y, 0, 0));
                result.Add(new mxRectangle(p3.X, p3.Y, 0, 0));
                result.Add(new mxRectangle(p4.X, p4.Y, 0, 0));
            }

            return result;
        }
Beispiel #24
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);
        }
Beispiel #25
0
 /// <summary>
 /// Constructs a copy of the given rectangle.
 /// </summary>
 /// <param name="rect">Rectangle to construct a copy of.</param>
 public mxRectangle(mxRectangle rect)
     : this(rect.X, rect.Y, rect.Width, rect.Height)
 {
 }
Beispiel #26
0
        /// <summary>
        /// Draws the given cells using a Graphics2D canvas and returns the buffered image
        /// that represents the cells.
        /// </summary>
        public static mxICanvas DrawCells(mxGraph graph, Object[] cells, double scale,
                mxRectangle clip, CanvasFactory factory)
        {
            mxICanvas canvas = null;

            if (cells == null)
            {
                cells = new Object[] { graph.Model.Root };
            }

            if (cells != null)
            {
                // Gets the current state of the view
                mxGraphView view = graph.View;
                Dictionary<Object, mxCellState> states = view.States;
                double oldScale = view.Scale;

                // Keeps the existing translation as the cells might
                // be aligned to the grid in a different way in a graph
                // that has a translation other than zero
                bool eventsEnabled = view.IsEventsEnabled;

                // Disables firing of scale events so that there is no
                // repaint or update of the original graph
                view.IsEventsEnabled = false;

                try
                {
                    // TODO: Factor-out into mxTemporaryCellStates class
                    view.States = new Dictionary<Object, mxCellState>();
                    view.Scale = scale;

                    // Creates virtual parent state for validation
                    mxCellState state = view.CreateState(new mxCell());

                    // Validates the vertices and edges without adding them to
                    // the model so that the original cells are not modified
                    for (int i = 0; i < cells.Length; i++)
                    {
                        view.ValidateBounds(state, cells[i]);
                    }

                    for (int i = 0; i < cells.Length; i++)
                    {
                        view.ValidatePoints(state, cells[i]);
                    }

                    if (clip == null)
                    {
                        clip = graph.GetPaintBounds(cells);
                    }

                    if (clip != null && clip.Width > 0 && clip.Height > 0)
                    {
                        Rectangle rect = clip.GetRectangle();
                        canvas = factory.CreateCanvas(rect.Width + 1,
                                rect.Height + 1);

                        if (canvas != null)
                        {
                            double previousScale = canvas.Scale;
                            Point previousTranslate = canvas.Translate;

                            try
                            {
                                canvas.Translate = new Point(-rect.X, -rect.Y);
                                canvas.Scale = view.Scale;

                                for (int i = 0; i < cells.Length; i++)
                                {
                                    graph.DrawCell(canvas, cells[i]);
                                }
                            }
                            finally
                            {
                                canvas.Scale = previousScale;
                                canvas.Translate = previousTranslate;
                            }
                        }
                    }
                }
                finally
                {
                    view.Scale = oldScale;
                    view.States = states;
                    view.IsEventsEnabled = eventsEnabled;
                }
            }

            return canvas;
        }
Beispiel #27
0
        /// <summary>
        /// Draws the given cells using a Graphics2D canvas and returns the buffered image
        /// that represents the cells.
        /// </summary>
        public static mxICanvas DrawCells(mxGraph graph, Object[] cells, double scale,
                                          mxRectangle clip, CanvasFactory factory)
        {
            mxICanvas canvas = null;

            if (cells == null)
            {
                cells = new Object[] { graph.Model.Root };
            }

            if (cells != null)
            {
                // Gets the current state of the view
                mxGraphView view = graph.View;
                Dictionary <Object, mxCellState> states = view.States;
                double oldScale = view.Scale;

                // Keeps the existing translation as the cells might
                // be aligned to the grid in a different way in a graph
                // that has a translation other than zero
                bool eventsEnabled = view.IsEventsEnabled;

                // Disables firing of scale events so that there is no
                // repaint or update of the original graph
                view.IsEventsEnabled = false;

                try
                {
                    // TODO: Factor-out into mxTemporaryCellStates class
                    view.States = new Dictionary <Object, mxCellState>();
                    view.Scale  = scale;

                    // Creates virtual parent state for validation
                    mxCellState state = view.CreateState(new mxCell());

                    // Validates the vertices and edges without adding them to
                    // the model so that the original cells are not modified
                    for (int i = 0; i < cells.Length; i++)
                    {
                        view.ValidateBounds(state, cells[i]);
                    }

                    for (int i = 0; i < cells.Length; i++)
                    {
                        view.ValidatePoints(state, cells[i]);
                    }

                    if (clip == null)
                    {
                        clip = graph.GetPaintBounds(cells);
                    }

                    if (clip != null && clip.Width > 0 && clip.Height > 0)
                    {
                        Rectangle rect = clip.GetRectangle();
                        canvas = factory.CreateCanvas(rect.Width + 1,
                                                      rect.Height + 1);

                        if (canvas != null)
                        {
                            double previousScale     = canvas.Scale;
                            Point  previousTranslate = canvas.Translate;

                            try
                            {
                                canvas.Translate = new Point(-rect.X, -rect.Y);
                                canvas.Scale     = view.Scale;

                                for (int i = 0; i < cells.Length; i++)
                                {
                                    graph.DrawCell(canvas, cells[i]);
                                }
                            }
                            finally
                            {
                                canvas.Scale     = previousScale;
                                canvas.Translate = previousTranslate;
                            }
                        }
                    }
                }
                finally
                {
                    view.Scale           = oldScale;
                    view.States          = states;
                    view.IsEventsEnabled = eventsEnabled;
                }
            }

            return(canvas);
        }
Beispiel #28
0
 /// <summary>
 /// Creates an image for the given arguments.
 /// </summary>
 public static Image CreateImage(mxGraph graph, Object[] cells, double scale, Color? background,
     bool antiAlias, mxRectangle clip)
 {
     return CreateImage(graph, cells, scale, background, antiAlias, clip, new mxGdiCanvas());
 }
Beispiel #29
0
        /// <summary>
        /// Constructs a copy of the given geometry.
        /// </summary>
        /// <param name="geometry">Geometry to construct a copy of.</param>
        public mxGeometry(mxGeometry geometry)
            : base(geometry.X, geometry.Y, geometry.Width, geometry
                    .Height)
        {
            if (geometry.points != null)
            {
                points = new List<mxPoint>(geometry.points.Count);

                foreach (mxPoint pt in geometry.points)
                {
                    points.Add(pt.Clone());
                }
            }

            if (geometry.sourcePoint != null)
            {
                sourcePoint = geometry.sourcePoint.Clone();
            }

            if (geometry.targetPoint != null)
            {
                targetPoint = geometry.targetPoint.Clone();
            }

            if (geometry.offset != null)
            {
                offset = geometry.offset.Clone();
            }

            if (geometry.alternateBounds != null)
            {
                alternateBounds = geometry.alternateBounds.Clone();
            }

            relative = geometry.relative;
        }
Beispiel #30
0
 /// <summary>
 /// Creates an image for the given arguments.
 /// </summary>
 public static Image CreateImage(mxGraph graph, Object[] cells, double scale, Color?background,
                                 bool antiAlias, mxRectangle clip)
 {
     return(CreateImage(graph, cells, scale, background, antiAlias, clip, new mxGdiCanvas()));
 }
Beispiel #31
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);
                double rotation = GetString(node, "vertical", "0").Equals("1") ? -90 : 0;

                canvas.Text(x0 + GetDouble(node, "x") * sx,
                            y0 + GetDouble(node, "y") * sy, 0, 0, str,
                            node.GetAttribute("align"), node.GetAttribute("valign"),
                            false, "", null, false, rotation, null);
            }
            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;
            }
        }
Beispiel #32
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;
        }
Beispiel #33
0
        /// <summary>
        /// Returns the paint bounds for the given label.
        /// </summary>
        /// <returns></returns>
        public static mxRectangle GetLabelPaintBounds(String label,
            Dictionary<string, Object> style, bool isHtml, mxPoint offset,
            mxRectangle vertexBounds, double scale)
        {
            bool horizontal = mxUtils.IsTrue(style, mxConstants.STYLE_HORIZONTAL, true);
            int w = 0;

            if (vertexBounds != null &&
                GetString(style, mxConstants.STYLE_WHITE_SPACE, "nowrap").Equals("wrap"))
            {
                if (horizontal)
                {
                    w = (int)(vertexBounds.Width / scale);
                }
                else
                {
                    w = (int)(vertexBounds.Height / scale);
                }
            }

            mxRectangle size = mxUtils.GetLabelSize(label, style, w);

            double x = offset.X;
            double y = offset.Y;
            double width = 0;
            double height = 0;

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

                // Limits the label to the swimlane title
                if (mxUtils.GetString(style, mxConstants.STYLE_SHAPE, "").Equals(
                    mxConstants.SHAPE_SWIMLANE))
                {
                    double start = mxUtils.GetDouble(style, mxConstants.STYLE_STARTSIZE,
                        mxConstants.DEFAULT_STARTSIZE) * scale;

                    if (horizontal)
                    {
                        width += vertexBounds.Width;
                        height += start;
                    }
                    else
                    {
                        width += start;
                        height += vertexBounds.Height;
                    }
                }
                else
                {
                    width += vertexBounds.Width;
                    height += vertexBounds.Height;
                }
            }

            return mxUtils.GetScaledLabelBounds(x, y,
                size, width, height, style, scale);
        }
Beispiel #34
0
        /// <summary>
        /// Returns the bounding box for an array of cells or null, if no cells are
        /// specified.
        /// </summary>
        public mxRectangle GetBounds(Object[] cells, bool boundingBox)
        {
            mxRectangle result = null;

            if (cells != null && cells.Length > 0)
            {
                mxIGraphModel model = graph.Model;

                for (int i = 0; i < cells.Length; i++)
                {
                    if (model.IsVertex(cells[i]) || model.IsEdge(cells[i]))
                    {
                        mxCellState state = GetState(cells[i]);

                        if (state != null)
                        {
                            mxRectangle tmp = (boundingBox) ? state.BoundingBox : state;

                            if (tmp != null)
                            {
                                if (result == null)
                                {
                                    result = new mxRectangle(tmp);
                                }
                                else
                                {
                                    result.Add(tmp);
                                }
                            }
                        }
                    }
                }
            }

            return result;
        }
Beispiel #35
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;
        }
Beispiel #36
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);
        }
Beispiel #37
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;
        }
Beispiel #38
0
        /// <summary>
        /// Validates the points for the state of the given cell recursively if the
        /// cell is not collapsed and returns the bounding box of all visited states
        /// as a rectangle.
        /// </summary>
        public mxRectangle ValidatePoints(mxCellState parentState, Object cell)
        {
            mxIGraphModel model = graph.Model;
            mxCellState state = GetState(cell);
            mxRectangle bbox = null;

            if (state != null)
            {
                mxGeometry geo = graph.GetCellGeometry(cell);

                if (geo != null && model.IsEdge(cell))
                {
                    // Updates the points on the source terminal if its an edge
                    mxCellState source = GetState(GetVisibleTerminal(cell, true));

                    if (source != null && model.IsEdge(source.Cell) &&
                        !model.IsAncestor(source, cell))
                    {
                        mxCellState tmp = GetState(model.GetParent(source.Cell));
                        ValidatePoints(tmp, source.Cell);
                    }

                    // Updates the points on the target terminal if its an edge
                    mxCellState target = GetState(GetVisibleTerminal(cell, false));

                    if (target != null && model.IsEdge(target.Cell) &&
                        !model.IsAncestor(target.Cell, cell))
                    {
                        mxCellState tmp = GetState(model.GetParent(target.Cell));
                        ValidatePoints(tmp, target.Cell);
                    }

                    UpdateFixedTerminalPoints(state, source, target);
                    UpdatePoints(state, geo.Points, source, target);
                    UpdateFloatingTerminalPoints(state, source, target);
                    UpdateEdgeBounds(state);
                    state.AbsoluteOffset = GetPoint(state, geo);
                }
                else if (geo != null &&
                    geo.Relative &&
                    parentState != null &&
                    model.IsEdge(parentState.Cell))
                {
                    mxPoint origin = GetPoint(parentState, geo);

                    if (origin != null)
                    {
                        state.X = origin.X;
                        state.Y = origin.Y;

                        origin.X = (origin.X / scale) - translate.X;
                        origin.Y = (origin.Y / scale) - translate.Y;
                        state.Origin = origin;

                        childMoved(parentState, state);
                    }
                }

                if (model.IsEdge(cell) || model.IsVertex(cell))
                {
                    UpdateLabelBounds(state);
                    bbox = new mxRectangle(UpdateBoundingBox(state));
                }
            }

            if (state != null && !graph.IsCellCollapsed(cell))
            {
                int childCount = model.GetChildCount(cell);

                for (int i = 0; i < childCount; i++)
                {
                    Object child = model.GetChildAt(cell, i);
                    mxRectangle bounds = ValidatePoints(state, child);

                    if (bounds != null)
                    {
                        if (bbox == null)
                        {
                            bbox = bounds;
                        }
                        else
                        {
                            bbox.Add(bounds);
                        }
                    }
                }
            }

            return bbox;
        }
Beispiel #39
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;
            }
        }
Beispiel #40
0
        /// <summary>
        /// Validates the points for the state of the given cell recursively if the
        /// cell is not collapsed and returns the bounding box of all visited states
        /// as a rectangle.
        /// </summary>
        public mxRectangle ValidatePoints(mxCellState parentState, Object cell)
        {
            mxIGraphModel model = graph.Model;
            mxCellState   state = GetState(cell);
            mxRectangle   bbox  = null;

            if (state != null)
            {
                mxGeometry geo = graph.GetCellGeometry(cell);

                if (geo != null && model.IsEdge(cell))
                {
                    // Updates the points on the source terminal if its an edge
                    mxCellState source = GetState(GetVisibleTerminal(cell, true));

                    if (source != null && model.IsEdge(source.Cell) &&
                        !model.IsAncestor(source, cell))
                    {
                        mxCellState tmp = GetState(model.GetParent(source.Cell));
                        ValidatePoints(tmp, source.Cell);
                    }

                    // Updates the points on the target terminal if its an edge
                    mxCellState target = GetState(GetVisibleTerminal(cell, false));

                    if (target != null && model.IsEdge(target.Cell) &&
                        !model.IsAncestor(target.Cell, cell))
                    {
                        mxCellState tmp = GetState(model.GetParent(target.Cell));
                        ValidatePoints(tmp, target.Cell);
                    }

                    UpdateFixedTerminalPoints(state, source, target);
                    UpdatePoints(state, geo.Points, source, target);
                    UpdateFloatingTerminalPoints(state, source, target);
                    UpdateEdgeBounds(state);
                    state.AbsoluteOffset = GetPoint(state, geo);
                }
                else if (geo != null &&
                         geo.Relative &&
                         parentState != null &&
                         model.IsEdge(parentState.Cell))
                {
                    mxPoint origin = GetPoint(parentState, geo);

                    if (origin != null)
                    {
                        state.X = origin.X;
                        state.Y = origin.Y;

                        origin.X     = (origin.X / scale) - translate.X;
                        origin.Y     = (origin.Y / scale) - translate.Y;
                        state.Origin = origin;

                        childMoved(parentState, state);
                    }
                }

                if (model.IsEdge(cell) || model.IsVertex(cell))
                {
                    UpdateLabelBounds(state);
                    bbox = new mxRectangle(UpdateBoundingBox(state));
                }
            }

            if (state != null && !graph.IsCellCollapsed(cell))
            {
                int childCount = model.GetChildCount(cell);

                for (int i = 0; i < childCount; i++)
                {
                    Object      child  = model.GetChildAt(cell, i);
                    mxRectangle bounds = ValidatePoints(state, child);

                    if (bounds != null)
                    {
                        if (bbox == null)
                        {
                            bbox = bounds;
                        }
                        else
                        {
                            bbox.Add(bounds);
                        }
                    }
                }
            }

            return(bbox);
        }
Beispiel #41
0
        /// <summary>
        /// Returns the rectangle that should be used as the perimeter of the cell.
        /// </summary>
        /// <param name="border"></param>
        /// <returns>Returns the rectangle that defines the perimeter.</returns>
        public mxRectangle GetPerimeterBounds(double border)
        {
            mxRectangle bounds = new mxRectangle(this);

            if (border != 0)
            {
                bounds.Grow(border);
            }

            return bounds;
        }
Beispiel #42
0
        /// <summary>
        /// Adds the given rectangle to this rectangle.
        /// </summary>
        public void Add(mxRectangle rect)
        {
            if (rect != null)
            {
                double minX = Math.Min(x, rect.x);
                double minY = Math.Min(y, rect.y);
                double maxX = Math.Max(x + width, rect.x + rect.width);
                double maxY = Math.Max(y + height, rect.y + rect.height);

                x = minX;
                y = minY;
                width = maxX - minX;
                height = maxY - minY;
            }
        }