StateMachineDesignerPaint.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / Activities / Designers / StateMachineDesignerPaint.cs / 1305376 / StateMachineDesignerPaint.cs

                            namespace System.Workflow.Activities 
{
    using System;
    using System.Text;
    using System.Reflection; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.CodeDom;
    using System.ComponentModel; 
    using System.ComponentModel.Design;
    using System.Drawing.Design;
    using System.Drawing;
    using System.Drawing.Drawing2D; 
    using System.Diagnostics;
    using System.IO; 
    using System.Windows.Forms; 
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Design; 
    using System.Runtime.Serialization;

    #region StateMachineDesignerPaint
 
    internal static class StateMachineDesignerPaint
    { 
        // same as AmbientTheme.FadeBrush 
        internal static readonly Brush FadeBrush = new SolidBrush(Color.FromArgb(120, 255, 255, 255));
 
        internal static Size MeasureString(Graphics graphics, Font font, string text, StringAlignment alignment, Size maxSize)
        {
            // copied from DesignerHelpers.cs
            SizeF textSize = SizeF.Empty; 
            if (maxSize.IsEmpty)
            { 
                textSize = graphics.MeasureString(text, font); 
            }
            else 
            {
                StringFormat format = new StringFormat();
                format.Alignment = alignment;
                format.LineAlignment = StringAlignment.Center; 
                format.Trimming = StringTrimming.EllipsisCharacter;
                format.FormatFlags = StringFormatFlags.LineLimit; 
                textSize = graphics.MeasureString(text, font, new SizeF(maxSize.Width, maxSize.Height), format); 
            }
 
            return new Size(Convert.ToInt32(Math.Ceiling(textSize.Width)), Convert.ToInt32(Math.Ceiling(textSize.Height)));
        }
        /// 
        /// Makes sure that rectangle is completely contained in the bounds rectangle 
        /// 
        ///  
        ///  
        /// 
        internal static Rectangle TrimRectangle(Rectangle rectangle, Rectangle bounds) 
        {
            int left = rectangle.Left;
            int top = rectangle.Top;
            int width = rectangle.Width; 
            int height = rectangle.Height;
 
            if (left < bounds.Left) 
                left = bounds.Left;
 
            if (top < bounds.Top)
                top = bounds.Top;

            if ((left + width) > bounds.Right) 
                width -= rectangle.Right - bounds.Right;
 
            if ((top + height) > bounds.Bottom) 
                height -= rectangle.Bottom - bounds.Bottom;
 
            return new Rectangle(left, top, width, height);
        }

        private static Point[] OptimizeConnectorPoints(Point[] points) 
        {
            Debug.Assert(points.Length >= 2); 
            List optimized = new List(); 
            optimized.Add(points[0]);
            Point p1; 
            Point p2 = points[0];
            Point p3 = points[1];

            if ((p2.X != p3.X) && (p2.Y != p3.Y)) 
                optimized.Add(new Point(p3.X, p2.Y));
 
            for (int i = 2; i < points.Length; i++) 
            {
                p1 = p2; 
                p2 = p3;
                p3 = points[i];
                if ((p1.X == p2.X) && (p2.X == p3.X) ||
                    (p1.Y == p2.Y) && (p2.Y == p3.Y)) 
                    continue;
 
                optimized.Add(p2); 
                if ((p2.X != p3.X) && (p2.Y != p3.Y))
                    optimized.Add(new Point(p3.X, p2.Y)); 
            }

            optimized.Add(points[points.Length - 1]);
 
            return optimized.ToArray();
        } 
 
