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; using System.Workflow.ComponentModel.Serialization; using System.ComponentModel.Design.Serialization; using System.Xml; [DesignerSerializer(typeof(StateDesignerConnectorLayoutSerializer), typeof(WorkflowMarkupSerializer))] internal class StateDesignerConnector : Connector { internal const int ConnectorPadding = 10; private string _setStateName; private string _eventHandlerName; private string _sourceStateName; private string _targetStateName; internal StateDesignerConnector(ConnectionPoint source, ConnectionPoint target) : base(source, target) { } private StateDesigner RootStateDesigner { get { StateDesigner stateDesigner = (StateDesigner)this.ParentDesigner; while (true && stateDesigner != null) { StateDesigner parentStateDesigner = stateDesigner.ParentDesigner as StateDesigner; if (parentStateDesigner == null) break; stateDesigner = parentStateDesigner; } return stateDesigner; } } internal string SetStateName { get { return _setStateName; } set { _setStateName = value; } } internal string EventHandlerName { get { return _eventHandlerName; } set { _eventHandlerName = value; } } internal string SourceStateName { get { return _sourceStateName; } set { _sourceStateName = value; } } internal string TargetStateName { get { return _targetStateName; } set { _targetStateName = value; } } internal void ClearConnectorSegments() { this.SetConnectorSegments(new Collection()); } protected override void OnLayout(ActivityDesignerLayoutEventArgs e) { if (!this.RootStateDesigner.HasActiveDesigner) base.OnLayout(e); } protected override ICollection ExcludedRoutingRectangles { get { StateDesigner sourceStateDesigner = (StateDesigner)this.Source.AssociatedDesigner; List excluded = new List(base.ExcludedRoutingRectangles); if (sourceStateDesigner.IsRootDesigner) { excluded.AddRange(sourceStateDesigner.EventHandlersBounds); } return excluded.AsReadOnly(); } } public override bool HitTest(Point point) { if (this.RootStateDesigner != null && this.RootStateDesigner.ActiveDesigner != null) return false; return base.HitTest(point); } protected override void OnPaintEdited(ActivityDesignerPaintEventArgs e, Point[] segments, Point[] segmentEditPoints) { if (this.RootStateDesigner != null && this.RootStateDesigner.ActiveDesigner != null) return; // we don't draw connectors in the EventDriven view StateMachineTheme theme = e.DesignerTheme as StateMachineTheme; if (theme != null) { using (Pen lineEditPen = new Pen(WorkflowTheme.CurrentTheme.AmbientTheme.SelectionForeColor, 1)) { lineEditPen.DashStyle = DashStyle.Dash; e.Graphics.DrawLines(lineEditPen, segments); if (Source != null) Source.OnPaint(e, false); for (int i = 1; i < segments.Length - 1; i++) PaintEditPoints(e, segments[i], false); for (int i = 0; i < segmentEditPoints.Length; i++) PaintEditPoints(e, segmentEditPoints[i], true); if (Target != null) Target.OnPaint(e, false); } } } protected override void OnPaintSelected(ActivityDesignerPaintEventArgs e, bool primarySelection, Point[] segmentEditPoints) { if (this.RootStateDesigner != null && this.RootStateDesigner.ActiveDesigner != null) return; // we don't draw connectors in the EventDriven view StateMachineTheme theme = e.DesignerTheme as StateMachineTheme; if (theme != null) { Size arrowCapSize = new Size(theme.ConnectorSize.Width / 5, theme.ConnectorSize.Height / 5); Size maxCapSize = theme.ConnectorSize; using (Pen lineSelectionPen = new Pen(WorkflowTheme.CurrentTheme.AmbientTheme.SelectionForeColor, 1)) { StateMachineDesignerPaint.DrawConnector(e.Graphics, lineSelectionPen, new List(ConnectorSegments).ToArray(), arrowCapSize, maxCapSize, theme.ConnectorStartCap, theme.ConnectorEndCap); } if (this.Source != null) this.Source.OnPaint(e, false); ReadOnlyCollection endSegmentEditPoints = ConnectorSegments; for (int i = 1; i < endSegmentEditPoints.Count - 1; i++) PaintEditPoints(e, endSegmentEditPoints[i], false); for (int i = 0; i < segmentEditPoints.Length; i++) PaintEditPoints(e, segmentEditPoints[i], true); if (this.Target != null) this.Target.OnPaint(e, false); } } protected override void OnPaint(ActivityDesignerPaintEventArgs e) { if (this.RootStateDesigner != null && this.RootStateDesigner.ActiveDesigner != null) return; // we don't draw connectors in the EventDriven view StateMachineTheme theme = e.DesignerTheme as StateMachineTheme; if (theme != null) { Size arrowCapSize = new Size(theme.ConnectorSize.Width / 5, theme.ConnectorSize.Height / 5); Size maxCapSize = theme.ConnectorSize; StateMachineDesignerPaint.DrawConnector(e.Graphics, theme.ConnectorPen, new List(ConnectorSegments).ToArray(), arrowCapSize, maxCapSize, theme.ConnectorStartCap, theme.ConnectorEndCap); } } private void PaintEditPoints(ActivityDesignerPaintEventArgs e, Point point, bool drawMidSegmentEditPoint) { Size size = (Source != null) ? Source.Bounds.Size : Size.Empty; if (!size.IsEmpty) { Rectangle bounds = new Rectangle(point.X - size.Width / 2, point.Y - size.Height / 2, size.Width, size.Height); if (drawMidSegmentEditPoint) { using (GraphicsPath path = new GraphicsPath()) { path.AddLine(new Point(bounds.Left + bounds.Width / 2, bounds.Top), new Point(bounds.Right, bounds.Top + bounds.Height / 2)); path.AddLine(new Point(bounds.Right, bounds.Top + bounds.Height / 2), new Point(bounds.Left + bounds.Width / 2, bounds.Bottom)); path.AddLine(new Point(bounds.Left + bounds.Width / 2, bounds.Bottom), new Point(bounds.Left, bounds.Top + bounds.Height / 2)); path.AddLine(new Point(bounds.Left, bounds.Top + bounds.Height / 2), new Point(bounds.Left + bounds.Width / 2, bounds.Top)); e.Graphics.FillPath(Brushes.White, path); e.Graphics.DrawPath(e.AmbientTheme.SelectionForegroundPen, path); } } else { bounds.Inflate(-1, -1); e.Graphics.FillEllipse(e.AmbientTheme.SelectionForegroundBrush, bounds); } } } } #region StateDesignerConnectorLayoutSerializer internal class StateDesignerConnectorLayoutSerializer : ConnectorLayoutSerializer { protected override PropertyInfo[] GetProperties(WorkflowMarkupSerializationManager serializationManager, object obj) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (obj == null) throw new ArgumentNullException("obj"); List properties = new List(base.GetProperties(serializationManager, obj)); properties.Add(typeof(StateDesignerConnector).GetProperty("SetStateName", BindingFlags.Instance | BindingFlags.NonPublic)); properties.Add(typeof(StateDesignerConnector).GetProperty("SourceStateName", BindingFlags.Instance | BindingFlags.NonPublic)); properties.Add(typeof(StateDesignerConnector).GetProperty("TargetStateName", BindingFlags.Instance | BindingFlags.NonPublic)); properties.Add(typeof(StateDesignerConnector).GetProperty("EventHandlerName", BindingFlags.Instance | BindingFlags.NonPublic)); return properties.ToArray(); } protected override object CreateInstance(WorkflowMarkupSerializationManager serializationManager, Type type) { if (serializationManager == null) throw new ArgumentNullException("serializationManager"); if (type == null) throw new ArgumentNullException("type"); StateDesignerConnector connector = null; IReferenceService referenceService = serializationManager.GetService(typeof(IReferenceService)) as IReferenceService; FreeformActivityDesigner freeformDesigner = serializationManager.Context[typeof(FreeformActivityDesigner)] as FreeformActivityDesigner; if (freeformDesigner != null && referenceService != null) { StateDesigner.DesignerLayoutConnectionPoint sourceConnection = null; ConnectionPoint targetConnection = null; StateDesigner.TransitionInfo transitionInfo = null; StateDesigner rootStateDesigner = null; try { Dictionary constructionArguments = GetConnectorConstructionArguments(serializationManager, type); if (constructionArguments.ContainsKey("EventHandlerName") && constructionArguments.ContainsKey("SetStateName") && constructionArguments.ContainsKey("TargetStateName")) { CompositeActivity eventHandler = (CompositeActivity)referenceService.GetReference(constructionArguments["EventHandlerName"] as string); SetStateActivity setState = (SetStateActivity)referenceService.GetReference(constructionArguments["SetStateName"] as string); StateActivity targetState = (StateActivity)referenceService.GetReference(constructionArguments["TargetStateName"] as string); transitionInfo = new StateDesigner.TransitionInfo(setState, eventHandler); transitionInfo.TargetState = targetState; } if (constructionArguments.ContainsKey("SourceActivity") && constructionArguments.ContainsKey("SourceConnectionIndex") && constructionArguments.ContainsKey("SourceConnectionEdge") && constructionArguments.ContainsKey("EventHandlerName")) { StateDesigner sourceDesigner = (StateDesigner)StateDesigner.GetDesigner(referenceService.GetReference(constructionArguments["SourceActivity"] as string) as Activity); CompositeActivity eventHandler = (CompositeActivity)referenceService.GetReference(constructionArguments["EventHandlerName"] as string); rootStateDesigner = sourceDesigner.RootStateDesigner; DesignerEdges sourceEdge = (DesignerEdges)Enum.Parse(typeof(DesignerEdges), constructionArguments["SourceConnectionEdge"] as string); int sourceIndex = Convert.ToInt32(constructionArguments["SourceConnectionIndex"] as string, System.Globalization.CultureInfo.InvariantCulture); if (sourceDesigner != null && eventHandler != null && sourceEdge != DesignerEdges.None && sourceIndex >= 0) sourceConnection = new StateDesigner.DesignerLayoutConnectionPoint(sourceDesigner, sourceIndex, eventHandler, sourceEdge); } if (constructionArguments.ContainsKey("TargetActivity") && constructionArguments.ContainsKey("TargetConnectionIndex") && constructionArguments.ContainsKey("TargetConnectionEdge")) { ActivityDesigner targetDesigner = StateDesigner.GetDesigner(referenceService.GetReference(constructionArguments["TargetActivity"] as string) as Activity); DesignerEdges targetEdge = (DesignerEdges)Enum.Parse(typeof(DesignerEdges), constructionArguments["TargetConnectionEdge"] as string); int targetIndex = Convert.ToInt32(constructionArguments["TargetConnectionIndex"] as string, System.Globalization.CultureInfo.InvariantCulture); if (targetDesigner != null && targetEdge != DesignerEdges.None && targetIndex >= 0) targetConnection = new ConnectionPoint(targetDesigner, targetEdge, targetIndex); } } catch { } if (transitionInfo != null && sourceConnection != null && targetConnection != null) { connector = rootStateDesigner.FindConnector(transitionInfo); if (connector == null) { rootStateDesigner.AddingSetState = false; try { connector = freeformDesigner.AddConnector(sourceConnection, targetConnection) as StateDesignerConnector; } finally { rootStateDesigner.AddingSetState = true; } } else { connector.Source = sourceConnection; connector.Target = targetConnection; connector.ClearConnectorSegments(); } } } return connector; } } #endregion }