|
#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 SequentialActivityDesigner Class
/// <summary>
/// Base class used for all the designers which have sequential vertical layout.
/// </summary>
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
public class SequentialActivityDesigner : StructuredCompositeActivityDesigner
{
#region Constants
private static readonly Size DefaultHelpTextSize = new Size(100, 85);
#endregion
#region Fields
private SequenceDesignerAccessibleObject accessibilityObject;
private string helpText = String.Empty;
private Size helpTextSize = Size.Empty;
#endregion
#region Constructor
/// <summary>
/// Default Constructor
/// </summary>
public SequentialActivityDesigner()
{
}
#endregion
#region Properties
#region Public Properties
public override bool Expanded
{
get
{
if (ParentDesigner is ParallelActivityDesigner)
return true;
else
return base.Expanded;
}
set
{
if (ParentDesigner is ParallelActivityDesigner)
value = true;
base.Expanded = value;
}
}
public override bool CanExpandCollapse
{
get
{
if (ParentDesigner is ParallelActivityDesigner)
return false;
else
return base.CanExpandCollapse;
}
}
public override object FirstSelectableObject
{
get
{
if (ActiveDesigner != this)
return base.FirstSelectableObject;
if (GetConnectors().Length == 0 || !Expanded || !IsVisible)
return null;
// This assumes there is always atleast one connector in SequenceContainer
return new ConnectorHitTestInfo(this, HitTestLocations.Designer, 0);
}
}
public override object LastSelectableObject
{
get
{
if (ActiveDesigner != this)
return base.LastSelectableObject;
Rectangle[] connectors = GetConnectors();
if (connectors.Length == 0 || !Expanded || !IsVisible)
return null;
// This assumes there is always atleast one connector in SequenceContainer
return new ConnectorHitTestInfo(this, HitTestLocations.Designer, connectors.Length - 1);
}
}
public override AccessibleObject AccessibilityObject
{
get
{
if (this.accessibilityObject == null)
this.accessibilityObject = new SequenceDesignerAccessibleObject(this);
return this.accessibilityObject;
}
}
#endregion
#region Protected Properties
/// <summary>
/// Gets the help text to be displayed when the are no contained designers to display
/// </summary>
protected virtual string HelpText
{
get
{
return this.helpText;
}
set
{
this.helpText = value;
PerformLayout();
}
}
/// <summary>
/// Gets the Rectangle bounding the help text.
/// </summary>
protected virtual Rectangle HelpTextRectangle
{
get
{
Rectangle[] connectors = GetConnectors();
if (this.HelpText.Length == 0 || ContainedDesigners.Count > 0 || !Expanded || connectors.Length == 0)
return Rectangle.Empty;
//Get the first connector and align the help text right in the center
Rectangle helpTextRectangle = Rectangle.Empty;
helpTextRectangle.X = connectors[0].Left + connectors[0].Width / 2 - this.helpTextSize.Width / 2;
helpTextRectangle.Y = connectors[0].Top + connectors[0].Height / 2 - this.helpTextSize.Height / 2;
helpTextRectangle.Size = this.helpTextSize;
return helpTextRectangle;
}
}
/// <summary>
/// Gets the array of rectangles bounding the connectors
/// </summary>
protected internal virtual Rectangle[] GetConnectors()
{
if (ActiveDesigner != this)
return new Rectangle[] { };
if (!Expanded)
return new Rectangle[] { };
CompositeDesignerTheme designerTheme = DesignerTheme as CompositeDesignerTheme;
if (designerTheme == null)
return new Rectangle[] { };
//Calculate no of connectors for the container; if there is no activityDesigner then we display single connector
ReadOnlyCollection<ActivityDesigner> containedDesigners = ContainedDesigners;
int connectorCount = (containedDesigners.Count > 0) ? (2 + (containedDesigners.Count - 1)) : 1;
Rectangle[] connectorBounds = new Rectangle[connectorCount];
ReadOnlyCollection<Point> containerConnections = GetInnerConnections(DesignerEdges.Top | DesignerEdges.Bottom);
Point containerStartConnection = new Point();
Point containerEndConnection = new Point();
if (containerConnections != null && containerConnections.Count > 0)
{
containerStartConnection = containerConnections[0];
containerEndConnection = containerConnections[containerConnections.Count - 1];
}
if (containedDesigners.Count > 0)
{
//Add the first connector. This will be from bitmap bottom to activityDesigner start
ActivityDesigner startDesigner = containedDesigners[0] as ActivityDesigner;
ReadOnlyCollection<Point> startDesignerConnections = startDesigner.GetConnections(DesignerEdges.Top | DesignerEdges.Bottom);
if (startDesignerConnections.Count == 0)
{
Rectangle startDesignerBounds = startDesigner.Bounds;
List<Point> connections = new List<Point>();
connections.Add(new Point(startDesignerBounds.Left + startDesignerBounds.Width / 2, startDesignerBounds.Top));
connections.Add(new Point(startDesignerBounds.Left + startDesignerBounds.Width / 2, startDesignerBounds.Bottom));
startDesignerConnections = connections.AsReadOnly();
}
connectorBounds[0].Location = new Point(containerStartConnection.X - ((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0) / 2, containerStartConnection.Y);
connectorBounds[0].Size = new Size(((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0), startDesignerConnections[0].Y - containerStartConnection.Y);
//Add rest of the points
for (int i = 0; i < containedDesigners.Count - 1; i++)
{
ActivityDesigner designerFrom = containedDesigners[i];
ActivityDesigner designerTo = containedDesigners[i + 1];
if (designerFrom != null && designerTo != null)
{
ReadOnlyCollection<Point> designerFromConnections = designerFrom.GetConnections(DesignerEdges.Top | DesignerEdges.Bottom);
int designerFromPointCount = designerFromConnections.Count;
ReadOnlyCollection<Point> designerToConnections = designerTo.GetConnections(DesignerEdges.Top | DesignerEdges.Bottom);
connectorBounds[i + 1].Location = new Point(designerFromConnections[designerFromPointCount - 1].X - ((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0) / 2, designerFromConnections[designerFromPointCount - 1].Y);
connectorBounds[i + 1].Size = new Size(((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0), designerToConnections[0].Y - designerFromConnections[designerFromPointCount - 1].Y);
}
}
//Add the last connector
ActivityDesigner endDesigner = containedDesigners[containedDesigners.Count - 1];
ReadOnlyCollection<Point> endDesignerConnections = endDesigner.GetConnections(DesignerEdges.Top | DesignerEdges.Bottom);
if (endDesignerConnections.Count == 0)
{
Rectangle endDesignerBounds = endDesigner.Bounds;
List<Point> connections = new List<Point>();
connections.Add(new Point(endDesignerBounds.Left + endDesignerBounds.Width / 2, endDesignerBounds.Top));
connections.Add(new Point(endDesignerBounds.Left + endDesignerBounds.Width / 2, endDesignerBounds.Bottom));
endDesignerConnections = connections.AsReadOnly();
}
connectorBounds[connectorCount - 1].Location = new Point(endDesignerConnections[endDesignerConnections.Count - 1].X - ((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0) / 2, endDesignerConnections[endDesignerConnections.Count - 1].Y);
connectorBounds[connectorCount - 1].Size = new Size(((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0), containerEndConnection.Y - endDesignerConnections[endDesignerConnections.Count - 1].Y);
}
else
{
//If there are no activity designers in the container then we show only one connector
connectorBounds[0].Location = new Point(containerStartConnection.X - ((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0) / 2, containerStartConnection.Y);
connectorBounds[0].Size = new Size(((designerTheme != null) ? designerTheme.ConnectorSize.Width : 0), containerEndConnection.Y - containerStartConnection.Y);
}
//extend the targets a little bit
for (int i = 0; i < connectorBounds.Length; i++)
connectorBounds[i].Inflate(3 * connectorBounds[i].Width, 0);
return connectorBounds;
}
protected internal override ActivityDesignerGlyphCollection Glyphs
{
get
{
ActivityDesignerGlyphCollection designerGlyphs = new ActivityDesignerGlyphCollection();
ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
if (selectionService != null)
{
ICollection selectedObjects = selectionService.GetSelectedComponents();
foreach (object obj in selectedObjects)
{
ConnectorHitTestInfo connectorHitTestInfo = obj as ConnectorHitTestInfo;
if (connectorHitTestInfo != null && connectorHitTestInfo.AssociatedDesigner == this)
designerGlyphs.Add(new SequentialConnectorSelectionGlyph(connectorHitTestInfo.MapToIndex(), (selectionService.PrimarySelection == obj)));
}
}
designerGlyphs.AddRange(CreateConnectorDragDropGlyphs());
designerGlyphs.AddRange(base.Glyphs);
return designerGlyphs;
}
}
protected Size HelpTextSize
{
get
{
return this.helpTextSize;
}
}
#endregion
#region Private Properties
#endregion
#endregion
#region Methods
#region Public Methods
public override HitTestInfo HitTest(Point point)
{
if (ActiveDesigner != this)
return base.HitTest(point);
HitTestInfo hitInfo = HitTestInfo.Nowhere;
if (!Expanded)
{
hitInfo = base.HitTest(point);
}
else if (ContainedDesigners.Count == 0 && HelpTextRectangle.Contains(point))
{
hitInfo = new ConnectorHitTestInfo(this, HitTestLocations.Designer, 0);
}
else
{
//Check if the hit is on any of the connectors
Rectangle[] connectors = GetConnectors();
for (int i = 0; i < connectors.Length; i++)
{
if (connectors[i].Contains(point))
{
hitInfo = new ConnectorHitTestInfo(this, HitTestLocations.Designer, i);
break;
}
}
if (hitInfo.HitLocation == HitTestLocations.None)
hitInfo = base.HitTest(point);
}
return hitInfo;
}
public override object GetNextSelectableObject(object obj, DesignerNavigationDirection direction)
{
if (ActiveDesigner != this)
return base.GetNextSelectableObject(obj, direction);
if (direction != DesignerNavigationDirection.Down && direction != DesignerNavigationDirection.Up)
return null;
object nextObject = null;
ReadOnlyCollection<ActivityDesigner> containedDesigners = ContainedDesigners;
if (direction == DesignerNavigationDirection.Down)
{
if (obj is ConnectorHitTestInfo)
{
int currentIndex = ((ConnectorHitTestInfo)obj).MapToIndex();
if (currentIndex >= 0 && currentIndex < containedDesigners.Count)
nextObject = ((ActivityDesigner)containedDesigners[currentIndex]).Activity;
}
else if (obj is Activity)
{
ActivityDesigner activityDesigner = ActivityDesigner.GetDesigner(obj as Activity);
int currentIndex = (activityDesigner != null) ? containedDesigners.IndexOf(activityDesigner) : -1;
if (currentIndex >= 0 && (currentIndex + 1) < GetConnectors().Length)
nextObject = new ConnectorHitTestInfo(this, HitTestLocations.Designer, currentIndex + 1);
}
}
else if (direction == DesignerNavigationDirection.Up)
{
if (obj is ConnectorHitTestInfo)
{
int currentIndex = ((ConnectorHitTestInfo)obj).MapToIndex();
if (currentIndex > 0 && currentIndex < GetConnectors().Length)
nextObject = ((ActivityDesigner)containedDesigners[currentIndex - 1]).Activity;
}
else if (obj is Activity)
{
ActivityDesigner activityDesigner = ActivityDesigner.GetDesigner(obj as Activity);
int currentIndex = (activityDesigner != null) ? containedDesigners.IndexOf(activityDesigner) : -1;
if (currentIndex >= 0 && currentIndex < GetConnectors().Length)
nextObject = new ConnectorHitTestInfo(this, HitTestLocations.Designer, currentIndex);
}
}
return nextObject;
}
#endregion
#region Protected Methods
protected override void Initialize(Activity activity)
{
base.Initialize(activity);
HelpText = DR.GetString(DR.DropActivitiesHere);
}
protected override Rectangle[] GetDropTargets(Point dropPoint)
{
if (HelpTextRectangle.Contains(dropPoint))
return new Rectangle[] { HelpTextRectangle };
else
return GetConnectors();
}
protected override void OnPaint(ActivityDesignerPaintEventArgs e)
{
base.OnPaint(e);
CompositeDesignerTheme compositeDesignerTheme = e.DesignerTheme as CompositeDesignerTheme;
if (Expanded && compositeDesignerTheme != null)
{
//Draw the connectors
Rectangle helpTextRectangle = HelpTextRectangle;
if (CurrentDropTarget == -1 && !helpTextRectangle.Size.IsEmpty)
{
Rectangle[] connectors = GetConnectors();
if (connectors.Length > 0)
{
DrawConnectors(e.Graphics, compositeDesignerTheme.ForegroundPen, new Point[] { new Point(connectors[0].X + connectors[0].Width / 2, connectors[0].Y + 2), new Point(connectors[0].X + connectors[0].Width / 2, helpTextRectangle.Top - 2) }, compositeDesignerTheme.ConnectorStartCap, LineAnchor.None);
DrawConnectors(e.Graphics, compositeDesignerTheme.ForegroundPen, new Point[] { new Point(connectors[0].X + connectors[0].Width / 2, helpTextRectangle.Bottom + 2), new Point(connectors[0].X + connectors[0].Width / 2, connectors[0].Bottom - 2) }, LineAnchor.None, compositeDesignerTheme.ConnectorEndCap);
}
ActivityDesignerPaint.DrawText(e.Graphics, compositeDesignerTheme.Font, this.HelpText, helpTextRectangle, StringAlignment.Center, e.AmbientTheme.TextQuality, compositeDesignerTheme.ForegroundBrush);
}
else
{
Rectangle[] connectors = GetConnectors();
for (int i = 0; i < connectors.Length; i++)
{
Pen pen = (i == CurrentDropTarget) ? e.AmbientTheme.DropIndicatorPen : compositeDesignerTheme.ForegroundPen;
LineAnchor startCap = ((i == 0 && connectors.Length > 2) || i == connectors.Length - 1) ? LineAnchor.None : compositeDesignerTheme.ConnectorStartCap;
LineAnchor endCap = (i == 0 || (i == connectors.Length - 1 && connectors.Length > 2)) ? LineAnchor.None : compositeDesignerTheme.ConnectorEndCap;
DrawConnectors(e.Graphics, pen, new Point[] { new Point(connectors[i].Left + connectors[i].Width / 2, connectors[i].Top + 2), new Point(connectors[i].Left + connectors[i].Width / 2, connectors[i].Bottom - 2) }, startCap, endCap);
}
}
}
}
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;
//This condition is to center align the children
int height = 0;
ReadOnlyCollection<Point> connectionPoints = GetInnerConnections(DesignerEdges.Top | DesignerEdges.Bottom);
Point location = (connectionPoints.Count > 0) ? connectionPoints[0] : Location;
if (ContainedDesigners.Count == 1)
{
int heightDelta = 0;
if (connectionPoints.Count > 0)
heightDelta = Size.Height - (connectionPoints[connectionPoints.Count - 1].Y - connectionPoints[0].Y);
height += (Size.Height - heightDelta) / 2 - ContainedDesigners[0].Size.Height / 2;
}
else
{
height += ((compositeDesignerTheme != null) ? compositeDesignerTheme.ConnectorSize.Height : 0);
}
foreach (ActivityDesigner activityDesigner in ContainedDesigners)
{
Size designerSize = activityDesigner.Size;
activityDesigner.Location = new Point(location.X - (designerSize.Width / 2), location.Y + height);
height += designerSize.Height + ((compositeDesignerTheme != null) ? compositeDesignerTheme.ConnectorSize.Height : 0);
}
}
}
protected override Size OnLayoutSize(ActivityDesignerLayoutEventArgs e)
{
Size containerSize = base.OnLayoutSize(e);
CompositeDesignerTheme compositeDesignerTheme = e.DesignerTheme as CompositeDesignerTheme;
if (Expanded && ActiveDesigner == this && compositeDesignerTheme != null)
{
if (this.HelpText.Length > 0)
this.helpTextSize = ActivityDesignerPaint.MeasureString(e.Graphics, compositeDesignerTheme.Font, this.HelpText, StringAlignment.Center, SequentialActivityDesigner.DefaultHelpTextSize);
//Calculate the size based on child size
containerSize.Height += compositeDesignerTheme.ConnectorSize.Height; //Add the height of first connector
foreach (ActivityDesigner activityDesigner in ContainedDesigners)
{
Size childSize = activityDesigner.Size;
containerSize.Width = Math.Max(containerSize.Width, childSize.Width);
containerSize.Height += childSize.Height;
containerSize.Height += compositeDesignerTheme.ConnectorSize.Height;
}
if (ContainedDesigners.Count == 0)
{
Rectangle helpTextRectangle = HelpTextRectangle;
containerSize.Width = Math.Max(helpTextRectangle.Width, containerSize.Width);
containerSize.Height += helpTextRectangle.Height;
containerSize.Height += compositeDesignerTheme.ConnectorSize.Height; //Add the height of last connector
}
containerSize.Width = Math.Max(containerSize.Width, compositeDesignerTheme.Size.Width);
containerSize.Width += 3 * e.AmbientTheme.Margin.Width;
containerSize.Width += 2 * e.AmbientTheme.SelectionSize.Width;
containerSize.Height = Math.Max(containerSize.Height, compositeDesignerTheme.Size.Height);
}
return containerSize;
}
#endregion
#region Private Methods
private DesignerGlyph[] CreateConnectorDragDropGlyphs()
{
//see if there's a drag'n'drop operation going on
WorkflowView parentView = ParentView;
DragDropManager dragDropManager = GetService(typeof(DragDropManager)) as DragDropManager;
if (parentView == null || dragDropManager == null || !parentView.DragDropInProgress || DrawingState != DrawingStates.Valid)
return new DesignerGlyph[] { };
List<DesignerGlyph> glyphs = new List<DesignerGlyph>();
Rectangle logicalViewPort = parentView.ClientRectangleToLogical(new Rectangle(Point.Empty, parentView.ViewPortSize));
AmbientTheme ambientTheme = WorkflowTheme.CurrentTheme.AmbientTheme;
Rectangle[] connectors = GetConnectors();
Rectangle helpTextRectangle = HelpTextRectangle;
for (int i = 0; i < connectors.Length; i++)
{
if (logicalViewPort.IntersectsWith(connectors[i]) && i != CurrentDropTarget && dragDropManager.IsValidDropContext(new ConnectorHitTestInfo(this, HitTestLocations.Designer, i)))
{
Point glyphLocation = Point.Empty;
if (helpTextRectangle.IsEmpty)
glyphLocation = new Point(connectors[i].Location.X + connectors[i].Size.Width / 2 + 1, connectors[i].Location.Y + connectors[i].Size.Height / 2);
else
glyphLocation = new Point(helpTextRectangle.Left + helpTextRectangle.Width / 2 + 1, helpTextRectangle.Top - ambientTheme.DropIndicatorSize.Height / 2);
glyphs.Add(new ConnectorDragDropGlyph(i, glyphLocation));
}
}
return glyphs.ToArray();
}
#endregion
#endregion
#region Class SequentialConnectorSelectionGlyph
private sealed class SequentialConnectorSelectionGlyph : ConnectorSelectionGlyph
{
public SequentialConnectorSelectionGlyph(int connectorIndex, bool isPrimarySelectionGlyph)
: base(connectorIndex, isPrimarySelectionGlyph)
{
}
public override Rectangle GetBounds(ActivityDesigner designer, bool activated)
{
Rectangle bounds = Rectangle.Empty;
if (designer is SequentialActivityDesigner)
{
Rectangle[] connectors = ((SequentialActivityDesigner)designer).GetConnectors();
if (this.connectorIndex < connectors.Length)
bounds = connectors[this.connectorIndex];
}
return bounds;
}
protected override void OnPaint(Graphics graphics, bool activated, AmbientTheme ambientTheme, ActivityDesigner designer)
{
Rectangle bounds = GetBounds(designer, activated);
Rectangle[] grabHandles = new Rectangle[2];
grabHandles[0] = new Rectangle(bounds.X + bounds.Width / 2 - ambientTheme.SelectionSize.Width / 2, bounds.Y, ambientTheme.SelectionSize.Width, ambientTheme.SelectionSize.Height);
grabHandles[1] = new Rectangle(bounds.X + bounds.Width / 2 - ambientTheme.SelectionSize.Width / 2, bounds.Bottom - ambientTheme.SelectionSize.Height, ambientTheme.SelectionSize.Width, ambientTheme.SelectionSize.Height);
ActivityDesignerPaint.DrawGrabHandles(graphics, grabHandles, this.isPrimarySelectionGlyph);
}
public override bool IsPrimarySelection
{
get
{
return this.isPrimarySelectionGlyph;
}
}
}
#endregion
}
#endregion
}
|