        internal static void DrawConnector(Graphics graphics, Pen pen, Point[] points, Size connectorCapSize, Size maxCapSize, LineAnchor startConnectorCap, LineAnchor endConnectorCap)
        { 
            if (points.GetLength(0) < 2)
                return;

            points = OptimizeConnectorPoints(points); 

            //First we start with drawing start cap 
            GraphicsPath startCap = null; 
            float startCapInset = 0.0f;
            if (startConnectorCap != LineAnchor.None) 
            {
                Point[] startSegment = new Point[] { points[0], points[1] };
                int capSize = (startSegment[0].Y == startSegment[1].Y) ? connectorCapSize.Width : connectorCapSize.Height;
                capSize += (capSize % 2); 
                capSize = Math.Min(Math.Min(capSize, maxCapSize.Width), maxCapSize.Height);
                startCap = GetLineCap(startConnectorCap, capSize, out startCapInset); 
 
                //Now if user has requested us to fill the line cap then we do so
                //THIS IS A WORKAROUND IN FILLING THE CUSTOM CAPS AS GDI+ HAS A 
                bool fill = (startCap != null && (((int)startConnectorCap % 2) == 0) && (startSegment[0].X == startSegment[1].X || startSegment[0].Y == startSegment[1].Y));
                if (fill)
                {
                    Matrix oldTransform = graphics.Transform; 
                    graphics.TranslateTransform(startSegment[0].X, startSegment[0].Y);
                    if (startSegment[0].Y == startSegment[1].Y) 
                        graphics.RotateTransform((startSegment[0].X < startSegment[1].X) ? 90.0f : 270.0f); 
                    else
                        graphics.RotateTransform((startSegment[0].Y < startSegment[1].Y) ? 180.0f : 0.0f); 
                    using (Brush penBrush = new SolidBrush(pen.Color))
                        graphics.FillPath(penBrush, startCap);
                    graphics.Transform = (oldTransform != null) ? oldTransform : new Matrix();
                } 
            }
 
            GraphicsPath endCap = null; 
            float endCapInset = 0.0f;
            if (endConnectorCap != LineAnchor.None) 
            {
                Point[] endSegment = new Point[] { points[points.GetLength(0) - 2], points[points.GetLength(0) - 1] };
                int capSize = (endSegment[0].Y == endSegment[1].Y) ? connectorCapSize.Width : connectorCapSize.Height;
                capSize += (capSize % 2); 
                capSize = Math.Min(Math.Min(capSize, maxCapSize.Width), maxCapSize.Height);
                endCap = GetLineCap(endConnectorCap, capSize, out endCapInset); 
 
                //Now if user has requested us to fill the line cap then we do so,
                //THIS IS A WORKAROUND IN FILLING THE CUSTOM CAPS AS GDI+ HAS A 
                bool fill = (endCap != null && (((int)endConnectorCap % 2) == 0) && (endSegment[0].X == endSegment[1].X || endSegment[0].Y == endSegment[1].Y));
                if (fill)
                {
                    Matrix oldTransform = graphics.Transform; 
                    graphics.TranslateTransform(endSegment[1].X, endSegment[1].Y);
                    if (endSegment[0].Y == endSegment[1].Y) 
                        graphics.RotateTransform((endSegment[0].X < endSegment[1].X) ? 270.0f : 90.0f); 
                    else
                        graphics.RotateTransform((endSegment[0].Y < endSegment[1].Y) ? 0.0f : 180.0f); 
                    using (Brush penBrush = new SolidBrush(pen.Color))
                        graphics.FillPath(penBrush, endCap);
                    graphics.Transform = (oldTransform != null) ? oldTransform : new Matrix();
                } 
            }
 
            if (startCap != null) 
            {
                CustomLineCap customStartCap = new CustomLineCap(null, startCap); 
                customStartCap.WidthScale = 1.0f / pen.Width;
                customStartCap.BaseInset = startCapInset;
                pen.CustomStartCap = customStartCap;
            } 

            if (endCap != null) 
            { 
                CustomLineCap customEndCap = new CustomLineCap(null, endCap);
                customEndCap.WidthScale = 1.0f / pen.Width; 
                customEndCap.BaseInset = endCapInset;
                pen.CustomEndCap = customEndCap;
            }
 
            using (GraphicsPath path = GetRoundedPath(points, StateDesignerConnector.ConnectorPadding / 2))
            { 
                graphics.DrawPath(pen, path); 
            }
 
            if (startCap != null)
            {
                CustomLineCap disposableLineCap = pen.CustomStartCap;
                pen.StartCap = LineCap.Flat; 
                disposableLineCap.Dispose();
            } 
 
            if (endCap != null)
            { 
                CustomLineCap disposableLineCap = pen.CustomEndCap;
                pen.EndCap = LineCap.Flat;
                disposableLineCap.Dispose();
            } 
        }
 
