#pragma warning disable 1634, 1691 namespace System.Workflow.ComponentModel.Design { using System; using System.IO; using System.Drawing; using System.CodeDom; using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System.Windows.Forms; using System.ComponentModel; using System.Globalization; using System.Drawing.Design; using System.Drawing.Imaging; using System.Drawing.Drawing2D; using System.Windows.Forms.Design; using System.ComponentModel.Design; using System.Collections.Specialized; using System.ComponentModel.Design.Serialization; using System.Workflow.ComponentModel.Compiler; using System.Workflow.ComponentModel.Serialization; using System.Collections.ObjectModel; using System.Reflection; using System.Workflow.ComponentModel.Design; using System.Runtime.Serialization.Formatters.Binary; // #region ParallelActivityDesigner Class /// /// Base class used for all the designers which have parallel vertical layout. /// [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")] public class ParallelActivityDesigner : StructuredCompositeActivityDesigner { #region Fields private ActivityDesignerVerbCollection designerVerbs; #endregion #region Constructor /// /// Default constructor for the ParallelActivityDesigner /// public ParallelActivityDesigner() { } #endregion #region Properties #region Public Properties public override object FirstSelectableObject { get { if (ActiveDesigner != this) return base.FirstSelectableObject; if (!Expanded || !IsVisible) return null; object firstComponent = null; if (ContainedDesigners.Count > 0) firstComponent = ContainedDesigners[0].Activity; return firstComponent; } } public override object LastSelectableObject { get { if (ActiveDesigner != this) return base.FirstSelectableObject; if (!Expanded || !IsVisible) return null; object firstComponent = (ContainedDesigners.Count > 0) ? ContainedDesigners[0].Activity : null; CompositeActivityDesigner firstDesigner = (firstComponent is Activity) ? ActivityDesigner.GetDesigner(firstComponent as Activity) as CompositeActivityDesigner : null; object lastObject = null; if (firstDesigner != null) lastObject = firstDesigner.LastSelectableObject; // this might have happen when the first activityDesigner is collapsed if (lastObject == null) lastObject = firstComponent; return lastObject; } } #endregion #region Protected Properties protected override ActivityDesignerVerbCollection Verbs { get { ActivityDesignerVerbCollection verbs = new ActivityDesignerVerbCollection(); verbs.AddRange(base.Verbs); if (this.designerVerbs == null) { this.designerVerbs = new ActivityDesignerVerbCollection(); this.designerVerbs.Add(new ActivityDesignerVerb(this, DesignerVerbGroup.General, DR.GetString(DR.AddBranch), new EventHandler(OnAddBranch), new EventHandler(OnStatusAddBranch))); } verbs.AddRange(this.designerVerbs); return verbs; } } #endregion #region Private Properties #endregion #endregion #region Methods #region Public Methods public override object GetNextSelectableObject(object obj, DesignerNavigationDirection direction) { if (ActiveDesigner != this) return base.GetNextSelectableObject(obj, direction); if (direction != DesignerNavigationDirection.Left && direction != DesignerNavigationDirection.Right) return null; object nextObject = null; ReadOnlyCollection containedDesigners = ContainedDesigners; ActivityDesigner activityDesigner = ActivityDesigner.GetDesigner(obj as Activity); int index = (activityDesigner != null) ? containedDesigners.IndexOf(activityDesigner) : -1; if (direction == DesignerNavigationDirection.Left && index >= 0 && index < containedDesigners.Count) nextObject = ((ActivityDesigner)containedDesigners[(index > 0) ? index - 1 : containedDesigners.Count - 1]).Activity; else if (direction == DesignerNavigationDirection.Right && index <= containedDesigners.Count - 1) nextObject = ((ActivityDesigner)containedDesigners[(index < containedDesigners.Count - 1) ? index + 1 : 0]).Activity; return nextObject; } public override bool CanRemoveActivities(ReadOnlyCollection activitiesToRemove) { if (activitiesToRemove == null) throw new ArgumentNullException("activitiesToRemove"); if (ActiveDesigner != this) return base.CanRemoveActivities(activitiesToRemove); if ((ContainedDesigners.Count - activitiesToRemove.Count) < 2) return false; else return base.CanRemoveActivities(activitiesToRemove); } public override bool CanMoveActivities(HitTestInfo moveLocation, ReadOnlyCollection activitiesToMove) { if (moveLocation == null) throw new ArgumentNullException("moveLocation"); if (activitiesToMove == null) throw new ArgumentNullException("activitiesToMove"); if (ActiveDesigner != this) return base.CanMoveActivities(moveLocation, activitiesToMove); if ((ContainedDesigners.Count - activitiesToMove.Count) < 2) { if (moveLocation != null && moveLocation.AssociatedDesigner != this) return false; } return base.CanMoveActivities(moveLocation, activitiesToMove); } #endregion #region Protected Methods /// /// Create new activity to be added as branch within the parallel designer /// /// CompositeActivity to be added as branch protected virtual CompositeActivity OnCreateNewBranch() { return null; } protected override void OnPaint(ActivityDesignerPaintEventArgs e) { base.OnPaint(e); if (Expanded && ActiveDesigner == this) { //Draw the connectors if (ContainedDesigners.Count > 0) DrawParallelConnectors(e); //Drop targets to add the branches if (CurrentDropTarget >= 0) DrawParallelDropTargets(e, CurrentDropTarget); } } protected override void OnLayoutPosition(ActivityDesignerLayoutEventArgs e) { if (e == null) throw new ArgumentNullException("e"); base.OnLayoutPosition(e); if (Expanded && ActiveDesigner == this) { CompositeDesignerTheme compositeDesignerTheme = e.DesignerTheme as CompositeDesignerTheme; if (compositeDesignerTheme != null) { ReadOnlyCollection connectionPoints = GetInnerConnections(DesignerEdges.Top | DesignerEdges.Bottom); Point location = (connectionPoints.Count > 0) ? new Point(Location.X, connectionPoints[0].Y) : Location; int width = 0; int height = compositeDesignerTheme.ConnectorSize.Height * 3 / 2; foreach (ActivityDesigner activityDesigner in ContainedDesigners) { width += e.AmbientTheme.SelectionSize.Width; width += compositeDesignerTheme.ConnectorSize.Width; Size designerSize = activityDesigner.Size; activityDesigner.Location = new Point(location.X + width, location.Y + height); width += designerSize.Width; width += e.AmbientTheme.SelectionSize.Width; } } } } protected override Size OnLayoutSize(ActivityDesignerLayoutEventArgs e) { Size size = base.OnLayoutSize(e); CompositeDesignerTheme compositeDesignerTheme = e.DesignerTheme as CompositeDesignerTheme; if (Expanded && ActiveDesigner == this && compositeDesignerTheme != null) { //Calculate the container size Size containerSize = Size.Empty; //Calculate the size based on child size foreach (ActivityDesigner activityDesigner in ContainedDesigners) { Size childSize = activityDesigner.Size; containerSize.Width += e.AmbientTheme.SelectionSize.Width; containerSize.Width += compositeDesignerTheme.ConnectorSize.Width; containerSize.Width += childSize.Width; containerSize.Width += e.AmbientTheme.SelectionSize.Width; containerSize.Height = Math.Max(containerSize.Height, childSize.Height); } containerSize.Width += (ContainedDesigners.Count > 0) ? compositeDesignerTheme.ConnectorSize.Width : 0; //Once this happens then make sure that all the branches are of same size foreach (ActivityDesigner activityDesigner in ContainedDesigners) activityDesigner.Size = new Size(activityDesigner.Size.Width, containerSize.Height); //Add the margin for drawing the parallel connectors containerSize.Height += 3 * compositeDesignerTheme.ConnectorSize.Height; //Now consider the base classe's size size.Width = Math.Max(size.Width, containerSize.Width); size.Height += containerSize.Height; } return size; } protected override Rectangle[] GetDropTargets(Point dropPoint) { if (!Expanded || ActiveDesigner != this) return new Rectangle[] { }; CompositeDesignerTheme designerTheme = DesignerTheme as CompositeDesignerTheme; Rectangle bounds = Bounds; ReadOnlyCollection containedDesigners = ContainedDesigners; Rectangle[] dropTargets = new Rectangle[containedDesigners.Count + 1]; if (containedDesigners.Count > 0) { //Add the first connector ActivityDesigner firstDesigner = containedDesigners[0]; dropTargets[0].Location = new Point(bounds.X, firstDesigner.Location.Y); dropTargets[0].Size = new Size(((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0), firstDesigner.Size.Height); for (int i = 0; i < containedDesigners.Count - 1; i++) { ActivityDesigner designer1 = containedDesigners[i]; Rectangle designerBounds1 = designer1.Bounds; ActivityDesigner designer2 = containedDesigners[i + 1]; Rectangle designerBounds2 = designer2.Bounds; dropTargets[i + 1].Location = new Point(designerBounds1.Right + (designerBounds2.Left - designerBounds1.Right) / 2 - ((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0) / 2, designerBounds1.Top); dropTargets[i + 1].Size = new Size(((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0), designerBounds1.Height); } //Add last connector ActivityDesigner lastDesigner = containedDesigners[containedDesigners.Count - 1]; dropTargets[containedDesigners.Count].Location = new Point(bounds.Right - ((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0), lastDesigner.Location.Y); dropTargets[containedDesigners.Count].Size = new Size(((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0), lastDesigner.Size.Height); } else { dropTargets[0].Location = new Point(Location.X + (Size.Width - ((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0)) / 2, TextRectangle.Bottom); dropTargets[0].Size = new Size(((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0), Location.Y + Size.Height - dropTargets[0].Location.Y); } return dropTargets; } #endregion #region Private Methods private void OnStatusAddBranch(object sender, EventArgs e) { ActivityDesignerVerb verb = sender as ActivityDesignerVerb; if (verb != null) { verb.Enabled = IsEditable; } } private void DrawParallelConnectors(ActivityDesignerPaintEventArgs e) { CompositeDesignerTheme compositeDesignerTheme = e.DesignerTheme as CompositeDesignerTheme; if (compositeDesignerTheme == null) return; //Get all the information required to calculate the connectors Rectangle bounds = Bounds; int parallelConnectorTop = bounds.Top; parallelConnectorTop += TitleHeight; ReadOnlyCollection containedDesigners = ContainedDesigners; ActivityDesigner firstDesigner = containedDesigners[0]; ReadOnlyCollection firstDesignerConnections = firstDesigner.GetConnections(DesignerEdges.Top | DesignerEdges.Bottom); ActivityDesigner lastDesigner = containedDesigners[containedDesigners.Count - 1]; ReadOnlyCollection lastDesignerConnections = lastDesigner.GetConnections(DesignerEdges.Top | DesignerEdges.Bottom); Point[] parallelLinks = new Point[2]; //Draw small vertical line at the top parallelLinks[0].X = bounds.Left + bounds.Width / 2; parallelLinks[0].Y = parallelConnectorTop; parallelLinks[1].X = bounds.Left + bounds.Width / 2; parallelLinks[1].Y = parallelConnectorTop + compositeDesignerTheme.ConnectorSize.Height * 3 / 4; DrawConnectors(e.Graphics, compositeDesignerTheme.ForegroundPen, parallelLinks, LineAnchor.None, LineAnchor.None); //Draw Horizontal line at the top parallelLinks[0].X = firstDesignerConnections[0].X; parallelLinks[0].Y = parallelConnectorTop + compositeDesignerTheme.ConnectorSize.Height * 3 / 4; parallelLinks[1].X = lastDesignerConnections[0].X; parallelLinks[1].Y = parallelConnectorTop + compositeDesignerTheme.ConnectorSize.Height * 3 / 4; DrawConnectors(e.Graphics, compositeDesignerTheme.ForegroundPen, parallelLinks, LineAnchor.None, LineAnchor.None); //Draw Horizontal line at the bottom parallelLinks[0].X = firstDesignerConnections[firstDesignerConnections.Count - 1].X; parallelLinks[0].Y = bounds.Bottom - compositeDesignerTheme.ConnectorSize.Height * 3 / 4; parallelLinks[1].X = lastDesignerConnections[lastDesignerConnections.Count - 1].X; parallelLinks[1].Y = bounds.Bottom - compositeDesignerTheme.ConnectorSize.Height * 3 / 4; DrawConnectors(e.Graphics, compositeDesignerTheme.ForegroundPen, parallelLinks, LineAnchor.None, LineAnchor.None); //Draw small vertical line at the bottom parallelLinks[0].X = bounds.Left + bounds.Width / 2; parallelLinks[0].Y = bounds.Bottom - compositeDesignerTheme.ConnectorSize.Height * 3 / 4; parallelLinks[1].X = bounds.Left + bounds.Width / 2; parallelLinks[1].Y = bounds.Bottom; DrawConnectors(e.Graphics, compositeDesignerTheme.ForegroundPen, parallelLinks, LineAnchor.None, LineAnchor.None); foreach (ActivityDesigner activityDesigner in containedDesigners) { ReadOnlyCollection designerConnections = activityDesigner.GetConnections(DesignerEdges.Top | DesignerEdges.Bottom); int connectionCount = designerConnections.Count; Point[] connectingLine = new Point[2]; //Draw connectors for every activityDesigner connectingLine[0].X = designerConnections[0].X; connectingLine[0].Y = parallelConnectorTop + compositeDesignerTheme.ConnectorSize.Height * 3 / 4; connectingLine[1].X = designerConnections[0].X; connectingLine[1].Y = designerConnections[0].Y; DrawConnectors(e.Graphics, compositeDesignerTheme.ForegroundPen, connectingLine, compositeDesignerTheme.ConnectorStartCap, compositeDesignerTheme.ConnectorEndCap); //Draw connectors for every activityDesigner connectingLine[0].X = designerConnections[connectionCount - 1].X; connectingLine[0].Y = designerConnections[connectionCount - 1].Y; connectingLine[1].X = designerConnections[connectionCount - 1].X; connectingLine[1].Y = bounds.Bottom - compositeDesignerTheme.ConnectorSize.Height * 3 / 4; DrawConnectors(e.Graphics, compositeDesignerTheme.ForegroundPen, connectingLine, compositeDesignerTheme.ConnectorStartCap, compositeDesignerTheme.ConnectorEndCap); } } private void DrawParallelDropTargets(ActivityDesignerPaintEventArgs e, int index) { Rectangle[] dropTargets = GetDropTargets(Point.Empty); if (index < 0 || index >= dropTargets.Length) return; CompositeDesignerTheme compositeDesignerTheme = e.DesignerTheme as CompositeDesignerTheme; if (compositeDesignerTheme == null) return; ReadOnlyCollection containedDesigners = ContainedDesigners; Rectangle dropTargetRectangle = dropTargets[index]; Rectangle bounds = Bounds; int parallelConnectorTop = bounds.Top; parallelConnectorTop += TitleHeight; parallelConnectorTop += (containedDesigners.Count > 0) ? compositeDesignerTheme.ConnectorSize.Height * 3 / 4 : 0; int heightDelta = dropTargetRectangle.Y - parallelConnectorTop; heightDelta += bounds.Bottom - dropTargetRectangle.Bottom; heightDelta -= (containedDesigners.Count > 0) ? compositeDesignerTheme.ConnectorSize.Height * 3 / 4 : 0; dropTargetRectangle.Y = parallelConnectorTop; dropTargetRectangle.Height += heightDelta; DrawConnectors(e.Graphics, e.AmbientTheme.DropIndicatorPen, new Point[] { new Point(dropTargetRectangle.Left + dropTargetRectangle.Width / 2, dropTargetRectangle.Top + 2), new Point(dropTargetRectangle.Left + dropTargetRectangle.Width / 2, dropTargetRectangle.Bottom - 2) }, compositeDesignerTheme.ConnectorStartCap, compositeDesignerTheme.ConnectorEndCap); if (containedDesigners.Count > 0) { if (index == 0) { ActivityDesigner firstDesigner = containedDesigners[0]; ReadOnlyCollection firstDesignerConnections = firstDesigner.GetConnections(DesignerEdges.Top | DesignerEdges.Bottom); Point[] connectorPoints = new Point[2]; connectorPoints[0].X = dropTargetRectangle.X + dropTargetRectangle.Width / 2; connectorPoints[0].Y = dropTargetRectangle.Y; connectorPoints[1].X = firstDesignerConnections[0].X; connectorPoints[1].Y = dropTargetRectangle.Y; DrawConnectors(e.Graphics, e.AmbientTheme.DropIndicatorPen, connectorPoints, LineAnchor.None, LineAnchor.None); connectorPoints[0].Y = dropTargetRectangle.Bottom; connectorPoints[1].Y = dropTargetRectangle.Bottom; DrawConnectors(e.Graphics, e.AmbientTheme.DropIndicatorPen, connectorPoints, LineAnchor.None, LineAnchor.None); } else if (index == containedDesigners.Count) { ActivityDesigner lastDesigner = containedDesigners[containedDesigners.Count - 1]; ReadOnlyCollection lastDesignerConnections = lastDesigner.GetConnections(DesignerEdges.Top | DesignerEdges.Bottom); Point[] connectorPoints = new Point[2]; connectorPoints[0].X = lastDesignerConnections[0].X; connectorPoints[0].Y = dropTargetRectangle.Y; connectorPoints[1].X = dropTargetRectangle.X + dropTargetRectangle.Width / 2; connectorPoints[1].Y = dropTargetRectangle.Y; DrawConnectors(e.Graphics, e.AmbientTheme.DropIndicatorPen, connectorPoints, LineAnchor.None, LineAnchor.None); connectorPoints[0].Y = dropTargetRectangle.Bottom; connectorPoints[1].Y = dropTargetRectangle.Bottom; DrawConnectors(e.Graphics, e.AmbientTheme.DropIndicatorPen, connectorPoints, LineAnchor.None, LineAnchor.None); } } } private void OnAddBranch(object sender, EventArgs e) { CompositeActivity branchActivity = OnCreateNewBranch(); CompositeActivity compositeActivity = Activity as CompositeActivity; if (compositeActivity != null && branchActivity != null) { // Record the current number of child activities int designerCount = ContainedDesigners.Count; CompositeActivityDesigner.InsertActivities(this, new ConnectorHitTestInfo(this, HitTestLocations.Designer, compositeActivity.Activities.Count), new List(new Activity[] { branchActivity }).AsReadOnly(), DR.GetString(DR.AddingBranch, branchActivity.GetType().Name)); // If the number of child activities has increased, the branch add was successful, so // make sure the highest indexed branch is visible if (ContainedDesigners.Count > designerCount && ContainedDesigners.Count > 0) ContainedDesigners[ContainedDesigners.Count - 1].EnsureVisible(); } } #endregion #endregion } #endregion }