        private static GraphicsPath GetRoundedPath(Point[] points, int radius) 
        {
            Debug.Assert(points.Length >= 2); 
            GraphicsPath path = new GraphicsPath();
            if (points.Length == 2)
            {
                path.AddLine(points[0], points[1]); 
                return path;
            } 
 
            int diameter = radius * 2;
 
            Point p1 = points[0];
            Point p2 = points[1];
            Point p3 = points[2];
            int previousConnectorSize; 
            int currentConnectorSize = GetDistance(p1, p2);
            int nextConnectorSize = GetDistance(p2, p3); 
            ArrowDirection direction1 = GetDirection(p1, p2); 
            ArrowDirection direction2 = GetDirection(p2, p3);
 
            if (currentConnectorSize < diameter || nextConnectorSize < diameter)
            {
                AddSegment(path, radius, p1, p2, false, false, direction1);
            } 
            else
            { 
                AddSegment(path, radius, p1, p2, false, true, direction1); 
                AddRoundedCorner(path, diameter, p2, direction1, direction2);
            } 
            int i = 2;
            while (i < (points.Length - 1))
            {
                previousConnectorSize = currentConnectorSize; 
                currentConnectorSize = nextConnectorSize;
                direction1 = direction2; 
                p1 = p2; 
                p2 = p3;
                p3 = points[i + 1]; 
                direction2 = GetDirection(p2, p3);
                nextConnectorSize = GetDistance(p2, p3);
                if (currentConnectorSize >= diameter && nextConnectorSize >= diameter)
                { 
                    AddSegment(path, radius, p1, p2, (previousConnectorSize >= diameter), true, direction1);
                    AddRoundedCorner(path, diameter, p2, direction1, direction2); 
                } 
                else
                { 
                    AddSegment(path, radius, p1, p2, (previousConnectorSize >= diameter), false, direction1);
                }

                i++; 
            }
 
            AddSegment(path, radius, p2, p3, 
                (currentConnectorSize >= diameter && nextConnectorSize >= diameter),
                false, direction2); 

            return path;
        }
 
        private static int GetDistance(Point p1, Point p2)
        { 
            if (p1.X == p2.X) 
                return Math.Abs(p1.Y - p2.Y);
            else 
                return Math.Abs(p1.X - p2.X);
        }

        private static void AddSegment(GraphicsPath path, int radius, Point p1, Point p2, bool roundP1, bool roundP2, ArrowDirection direction) 
        {
            if (roundP1) 
            { 
                switch (direction)
                { 
                    case ArrowDirection.Down:
                        p1.Y += radius;
                        break;
                    case ArrowDirection.Up: 
                        p1.Y -= radius;
                        break; 
                    case ArrowDirection.Left: 
                        p1.X -= radius;
                        break; 
                    default:
                        p1.X += radius;
                        break;
                } 
            }
            if (roundP2) 
            { 
                switch (direction)
                { 
                    case ArrowDirection.Down:
                        p2.Y -= radius;
                        break;
                    case ArrowDirection.Up: 
                        p2.Y += radius;
                        break; 
                    case ArrowDirection.Left: 
                        p2.X += radius;
                        break; 
                    default:
                        p2.X -= radius;
                        break;
                } 
            }
            path.AddLine(p1, p2); 
        } 

        private static void AddRoundedCorner(GraphicsPath path, int diameter, Point midPoint, ArrowDirection direction1, ArrowDirection direction2) 
        {
            switch (direction1)
            {
                case ArrowDirection.Left: 
                    if (direction2 == ArrowDirection.Down)
                        path.AddArc(midPoint.X, midPoint.Y, diameter, diameter, 270f, -90f); 
                    else 
                        path.AddArc(midPoint.X, midPoint.Y - diameter, diameter, diameter, 90f, 90f);
                    break; 
                case ArrowDirection.Right:
                    if (direction2 == ArrowDirection.Down)
                        path.AddArc(midPoint.X - diameter, midPoint.Y, diameter, diameter, 270f, 90f);
                    else 
                        path.AddArc(midPoint.X - diameter, midPoint.Y - diameter, diameter, diameter, 90f, -90f);
                    break; 
                case ArrowDirection.Up: 
                    if (direction2 == ArrowDirection.Left)
                        path.AddArc(midPoint.X - diameter, midPoint.Y, diameter, diameter, 0f, -90f); 
                    else
                        path.AddArc(midPoint.X, midPoint.Y, diameter, diameter, 180f, 90f);
                    break;
                default: 
                    if (direction2 == ArrowDirection.Left)
                        path.AddArc(midPoint.X - diameter, midPoint.Y - diameter, diameter, diameter, 0f, 90f); 
                    else 
                        path.AddArc(midPoint.X, midPoint.Y - diameter, diameter, diameter, 180f, -90f);
                    break; 
            }
        }

        private static ArrowDirection GetDirection(Point start, Point end) 
        {
            // we only support vertical or horizotal lines. No diagonals 
            Debug.Assert(start.X == end.X || start.Y == end.Y); 

            if (start.X == end.X) 
                // vertical
                if (start.Y < end.Y)
                    // top to bottom
                    return ArrowDirection.Down; 
                else
                    // Bottom to Top 
                    return ArrowDirection.Up; 
            else
                // horizontal 
                if (start.X < end.X)
                    // left to right
                    return ArrowDirection.Right;
                else 
                    // right to left
                    return ArrowDirection.Left; 
        } 

 

        //

        internal static GraphicsPath GetLineCap(LineAnchor lineCap, int capsize, out float capinset) 
        {
            //WE DO NOT SUPPORT ARROWCAPS FOR ANGULAR CONNECTORS FOR NOW 
            capinset = 0.0f; 
            capinset = (float)capsize / 2;
            Size capSize = new Size(capsize, capsize); 

            GraphicsPath lineCapPath = new GraphicsPath();
            switch (lineCap)
            { 
                case LineAnchor.Arrow:
                case LineAnchor.ArrowAnchor: 
                    int arcRadius = capSize.Height / 3; 
                    lineCapPath.AddLine(capSize.Width / 2, -capSize.Height, 0, 0);
                    lineCapPath.AddLine(0, 0, -capSize.Width / 2, -capSize.Height); 
                    lineCapPath.AddLine(-capSize.Width / 2, -capSize.Height, 0, -capSize.Height + arcRadius);
                    lineCapPath.AddLine(0, -capSize.Height + arcRadius, capSize.Width / 2, -capSize.Height);
                    capinset = capSize.Height - arcRadius;
                    break; 

                case LineAnchor.Diamond: 
                case LineAnchor.DiamondAnchor: 
                    lineCapPath.AddLine(0, -capSize.Height, capSize.Width / 2, -capSize.Height / 2);
                    lineCapPath.AddLine(capSize.Width / 2, -capSize.Height / 2, 0, 0); 
                    lineCapPath.AddLine(0, 0, -capSize.Width / 2, -capSize.Height / 2);
                    lineCapPath.AddLine(-capSize.Width / 2, -capSize.Height / 2, 0, -capSize.Height);
                    break;
 
                case LineAnchor.Round:
                case LineAnchor.RoundAnchor: 
                    lineCapPath.AddEllipse(new Rectangle(-capSize.Width / 2, -capSize.Height, capSize.Width, capSize.Height)); 
                    break;
 
                case LineAnchor.Rectangle:
                case LineAnchor.RectangleAnchor:
                    lineCapPath.AddRectangle(new Rectangle(-capSize.Width / 2, -capSize.Height, capSize.Width, capSize.Height));
                    break; 

                case LineAnchor.RoundedRectangle: 
                case LineAnchor.RoundedRectangleAnchor: 
                    arcRadius = capSize.Height / 4;
                    lineCapPath.AddPath(ActivityDesignerPaint.GetRoundedRectanglePath(new Rectangle(-capSize.Width / 2, -capSize.Height, capSize.Width, capSize.Height), arcRadius), true); 
                    break;
            }

            lineCapPath.CloseFigure(); 
            return lineCapPath;
        } 
 
        internal static GraphicsPath GetDesignerPath(ActivityDesigner designer, Rectangle bounds, ActivityDesignerTheme designerTheme)
        { 
            GraphicsPath designerPath = new GraphicsPath();

            if (designer == GetSafeRootDesigner(designer.Activity.Site) && ((IWorkflowRootDesigner)designer).InvokingDesigner == null)
            { 
                designerPath.AddRectangle(bounds);
            } 
            else 
            {
                // Work around: This should come from AmbientTheme.ArcDiameter 
                // but it is internal
                int arcDiameter = 8;
                if (designerTheme != null && designerTheme.DesignerGeometry == DesignerGeometry.RoundedRectangle)
                    designerPath.AddPath(ActivityDesignerPaint.GetRoundedRectanglePath(bounds, arcDiameter), true); 
                else
                    designerPath.AddRectangle(bounds); 
            } 

            return designerPath; 
        }

        internal static ActivityDesigner GetSafeRootDesigner(IServiceProvider serviceProvider)
        { 
            return (serviceProvider != null) ? ActivityDesigner.GetRootDesigner(serviceProvider) : null;
        } 
    } 
    #endregion
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
namespace System.Workflow.Activities 
{
    using System;
    using System.Text;
    using System.Reflection; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Collections.ObjectModel; 
    using System.CodeDom;
    using System.ComponentModel; 
    using System.ComponentModel.Design;
    using System.Drawing.Design;
    using System.Drawing;
    using System.Drawing.Drawing2D; 
    using System.Diagnostics;
    using System.IO; 
    using System.Windows.Forms; 
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Design; 
    using System.Runtime.Serialization;

    #region StateMachineDesignerPaint
 
    internal static class StateMachineDesignerPaint
    { 
        // same as AmbientTheme.FadeBrush 
        internal static readonly Brush FadeBrush = new SolidBrush(Color.FromArgb(120, 255, 255, 255));
 
        internal static Size MeasureString(Graphics graphics, Font font, string text, StringAlignment alignment, Size maxSize)
        {
            // copied from DesignerHelpers.cs
            SizeF textSize = SizeF.Empty; 
            if (maxSize.IsEmpty)
            { 
                textSize = graphics.MeasureString(text, font); 
            }
            else 
            {
                StringFormat format = new StringFormat();
                format.Alignment = alignment;
                format.LineAlignment = StringAlignment.Center; 
                format.Trimming = StringTrimming.EllipsisCharacter;
                format.FormatFlags = StringFormatFlags.LineLimit; 
                textSize = graphics.MeasureString(text, font, new SizeF(maxSize.Width, maxSize.Height), format); 
            }
 
            return new Size(Convert.ToInt32(Math.Ceiling(textSize.Width)), Convert.ToInt32(Math.Ceiling(textSize.Height)));
        }
        /// 
        /// Makes sure that rectangle is completely contained in the bounds rectangle 
        /// 
        ///  
        ///  
        /// 
        internal static Rectangle TrimRectangle(Rectangle rectangle, Rectangle bounds) 
        {
            int left = rectangle.Left;
            int top = rectangle.Top;
            int width = rectangle.Width; 
            int height = rectangle.Height;
 
            if (left < bounds.Left) 
                left = bounds.Left;
 
            if (top < bounds.Top)
                top = bounds.Top;

            if ((left + width) > bounds.Right) 
                width -= rectangle.Right - bounds.Right;
 
            if ((top + height) > bounds.Bottom) 
                height -= rectangle.Bottom - bounds.Bottom;
 
            return new Rectangle(left, top, width, height);
        }

        private static Point[] OptimizeConnectorPoints(Point[] points) 
        {
            Debug.Assert(points.Length >= 2); 
            List optimized = new List(); 
            optimized.Add(points[0]);
            Point p1; 
            Point p2 = points[0];
            Point p3 = points[1];

            if ((p2.X != p3.X) && (p2.Y != p3.Y)) 
                optimized.Add(new Point(p3.X, p2.Y));
 
            for (int i = 2; i < points.Length; i++) 
            {
                p1 = p2; 
                p2 = p3;
                p3 = points[i];
                if ((p1.X == p2.X) && (p2.X == p3.X) ||
                    (p1.Y == p2.Y) && (p2.Y == p3.Y)) 
                    continue;
 
                optimized.Add(p2); 
                if ((p2.X != p3.X) && (p2.Y != p3.Y))
                    optimized.Add(new Point(p3.X, p2.Y)); 
            }

            optimized.Add(points[points.Length - 1]);
 
            return optimized.ToArray();
        } 
 
        internal static void DrawConnector(Graphics graphics, Pen pen, Point[] points, Size connectorCapSize, Size maxCapSize, LineAnchor startConnectorCap, LineAnchor endConnectorCap)
        { 
            if (points.GetLength(0) < 2)
                return;

            points = OptimizeConnectorPoints(points); 

            //First we start with drawing start cap 
            GraphicsPath startCap = null; 
            float startCapInset = 0.0f;
            if (startConnectorCap != LineAnchor.None) 
            {
                Point[] startSegment = new Point[] { points[0], points[1] };
                int capSize = (startSegment[0].Y == startSegment[1].Y) ? connectorCapSize.Width : connectorCapSize.Height;
                capSize += (capSize % 2); 
                capSize = Math.Min(Math.Min(capSize, maxCapSize.Width), maxCapSize.Height);
                startCap = GetLineCap(startConnectorCap, capSize, out startCapInset); 
 
                //Now if user has requested us to fill the line cap then we do so
                //THIS IS A WORKAROUND IN FILLING THE CUSTOM CAPS AS GDI+ HAS A 
                bool fill = (startCap != null && (((int)startConnectorCap % 2) == 0) && (startSegment[0].X == startSegment[1].X || startSegment[0].Y == startSegment[1].Y));
                if (fill)
                {
                    Matrix oldTransform = graphics.Transform; 
                    graphics.TranslateTransform(startSegment[0].X, startSegment[0].Y);
                    if (startSegment[0].Y == startSegment[1].Y) 
                        graphics.RotateTransform((startSegment[0].X < startSegment[1].X) ? 90.0f : 270.0f); 
                    else
                        graphics.RotateTransform((startSegment[0].Y < startSegment[1].Y) ? 180.0f : 0.0f); 
                    using (Brush penBrush = new SolidBrush(pen.Color))
                        graphics.FillPath(penBrush, startCap);
                    graphics.Transform = (oldTransform != null) ? oldTransform : new Matrix();
                } 
            }
 
            GraphicsPath endCap = null; 
            float endCapInset = 0.0f;
            if (endConnectorCap != LineAnchor.None) 
            {
                Point[] endSegment = new Point[] { points[points.GetLength(0) - 2], points[points.GetLength(0) - 1] };
                int capSize = (endSegment[0].Y == endSegment[1].Y) ? connectorCapSize.Width : connectorCapSize.Height;
                capSize += (capSize % 2); 
                capSize = Math.Min(Math.Min(capSize, maxCapSize.Width), maxCapSize.Height);
                endCap = GetLineCap(endConnectorCap, capSize, out endCapInset); 
 
                //Now if user has requested us to fill the line cap then we do so,
                //THIS IS A WORKAROUND IN FILLING THE CUSTOM CAPS AS GDI+ HAS A 
                bool fill = (endCap != null && (((int)endConnectorCap % 2) == 0) && (endSegment[0].X == endSegment[1].X || endSegment[0].Y == endSegment[1].Y));
                if (fill)
                {
                    Matrix oldTransform = graphics.Transform; 
                    graphics.TranslateTransform(endSegment[1].X, endSegment[1].Y);
                    if (endSegment[0].Y == endSegment[1].Y) 
                        graphics.RotateTransform((endSegment[0].X < endSegment[1].X) ? 270.0f : 90.0f); 
                    else
                        graphics.RotateTransform((endSegment[0].Y < endSegment[1].Y) ? 0.0f : 180.0f); 
                    using (Brush penBrush = new SolidBrush(pen.Color))
                        graphics.FillPath(penBrush, endCap);
                    graphics.Transform = (oldTransform != null) ? oldTransform : new Matrix();
                } 
            }
 
            if (startCap != null) 
            {
                CustomLineCap customStartCap = new CustomLineCap(null, startCap); 
                customStartCap.WidthScale = 1.0f / pen.Width;
                customStartCap.BaseInset = startCapInset;
                pen.CustomStartCap = customStartCap;
            } 

            if (endCap != null) 
            { 
                CustomLineCap customEndCap = new CustomLineCap(null, endCap);
                customEndCap.WidthScale = 1.0f / pen.Width; 
                customEndCap.BaseInset = endCapInset;
                pen.CustomEndCap = customEndCap;
            }
 
            using (GraphicsPath path = GetRoundedPath(points, StateDesignerConnector.ConnectorPadding / 2))
            { 
                graphics.DrawPath(pen, path); 
            }
 
            if (startCap != null)
            {
                CustomLineCap disposableLineCap = pen.CustomStartCap;
                pen.StartCap = LineCap.Flat; 
                disposableLineCap.Dispose();
            } 
 
            if (endCap != null)
            { 
                CustomLineCap disposableLineCap = pen.CustomEndCap;
                pen.EndCap = LineCap.Flat;
                disposableLineCap.Dispose();
            } 
        }
 
        private static GraphicsPath GetRoundedPath(Point[] points, int radius) 
        {
            Debug.Assert(points.Length >= 2); 
            GraphicsPath path = new GraphicsPath();
            if (points.Length == 2)
            {
                path.AddLine(points[0], points[1]); 
                return path;
            } 
 
            int diameter = radius * 2;
 
            Point p1 = points[0];
            Point p2 = points[1];
            Point p3 = points[2];
            int previousConnectorSize; 
            int currentConnectorSize = GetDistance(p1, p2);
            int nextConnectorSize = GetDistance(p2, p3); 
            ArrowDirection direction1 = GetDirection(p1, p2); 
            ArrowDirection direction2 = GetDirection(p2, p3);
 
            if (currentConnectorSize < diameter || nextConnectorSize < diameter)
            {
                AddSegment(path, radius, p1, p2, false, false, direction1);
            } 
            else
            { 
                AddSegment(path, radius, p1, p2, false, true, direction1); 
                AddRoundedCorner(path, diameter, p2, direction1, direction2);
            } 
            int i = 2;
            while (i < (points.Length - 1))
            {
                previousConnectorSize = currentConnectorSize; 
                currentConnectorSize = nextConnectorSize;
                direction1 = direction2; 
                p1 = p2; 
                p2 = p3;
                p3 = points[i + 1]; 
                direction2 = GetDirection(p2, p3);
                nextConnectorSize = GetDistance(p2, p3);
                if (currentConnectorSize >= diameter && nextConnectorSize >= diameter)
                { 
                    AddSegment(path, radius, p1, p2, (previousConnectorSize >= diameter), true, direction1);
                    AddRoundedCorner(path, diameter, p2, direction1, direction2); 
                } 
                else
                { 
                    AddSegment(path, radius, p1, p2, (previousConnectorSize >= diameter), false, direction1);
                }

                i++; 
            }
 
            AddSegment(path, radius, p2, p3, 
                (currentConnectorSize >= diameter && nextConnectorSize >= diameter),
                false, direction2); 

            return path;
        }
 
        private static int GetDistance(Point p1, Point p2)
        { 
            if (p1.X == p2.X) 
                return Math.Abs(p1.Y - p2.Y);
            else 
                return Math.Abs(p1.X - p2.X);
        }

        private static void AddSegment(GraphicsPath path, int radius, Point p1, Point p2, bool roundP1, bool roundP2, ArrowDirection direction) 
        {
            if (roundP1) 
            { 
                switch (direction)
                { 
                    case ArrowDirection.Down:
                        p1.Y += radius;
                        break;
                    case ArrowDirection.Up: 
                        p1.Y -= radius;
                        break; 
                    case ArrowDirection.Left: 
                        p1.X -= radius;
                        break; 
                    default:
                        p1.X += radius;
                        break;
                } 
            }
            if (roundP2) 
            { 
                switch (direction)
                { 
                    case ArrowDirection.Down:
                        p2.Y -= radius;
                        break;
                    case ArrowDirection.Up: 
                        p2.Y += radius;
                        break; 
                    case ArrowDirection.Left: 
                        p2.X += radius;
                        break; 
                    default:
                        p2.X -= radius;
                        break;
                } 
            }
            path.AddLine(p1, p2); 
        } 

        private static void AddRoundedCorner(GraphicsPath path, int diameter, Point midPoint, ArrowDirection direction1, ArrowDirection direction2) 
        {
            switch (direction1)
            {
                case ArrowDirection.Left: 
                    if (direction2 == ArrowDirection.Down)
                        path.AddArc(midPoint.X, midPoint.Y, diameter, diameter, 270f, -90f); 
                    else 
                        path.AddArc(midPoint.X, midPoint.Y - diameter, diameter, diameter, 90f, 90f);
                    break; 
                case ArrowDirection.Right:
                    if (direction2 == ArrowDirection.Down)
                        path.AddArc(midPoint.X - diameter, midPoint.Y, diameter, diameter, 270f, 90f);
                    else 
                        path.AddArc(midPoint.X - diameter, midPoint.Y - diameter, diameter, diameter, 90f, -90f);
                    break; 
                case ArrowDirection.Up: 
                    if (direction2 == ArrowDirection.Left)
                        path.AddArc(midPoint.X - diameter, midPoint.Y, diameter, diameter, 0f, -90f); 
                    else
                        path.AddArc(midPoint.X, midPoint.Y, diameter, diameter, 180f, 90f);
                    break;
                default: 
                    if (direction2 == ArrowDirection.Left)
                        path.AddArc(midPoint.X - diameter, midPoint.Y - diameter, diameter, diameter, 0f, 90f); 
                    else 
                        path.AddArc(midPoint.X, midPoint.Y - diameter, diameter, diameter, 180f, -90f);
                    break; 
            }
        }

        private static ArrowDirection GetDirection(Point start, Point end) 
        {
            // we only support vertical or horizotal lines. No diagonals 
            Debug.Assert(start.X == end.X || start.Y == end.Y); 

            if (start.X == end.X) 
                // vertical
                if (start.Y < end.Y)
                    // top to bottom
                    return ArrowDirection.Down; 
                else
                    // Bottom to Top 
                    return ArrowDirection.Up; 
            else
                // horizontal 
                if (start.X < end.X)
                    // left to right
                    return ArrowDirection.Right;
                else 
                    // right to left
                    return ArrowDirection.Left; 
        } 

 

        //

        internal static GraphicsPath GetLineCap(LineAnchor lineCap, int capsize, out float capinset) 
        {
            //WE DO NOT SUPPORT ARROWCAPS FOR ANGULAR CONNECTORS FOR NOW 
            capinset = 0.0f; 
            capinset = (float)capsize / 2;
            Size capSize = new Size(capsize, capsize); 

            GraphicsPath lineCapPath = new GraphicsPath();
            switch (lineCap)
            { 
                case LineAnchor.Arrow:
                case LineAnchor.ArrowAnchor: 
                    int arcRadius = capSize.Height / 3; 
                    lineCapPath.AddLine(capSize.Width / 2, -capSize.Height, 0, 0);
                    lineCapPath.AddLine(0, 0, -capSize.Width / 2, -capSize.Height); 
                    lineCapPath.AddLine(-capSize.Width / 2, -capSize.Height, 0, -capSize.Height + arcRadius);
                    lineCapPath.AddLine(0, -capSize.Height + arcRadius, capSize.Width / 2, -capSize.Height);
                    capinset = capSize.Height - arcRadius;
                    break; 

                case LineAnchor.Diamond: 
                case LineAnchor.DiamondAnchor: 
                    lineCapPath.AddLine(0, -capSize.Height, capSize.Width / 2, -capSize.Height / 2);
                    lineCapPath.AddLine(capSize.Width / 2, -capSize.Height / 2, 0, 0); 
                    lineCapPath.AddLine(0, 0, -capSize.Width / 2, -capSize.Height / 2);
                    lineCapPath.AddLine(-capSize.Width / 2, -capSize.Height / 2, 0, -capSize.Height);
                    break;
 
                case LineAnchor.Round:
                case LineAnchor.RoundAnchor: 
                    lineCapPath.AddEllipse(new Rectangle(-capSize.Width / 2, -capSize.Height, capSize.Width, capSize.Height)); 
                    break;
 
                case LineAnchor.Rectangle:
                case LineAnchor.RectangleAnchor:
                    lineCapPath.AddRectangle(new Rectangle(-capSize.Width / 2, -capSize.Height, capSize.Width, capSize.Height));
                    break; 

                case LineAnchor.RoundedRectangle: 
                case LineAnchor.RoundedRectangleAnchor: 
                    arcRadius = capSize.Height / 4;
                    lineCapPath.AddPath(ActivityDesignerPaint.GetRoundedRectanglePath(new Rectangle(-capSize.Width / 2, -capSize.Height, capSize.Width, capSize.Height), arcRadius), true); 
                    break;
            }

            lineCapPath.CloseFigure(); 
            return lineCapPath;
        } 
 
        internal static GraphicsPath GetDesignerPath(ActivityDesigner designer, Rectangle bounds, ActivityDesignerTheme designerTheme)
        { 
            GraphicsPath designerPath = new GraphicsPath();

            if (designer == GetSafeRootDesigner(designer.Activity.Site) && ((IWorkflowRootDesigner)designer).InvokingDesigner == null)
            { 
                designerPath.AddRectangle(bounds);
            } 
            else 
            {
                // Work around: This should come from AmbientTheme.ArcDiameter 
                // but it is internal
                int arcDiameter = 8;
                if (designerTheme != null && designerTheme.DesignerGeometry == DesignerGeometry.RoundedRectangle)
                    designerPath.AddPath(ActivityDesignerPaint.GetRoundedRectanglePath(bounds, arcDiameter), true); 
                else
                    designerPath.AddRectangle(bounds); 
            } 

            return designerPath; 
        }

        internal static ActivityDesigner GetSafeRootDesigner(IServiceProvider serviceProvider)
        { 
            return (serviceProvider != null) ? ActivityDesigner.GetRootDesigner(serviceProvider) : null;
        } 
    } 
    #endregion
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK