Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / Common / AuthoringOM / Design / FreeFormDesigner.cs / 1305376 / FreeFormDesigner.cs
namespace System.Workflow.ComponentModel.Design { using System; using System.IO; using System.Drawing; using System.Diagnostics; using System.Collections; using System.Windows.Forms; using System.ComponentModel; using System.Drawing.Drawing2D; using System.Collections.Generic; using System.ComponentModel.Design; using System.Collections.ObjectModel; using System.Workflow.ComponentModel.Design; using System.ComponentModel.Design.Serialization; using System.Workflow.ComponentModel.Serialization; #region Interface IConnectableDesigner internal interface IConnectableDesigner { bool CanConnect(ConnectionPoint source, ConnectionPoint target); void OnConnected(ConnectionPoint source, ConnectionPoint target); } #endregion #region Enum ZOrder internal enum ZOrder { Foreground = 1, Background = 2 } #endregion #region Class FreeformActivityDesigner // //By default this designer will use the CompositeActivityDesigner theme [DesignerSerializer(typeof(FreeformActivityDesignerLayoutSerializer), typeof(WorkflowMarkupSerializer))] public class FreeformActivityDesigner : CompositeActivityDesigner { #region Class FreeformDesignerAccessibleObject internal class FreeformDesignerAccessibleObject : CompositeDesignerAccessibleObject { public FreeformDesignerAccessibleObject(FreeformActivityDesigner activityDesigner) : base(activityDesigner) { } public override AccessibleObject GetChild(int index) { FreeformActivityDesigner designer = (FreeformActivityDesigner)this.ActivityDesigner; if (designer.ShowConnectorsInForeground) { int connectorsCount = designer.Connectors.Count; if (index < connectorsCount) return designer.Connectors[index].AccessibilityObject; else return designer.ContainedDesigners[index - connectorsCount].AccessibilityObject; } else { int containedDesignersCount = designer.ContainedDesigners.Count; if (index < containedDesignersCount) return designer.ContainedDesigners[index].AccessibilityObject; else return designer.Connectors[index - containedDesignersCount].AccessibilityObject; } } public override int GetChildCount() { FreeformActivityDesigner designer = (FreeformActivityDesigner)this.ActivityDesigner; int count = base.GetChildCount() + designer.Connectors.Count; return count; } } #endregion Class FreeformDesignerAccessibleObject #region Members internal static Size DefaultAutoSizeMargin = new Size(40, 40); private FreeformDesignerAccessibleObject accessibilityObject; private bool autoSize = true; private AutoSizeMode autoSizeMode = AutoSizeMode.GrowOnly; private Size autoSizeMargin = FreeformActivityDesigner.DefaultAutoSizeMargin; private bool enableUserDrawnConnectors = true; private Listconnectors = new List (); private bool retainContainedDesignerLocations = false; public event ConnectorEventHandler ConnectorAdded; public event ConnectorEventHandler ConnectorChanged; public event ConnectorEventHandler ConnectorRemoved; #endregion #region Construction / Destruction public FreeformActivityDesigner() { } #endregion #region Properties #region Public Properties public override AccessibleObject AccessibilityObject { get { if (this.accessibilityObject == null) this.accessibilityObject = new FreeformDesignerAccessibleObject(this); return this.accessibilityObject; } } /// /// Gets or Sets value indicating if the designer will be resized automatically based on the child designers /// [DefaultValue(true)] public bool AutoSize { get { return this.autoSize; } set { if (this.autoSize == value) return; this.autoSize = value; PerformLayout(); } } ////// Gets or Sets the auto sizing mode /// [DefaultValue(AutoSizeMode.GrowOnly)] public AutoSizeMode AutoSizeMode { get { return this.autoSizeMode; } set { if (this.autoSizeMode == value) return; this.autoSizeMode = value; PerformLayout(); } } ////// Gets the margins left around the contained designers when autosizing /// public Size AutoSizeMargin { get { Size margin = this.autoSizeMargin; if (WorkflowTheme.CurrentTheme.AmbientTheme.ShowGrid) { Size gridSize = WorkflowTheme.CurrentTheme.AmbientTheme.GridSize; margin.Width += gridSize.Width / 2; margin.Height += gridSize.Height / 2; } return margin; } set { if (this.autoSizeMargin == value) return; this.autoSizeMargin = value; PerformLayout(); } } ////// Allows user to drag and draw connectors on the design surface /// [DefaultValue(true)] public bool EnableUserDrawnConnectors { get { return (this.enableUserDrawnConnectors && IsEditable); } set { this.enableUserDrawnConnectors = value; } } public override bool CanExpandCollapse { get { return false; } } public override object FirstSelectableObject { get { IListchilddesigners = ContainedDesigners; return (childdesigners.Count > 0) ? childdesigners[0].Activity : null; } } public override object LastSelectableObject { get { IList childdesigners = ContainedDesigners; return (childdesigners.Count > 0) ? childdesigners[childdesigners.Count - 1].Activity : null; } } public override Size MinimumSize { get { //Now go thru all the activity designers and consider the bottom coordinate + selection size + page separator as the min size Size minimumSize = base.MinimumSize; if (Activity != null && ((IComponent)Activity).Site != null && !(ParentDesigner is FreeformActivityDesigner)) { minimumSize.Width *= 4; minimumSize.Height *= 4; } //If the designer is root designer and not inlined then we should occupy the area of workflow view if (IsRootDesigner && InvokingDesigner == null) { WorkflowView workflowView = ParentView; minimumSize.Width = Math.Max(minimumSize.Width, workflowView.ViewPortSize.Width - 2 * WorkflowRootLayout.Separator.Width); minimumSize.Height = Math.Max(minimumSize.Height, workflowView.ViewPortSize.Height - 2 * WorkflowRootLayout.Separator.Height); } if (AutoSize) { Rectangle childRectangle = GetEnclosingRectangle(); if (!childRectangle.IsEmpty) { minimumSize.Width = Math.Max(minimumSize.Width, childRectangle.Width); minimumSize.Height = Math.Max(minimumSize.Height, childRectangle.Height); } } return minimumSize; } } public override Point Location { get { return base.Location; } set { if (Location == value) return; //Please note that we require this logic to maintain the contained designer location when //resizing the designer ReadOnlyCollection containedDesigners = ContainedDesigners; List containedDesignerLocations = new List (); if (this.retainContainedDesignerLocations) { foreach (ActivityDesigner activityDesigner in containedDesigners) containedDesignerLocations.Add(activityDesigner.Location); } else { Size moveDelta = new Size(value.X - base.Location.X, value.Y - base.Location.Y); FreeformActivityDesigner freeFormActivityDesigner = this; Collection connectors = new Collection (); while (freeFormActivityDesigner != null) { foreach (Connector connector in freeFormActivityDesigner.Connectors) if (connector.RenderingOwner == this) connectors.Add(connector); freeFormActivityDesigner = freeFormActivityDesigner.ParentDesigner as FreeformActivityDesigner; } foreach (Connector connector in connectors) { connector.Offset(moveDelta); } } base.Location = value; if (this.retainContainedDesignerLocations && containedDesigners.Count == containedDesignerLocations.Count) { for (int i = 0; i < containedDesigners.Count; i++) containedDesigners[i].Location = containedDesignerLocations[i]; } Invalidate(); } } /// /// Returns collection of connectors /// public ReadOnlyCollectionConnectors { get { return this.connectors.AsReadOnly(); } } #endregion #region Protected Properties /// /// Get the value indicating if the connectors are drawn in the forground /// protected virtual bool ShowConnectorsInForeground { get { return false; } } protected internal override bool EnableVisualResizing { get { if (AutoSize && AutoSizeMode == AutoSizeMode.GrowAndShrink) return false; else return true; } } protected internal override ActivityDesignerGlyphCollection Glyphs { get { ActivityDesignerGlyphCollection glyphs = new ActivityDesignerGlyphCollection(); glyphs.AddRange(base.Glyphs); //Now go thru all the designers and for the designers which are connectable, return connection glyphs //Also return the move glyphs for movable designer ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService; if (selectionService != null) { foreach (object selectedObject in selectionService.GetSelectedComponents()) { ConnectorHitTestInfo connectorHitInfo = selectedObject as ConnectorHitTestInfo; if (connectorHitInfo != null && connectorHitInfo.AssociatedDesigner == this) glyphs.Add(new FreeFormConnectorSelectionGlyph(connectorHitInfo.MapToIndex(), (connectorHitInfo == selectionService.PrimarySelection))); } } return glyphs; } } #endregion #region Private Properties internal override WorkflowLayout SupportedLayout { get { return new WorkflowRootLayout(Activity.Site); } } #region Properties used during serialization only //NOTE THAT THIS WILL ONLY BE USED FOR SERIALIZATION PURPOSES [EditorBrowsable(EditorBrowsableState.Never)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] internal ListDesignerConnectors { get { List connectors = new List (this.connectors); return connectors; } } #endregion #endregion #endregion #region Methods #region Public Methods /// /// Adds connector to the designer /// /// Connector to add public Connector AddConnector(ConnectionPoint source, ConnectionPoint target) { if (source == null) throw new ArgumentNullException("source"); if (source.AssociatedDesigner == null) throw new ArgumentException("source", SR.GetString(SR.Error_AssociatedDesignerMissing)); if (target == null) throw new ArgumentNullException("target"); if (target.AssociatedDesigner == null) throw new ArgumentException("target", SR.GetString(SR.Error_AssociatedDesignerMissing)); //This check can be eliminated if it slows down connections, this is just to ensure we are adding connectors //to correct activity designer FreeformActivityDesigner connectorContainer = ConnectionManager.GetConnectorContainer(source.AssociatedDesigner); if (this != connectorContainer) throw new InvalidOperationException(DR.GetString(DR.Error_AddConnector1)); if ((Activity != source.AssociatedDesigner.Activity && !Helpers.IsChildActivity(Activity as CompositeActivity, source.AssociatedDesigner.Activity)) || (Activity != target.AssociatedDesigner.Activity && !Helpers.IsChildActivity(Activity as CompositeActivity, target.AssociatedDesigner.Activity))) throw new ArgumentException(DR.GetString(DR.Error_AddConnector2)); Connector connector = CreateConnector(source, target); if (connector != null) { if (this.connectors.Contains(connector)) throw new InvalidOperationException(DR.GetString(DR.Error_AddConnector3)); this.connectors.Add(connector); connector.SetParent(this); OnConnectorAdded(new ConnectorEventArgs(connector)); } PerformLayout(); return connector; } ////// Removes connector from the designer /// /// Connector to remove public void RemoveConnector(Connector connector) { if (connector == null) throw new ArgumentNullException("connector"); if (this.connectors.Contains(connector)) { OnConnectorRemoved(new ConnectorEventArgs(connector)); connector.SetParent(null); this.connectors.Remove(connector); } } ////// Sends the contained designer to back of z-order /// /// Designer to send to back public void SendToBack(ActivityDesigner containedDesigner) { if (containedDesigner == null) throw new ArgumentNullException("containedDesigner"); if (!ContainedDesigners.Contains(containedDesigner)) throw new ArgumentException(DR.GetString(DR.InvalidDesignerSpecified, "containedDesigner")); UpdateZOrder(containedDesigner, ZOrder.Background); } ////// Brings the contained designer to top of z-order /// /// Designer to bring to front public void BringToFront(ActivityDesigner containedDesigner) { if (containedDesigner == null) throw new ArgumentNullException("containedDesigner"); if (!ContainedDesigners.Contains(containedDesigner)) throw new ArgumentException(DR.GetString(DR.InvalidDesignerSpecified, "containedDesigner")); UpdateZOrder(containedDesigner, ZOrder.Foreground); } ////// Moves specified contained designer to specified location inside designer /// /// Designer to move /// Location to move to. public void MoveContainedDesigner(ActivityDesigner containedDesigner, Point newLocation) { if (containedDesigner == null) throw new ArgumentNullException("containedDesigner"); if (!ContainedDesigners.Contains(containedDesigner)) throw new ArgumentException(DR.GetString(DR.InvalidDesignerSpecified, "containedDesigner")); FreeformActivityDesigner.SetDesignerBounds(containedDesigner, new Rectangle(newLocation, containedDesigner.Size)); PerformLayout(); Invalidate(); } ////// Resizes specified contained designer to specified size /// /// Designer to resize /// Size to resize it to public void ResizeContainedDesigner(ActivityDesigner containedDesigner, Size newSize) { if (containedDesigner == null) throw new ArgumentNullException("containedDesigner"); if (!ContainedDesigners.Contains(containedDesigner)) throw new ArgumentException(DR.GetString(DR.InvalidDesignerSpecified, "containedDesigner")); FreeformActivityDesigner.SetDesignerBounds(containedDesigner, new Rectangle(containedDesigner.Location, newSize)); PerformLayout(); } public override HitTestInfo HitTest(Point point) { HitTestInfo hitInfo = base.HitTest(point); //First check that if the drag drop is in progress and the drop operation has been initiated based on //A child designer then if the queried point is also on the drop initiated designer then we return freeform //designer as the designer where hittest occured ReadOnlyCollectioncontainedDesigners = ContainedDesigners; WorkflowView workflowView = ParentView; DragDropManager dragDropManager = GetService(typeof(DragDropManager)) as DragDropManager; if (workflowView != null && dragDropManager != null && workflowView.DragDropInProgress && hitInfo.AssociatedDesigner != null && dragDropManager.DraggedActivities.Contains(hitInfo.AssociatedDesigner.Activity) && hitInfo.AssociatedDesigner.Bounds.Contains(point)) { if (Activity == hitInfo.AssociatedDesigner.Activity) return HitTestInfo.Nowhere; else if (containedDesigners.Contains(hitInfo.AssociatedDesigner)) return new HitTestInfo(this, HitTestLocations.Designer); } //Now try going through the connectors if (!(hitInfo is ConnectionPointHitTestInfo) && (hitInfo.HitLocation == HitTestLocations.None || hitInfo.AssociatedDesigner == this || ShowConnectorsInForeground)) { //Now go thru all the connectors and try to select them for (int i = 0; i < this.connectors.Count; i++) { if (this.connectors[i].HitTest(point)) return new ConnectorHitTestInfo(this, HitTestLocations.Designer | HitTestLocations.Connector, i); } } return hitInfo; } //activities being moved within the same container private List movedActivities = null; private List MovingActivities { get { if(this.movedActivities == null) this.movedActivities = new List (); return this.movedActivities; } } public override void MoveActivities(HitTestInfo moveLocation, ReadOnlyCollection activitiesToMove) { if (moveLocation == null) throw new ArgumentNullException("moveLocation"); if (activitiesToMove == null) throw new ArgumentNullException("activitiesToMove"); FreeformActivityDesigner connectorContainer = ConnectionManager.GetConnectorContainer(this); try { connectorContainer.MovingActivities.Clear(); if (connectorContainer != null && connectorContainer.Connectors.Count > 0) { foreach (Activity movingActivity in activitiesToMove) { ActivityDesigner designerToMove = ActivityDesigner.GetDesigner(movingActivity); FreeformActivityDesigner topMostParentDesigner = ConnectionManager.GetConnectorContainer(designerToMove); if (topMostParentDesigner == connectorContainer) connectorContainer.MovingActivities.Add(designerToMove); } } base.MoveActivities(moveLocation, activitiesToMove); } finally { connectorContainer.MovingActivities.Clear(); } } public override object GetNextSelectableObject(object current, DesignerNavigationDirection navigate) { object nextObject = null; ArrayList activityDesigners = new ArrayList(ContainedDesigners); ActivityDesigner activityDesigner = (current is Activity) ? ActivityDesigner.GetDesigner(current as Activity) : ActivityDesigner.GetParentDesigner(current); int index = (activityDesigner != null) ? activityDesigners.IndexOf(activityDesigner) : -1; if ((navigate == DesignerNavigationDirection.Left || navigate == DesignerNavigationDirection.Up) && index >= 0 && index < activityDesigners.Count) nextObject = ((ActivityDesigner)activityDesigners[(index > 0) ? index - 1 : activityDesigners.Count - 1]).Activity; else if ((navigate == DesignerNavigationDirection.Right || navigate == DesignerNavigationDirection.Down) && index <= activityDesigners.Count - 1) nextObject = ((ActivityDesigner)activityDesigners[(index < activityDesigners.Count - 1) ? index + 1 : 0]).Activity; return nextObject; } #endregion #region Protected Methods protected override void Initialize(Activity activity) { base.Initialize(activity); //We only add the designer property extender here, it will be removed when the design surface is //destroyed EnsureDesignerExtender(); } protected override void Dispose(bool disposing) { //Dispose the connectors for (int i = 0; i < this.connectors.Count; i++) ((IDisposable)this.connectors[i]).Dispose(); this.connectors.Clear(); base.Dispose(disposing); } // protected override void OnContainedActivitiesChanging(ActivityCollectionChangeEventArgs listChangeArgs) { base.OnContainedActivitiesChanging(listChangeArgs); if (listChangeArgs.Action == ActivityCollectionChangeAction.Remove) { FreeformActivityDesigner connectorContainer = ConnectionManager.GetConnectorContainer(this); List connectorsToDelete = new List (); //check if the removed designer is being moved within the same container //in this case dont remove the connector... ActivityDesigner activityDesigner = this; while (activityDesigner != null) { FreeformActivityDesigner freeFormDesigner = activityDesigner as FreeformActivityDesigner; if (freeFormDesigner != null && freeFormDesigner.Connectors.Count > 0) { foreach (Activity activityToRemove in listChangeArgs.RemovedItems) { ActivityDesigner designerToRemove = ActivityDesigner.GetDesigner(activityToRemove); //if the designer is being moved within the same container, ignore it //otherwise remove all related connectors if (!connectorContainer.MovingActivities.Contains(designerToRemove)) { foreach (Connector connector in freeFormDesigner.Connectors) { if (designerToRemove == connector.Source.AssociatedDesigner || designerToRemove == connector.Target.AssociatedDesigner) connectorsToDelete.Add(connector); } } } } activityDesigner = activityDesigner.ParentDesigner; } foreach (Connector connectorToDelete in connectorsToDelete) { connectorToDelete.ParentDesigner.RemoveConnector(connectorToDelete); ((IDisposable)connectorToDelete).Dispose(); } } } /// /// Creates the connector between specified connection points. /// /// Source connection point /// Target connection point ///protected internal virtual Connector CreateConnector(ConnectionPoint source, ConnectionPoint target) { return new Connector(source, target); } /// /// Called to check if contained designers can be connected /// /// Source connection point /// Target connection point ///protected internal virtual bool CanConnectContainedDesigners(ConnectionPoint source, ConnectionPoint target) { return (((IConnectableDesigner)source.AssociatedDesigner).CanConnect(source, target) && ((IConnectableDesigner)target.AssociatedDesigner).CanConnect(source, target)); } /// /// Called when the connection between contained designers is established /// /// Source connection point /// Target connection point protected internal virtual void OnContainedDesignersConnected(ConnectionPoint source, ConnectionPoint target) { ((IConnectableDesigner)source.AssociatedDesigner).OnConnected(source, target); ((IConnectableDesigner)target.AssociatedDesigner).OnConnected(source, target); } ////// Called to find if the contained designer can be visually resized by the user /// /// Designer to visually resize ///True if the designer can be visually resize, false otherwise protected internal virtual bool CanResizeContainedDesigner(ActivityDesigner containedDesigner) { return (containedDesigner is FreeformActivityDesigner); } ////// Called when a new connector has been added in the freeform designer /// /// Event args containing connector protected virtual void OnConnectorAdded(ConnectorEventArgs e) { if (ConnectorAdded != null) ConnectorAdded(this, e); } ////// Called when the user changed the end points of the connector /// /// protected internal virtual void OnConnectorChanged(ConnectorEventArgs e) { if (ConnectorChanged != null) ConnectorChanged(this, e); } protected virtual void OnConnectorRemoved(ConnectorEventArgs e) { if (ConnectorRemoved != null) ConnectorRemoved(this, e); } protected override void OnLayoutPosition(ActivityDesignerLayoutEventArgs e) { base.OnLayoutPosition(e); if (AutoSize) { Point newLocation = Location; Rectangle childRectangle = GetEnclosingRectangle(); if (!childRectangle.IsEmpty) { if (AutoSizeMode == AutoSizeMode.GrowOnly) { newLocation.X = Math.Min(newLocation.X, childRectangle.Left); newLocation.Y = Math.Min(newLocation.Y, childRectangle.Top); } else { newLocation = childRectangle.Location; } } this.retainContainedDesignerLocations = true; Location = newLocation; this.retainContainedDesignerLocations = false; } foreach (Connector connector in this.connectors) connector.OnLayout(e); } protected override Size OnLayoutSize(ActivityDesignerLayoutEventArgs e) { Rectangle bounds = Bounds; Size size = bounds.Size; base.OnLayoutSize(e); if (AutoSize) { if (AutoSizeMode == AutoSizeMode.GrowOnly) { Rectangle childRectangle = GetEnclosingRectangle(); if (!childRectangle.IsEmpty) { size.Width += Math.Max(bounds.Left - childRectangle.Left, 0); size.Width += Math.Max(childRectangle.Right - bounds.Right, 0); size.Height += Math.Max(bounds.Top - childRectangle.Top, 0); size.Height += Math.Max(childRectangle.Bottom - bounds.Bottom, 0); } } else { size = MinimumSize; } } return size; } protected override void OnThemeChange(ActivityDesignerTheme newTheme) { base.OnThemeChange(newTheme); if (WorkflowTheme.CurrentTheme.AmbientTheme.ShowGrid) { foreach (ActivityDesigner containedDesigner in ContainedDesigners) containedDesigner.Location = DesignerHelpers.SnapToGrid(containedDesigner.Location); PerformLayout(); } } protected override void OnDragOver(ActivityDragEventArgs e) { bool ctrlKeyPressed = ((e.KeyState & 8) == 8); if (ctrlKeyPressed && (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) e.Effect = DragDropEffects.Copy; else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move) e.Effect = DragDropEffects.Move; } protected override void OnDragDrop(ActivityDragEventArgs e) { //Set the correct drag drop effect bool ctrlKeyPressed = ((e.KeyState & 8) == 8); if (ctrlKeyPressed && (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) e.Effect = DragDropEffects.Copy; else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move) e.Effect = DragDropEffects.Move; //Now there can be set of activities which are inserted and set of activities which are moved //So first lets get the list of activities which need to be inserted ListactivitiesToInsert = new List (); List newActivities = new List (); foreach (Activity activity in e.Activities) { if (activity.Site == null || activity.Parent != Activity) activitiesToInsert.Add(activity); if (activity.Site == null) newActivities.Add(activity); } //If the component are sited then that means that we are inserting it if (activitiesToInsert.Count > 0) CompositeActivityDesigner.InsertActivities(this, new ConnectorHitTestInfo(this, HitTestLocations.Designer, ((CompositeActivity)Activity).Activities.Count), activitiesToInsert.AsReadOnly(), SR.GetString(SR.DragDropActivities)); Point dropPoint = new Point(e.X, e.Y); Point[] movedLocations = FreeFormDragDropManager.GetDesignerLocations(e.DragInitiationPoint, dropPoint, e.Activities); if (movedLocations.Length == e.Activities.Count) { for (int i = 0; i < e.Activities.Count; i++) { ActivityDesigner designerToMove = ActivityDesigner.GetDesigner(e.Activities[i]); if (designerToMove != null) { Point location = (newActivities.Contains(designerToMove.Activity)) ? dropPoint : movedLocations[i]; MoveContainedDesigner(designerToMove, location); } } } else { Debug.Assert(false); } } public override void InsertActivities(HitTestInfo insertLocation, ReadOnlyCollection activitiesToInsert) { base.InsertActivities(insertLocation, activitiesToInsert); //Now go through all the designers for activities and make sure that if their locations are 0,0 then we set the //locations at Location.X + AutoSizeMargin if (AutoSize) { Size autoSizeMargin = AutoSizeMargin; Point location = Location; foreach (Activity activity in activitiesToInsert) { ActivityDesigner designer = ActivityDesigner.GetDesigner(activity); if (designer.Location.IsEmpty) designer.Location = new Point(location.X + autoSizeMargin.Width, location.Y + autoSizeMargin.Height); } } } protected override void OnResizing(ActivityDesignerResizeEventArgs e) { //If we are in AutoSize mode with grow and shrink option then dont allow resizing if (AutoSize) { if (AutoSizeMode == AutoSizeMode.GrowOnly) { Rectangle minRectangle = GetEnclosingRectangle(); if (!minRectangle.IsEmpty) { Rectangle bounds = Rectangle.Empty; bounds.X = Math.Min(minRectangle.Left, e.Bounds.Left); bounds.Y = Math.Min(minRectangle.Top, e.Bounds.Top); bounds.Width = Math.Max(minRectangle.Right - bounds.Left, e.Bounds.Right - bounds.Left); bounds.Height = Math.Max(minRectangle.Bottom - bounds.Top, e.Bounds.Bottom - bounds.Top); if (bounds != e.Bounds) e = new ActivityDesignerResizeEventArgs(e.SizingEdge, bounds); } } else { PerformLayout(); } } this.retainContainedDesignerLocations = true; base.OnResizing(e); this.retainContainedDesignerLocations = false; } protected override void OnKeyDown(KeyEventArgs e) { if (e == null) throw new ArgumentNullException("e"); ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService; object selectedObject = (selectionService != null) ? selectionService.PrimarySelection : null; if (selectedObject == null) return; List topLevelActivities = new List (Helpers.GetTopLevelActivities(selectionService.GetSelectedComponents())); if (e.KeyCode == Keys.Left || e.KeyCode == Keys.Right || e.KeyCode == Keys.Up || e.KeyCode == Keys.Down) { Size direction = Size.Empty; const int step = 5; if (e.KeyCode == Keys.Left) direction = new Size(-step, 0); else if (e.KeyCode == Keys.Right) direction = new Size(step, 0); else if (e.KeyCode == Keys.Up) direction = new Size(0, -step); else if (e.KeyCode == Keys.Down) direction = new Size(0, step); foreach (Activity selectedActivity in topLevelActivities) { //move designer by 'direction' ActivityDesigner designer = ActivityDesigner.GetDesigner(selectedActivity); if (designer != null) { //refresh designer area both before and after move ParentView.InvalidateClientRectangle(new Rectangle(designer.Location, designer.Size)); designer.Location += direction; ParentView.InvalidateClientRectangle(new Rectangle(designer.Location, designer.Size)); } } //update layout to grow the parent if needed after all designers have been moved // PerformLayout(); e.Handled = true; } else if (e.KeyCode == Keys.Delete) { //if there is a connector selected, delete it ICollection components = selectionService.GetSelectedComponents(); foreach (object component in components) { ConnectorHitTestInfo connector = component as ConnectorHitTestInfo; if (connector != null) { FreeformActivityDesigner freeformDesigner = connector.AssociatedDesigner as FreeformActivityDesigner; if (freeformDesigner != null) { ReadOnlyCollection connectors = freeformDesigner.Connectors; int connectorIndex = connector.MapToIndex(); if (connectorIndex < connectors.Count) { selectionService.SetSelectedComponents(new object[] { connector }, SelectionTypes.Remove); freeformDesigner.RemoveConnector(connectors[connectorIndex]); object nextSelectableObject = freeformDesigner; if (connectors.Count > 0) nextSelectableObject = new ConnectorHitTestInfo(freeformDesigner, HitTestLocations.Connector | HitTestLocations.Designer, (connectorIndex > 0) ? connectorIndex - 1 : connectorIndex); selectionService.SetSelectedComponents(new object[] { nextSelectableObject }, SelectionTypes.Replace); } } } } e.Handled = true; } if(!e.Handled) { //let the base handle all other keys including tabs base.OnKeyDown(e); } } #endregion #region Private Methods internal static void SetDesignerBounds(ActivityDesigner designer, Rectangle bounds) { if (designer == null || designer.Activity == null || designer.Activity.Site == null) return; PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(designer); PropertyDescriptor sizeProperty = (properties != null) ? properties["Size"] : null; if (sizeProperty != null) sizeProperty.SetValue(designer.Activity, bounds.Size); else designer.Size = bounds.Size; PropertyDescriptor locationProperty = (properties != null) ? properties["Location"] : null; if (locationProperty != null) locationProperty.SetValue(designer.Activity, bounds.Location); else designer.Location = bounds.Location; WorkflowView workflowView = designer.Activity.Site.GetService(typeof(WorkflowView)) as WorkflowView; if (workflowView != null) { if (designer.ParentDesigner != null) workflowView.InvalidateLogicalRectangle(designer.ParentDesigner.Bounds); else workflowView.Invalidate(); } } internal override void OnPaintContainedDesigners(ActivityDesignerPaintEventArgs e) { if (ShowConnectorsInForeground) base.OnPaintContainedDesigners(e); FreeformActivityDesigner connectorContainer = ConnectionManager.GetConnectorContainer(this); if (connectorContainer != null && Activity != null && Activity.Site != null) { Region clipRegion = null; Region oldClipRegion = e.Graphics.Clip; try { if (oldClipRegion != null) { clipRegion = new Region(connectorContainer.Bounds); clipRegion.Intersect(e.ViewPort); e.Graphics.Clip = clipRegion; } //Lets draw all the connectors before the designers so that designers always overlap connectors foreach (Connector connector in connectorContainer.Connectors) { if (this == connector.RenderingOwner) connector.OnPaint(e); } } finally { if (oldClipRegion != null) { e.Graphics.Clip = oldClipRegion; clipRegion.Dispose(); } } } if (!ShowConnectorsInForeground) base.OnPaintContainedDesigners(e); } private Rectangle GetEnclosingRectangle() { Point leftTop = new Point(int.MaxValue, int.MaxValue), rightBottom = new Point(int.MinValue, int.MinValue); foreach (ActivityDesigner activityDesigner in ContainedDesigners) { if (activityDesigner.IsVisible) { leftTop.X = (activityDesigner.Bounds.Left < leftTop.X) ? activityDesigner.Bounds.Left : leftTop.X; leftTop.Y = (activityDesigner.Bounds.Top < leftTop.Y) ? activityDesigner.Bounds.Top : leftTop.Y; rightBottom.X = (rightBottom.X < activityDesigner.Bounds.Right) ? activityDesigner.Bounds.Right : rightBottom.X; rightBottom.Y = (rightBottom.Y < activityDesigner.Bounds.Bottom) ? activityDesigner.Bounds.Bottom : rightBottom.Y; } } //for the invoked workflow dont take connectors into account //this causes un-necessary growth of the workflow... if (this.InvokingDesigner == null) { foreach (Connector connector in Connectors) { leftTop.X = (connector.Bounds.Left < leftTop.X) ? connector.Bounds.Left : leftTop.X; leftTop.Y = (connector.Bounds.Top < leftTop.Y) ? connector.Bounds.Top : leftTop.Y; rightBottom.X = (rightBottom.X < connector.Bounds.Right) ? connector.Bounds.Right : rightBottom.X; rightBottom.Y = (rightBottom.Y < connector.Bounds.Bottom) ? connector.Bounds.Bottom : rightBottom.Y; } } Rectangle enclosingRectangle = Rectangle.Empty; if (leftTop.X != int.MaxValue && rightBottom.X != int.MinValue) { enclosingRectangle.X = leftTop.X; enclosingRectangle.Width = rightBottom.X - leftTop.X; } if (leftTop.Y != int.MaxValue && rightBottom.Y != int.MinValue) { enclosingRectangle.Y = leftTop.Y; enclosingRectangle.Height = rightBottom.Y - leftTop.Y; } if (!enclosingRectangle.IsEmpty) enclosingRectangle.Inflate(AutoSizeMargin); return enclosingRectangle; } internal bool CanUpdateZOrder(ActivityDesigner activityDesigner, ZOrder zorder) { bool canUpdateZOrder = false; CompositeActivityDesigner parentDesigner = this; ActivityDesigner childDesigner = activityDesigner; while (parentDesigner != null && childDesigner != null) { if (parentDesigner is FreeformActivityDesigner) { ReadOnlyCollection containedDesigners = parentDesigner.ContainedDesigners; if (containedDesigners.Count > 1 && containedDesigners[(zorder == ZOrder.Background) ? 0 : containedDesigners.Count - 1] != childDesigner) { canUpdateZOrder = true; break; } } childDesigner = parentDesigner; parentDesigner = parentDesigner.ParentDesigner; } return canUpdateZOrder; } private void UpdateZOrder(ActivityDesigner activityDesigner, ZOrder zorder) { IDesignerHost designerHost = GetService(typeof(IDesignerHost)) as IDesignerHost; DesignerTransaction transaction = null; if (designerHost != null) transaction = designerHost.CreateTransaction(DR.GetString(DR.ZOrderUndoDescription, activityDesigner.Text)); try { bool zOrderChanged = false; CompositeActivityDesigner parentDesigner = this; ActivityDesigner childDesigner = activityDesigner; while (parentDesigner != null && childDesigner != null) { if (parentDesigner is FreeformActivityDesigner) { ReadOnlyCollection containedDesigners = parentDesigner.ContainedDesigners; if (containedDesigners.Count > 1 && containedDesigners[(zorder == ZOrder.Background) ? 0 : containedDesigners.Count - 1] != childDesigner) { int moveIndex = (zorder == ZOrder.Background) ? 0 : containedDesigners.Count; parentDesigner.MoveActivities(new ConnectorHitTestInfo(this, HitTestLocations.Designer, moveIndex), new List (new Activity[] { childDesigner.Activity }).AsReadOnly()); zOrderChanged = true; } } childDesigner = parentDesigner; parentDesigner = parentDesigner.ParentDesigner; } if (zOrderChanged) Invalidate(); if (transaction != null) transaction.Commit(); } catch (Exception e) { if (transaction != null) transaction.Cancel(); throw e; } } private void EnsureDesignerExtender() { bool addExtender = true; IExtenderListService extenderListService = GetService(typeof(IExtenderListService)) as IExtenderListService; if (extenderListService != null) { foreach (IExtenderProvider extenderProvider in extenderListService.GetExtenderProviders()) { if (extenderProvider.GetType() == typeof(FreeFormDesignerPropertyExtender)) { addExtender = false; break; } } } if (addExtender) { IExtenderProviderService extenderProviderService = GetService(typeof(IExtenderProviderService)) as IExtenderProviderService; if (extenderProviderService != null) { extenderProviderService.AddExtenderProvider(new FreeFormDesignerPropertyExtender()); TypeDescriptor.Refresh(Activity); } } } #endregion #endregion #region Private Classes #region Class FreeFormConnectorSelectionGlyph // private sealed class FreeFormConnectorSelectionGlyph : ConnectorSelectionGlyph { internal FreeFormConnectorSelectionGlyph(int connectorIndex, bool isPrimarySelectionGlyph) : base(connectorIndex, isPrimarySelectionGlyph) { } public override Rectangle GetBounds(ActivityDesigner designer, bool activated) { //FreeformActivityDesigner connectorContainer = designer as FreeformActivityDesigner; //return (connectorContainer != null) ? DesignerGeometryHelper.RectangleFromLineSegments(connectorContainer.Connectors[this.connectorIndex].ConnectorSegments) : Rectangle.Empty; return Rectangle.Empty; } protected override void OnPaint(Graphics graphics, bool activated, AmbientTheme ambientTheme, ActivityDesigner designer) { /*IConnectorContainer connectorContainer = designer as IConnectorContainer; if (connectorContainer == null) return; Connector connector = connectorContainer[this.connectorIndex]; Rectangle[] grabHandles = new Rectangle[connector.Segments.Length]; for (int i = 0; i < connector.Segments.Length; i++) { grabHandles[i].X = connector.Segments[i].X - ambientTheme.SelectionSize.Width / 2; grabHandles[i].Y = connector.Segments[i].Y - ambientTheme.SelectionSize.Height / 2; grabHandles[i].Size = ambientTheme.SelectionSize; } ActivityDesignerPaint.DrawGrabHandles(graphics, grabHandles, this.isPrimarySelectionGlyph);*/ } public override bool IsPrimarySelection { get { return this.isPrimarySelectionGlyph; } } } #endregion #region Class FreeFormDesignerPropertyExtender [ProvideProperty("Location", typeof(Activity))] [ProvideProperty("Size", typeof(Activity))] private sealed class FreeFormDesignerPropertyExtender : IExtenderProvider { #region Properties [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [DesignOnly(true)] [MergableProperty(false)] [Browsable(false)] public Point GetLocation(Activity activity) { Point location = Point.Empty; ActivityDesigner designer = ActivityDesigner.GetDesigner(activity); if (designer != null) location = designer.Location; return location; } public void SetLocation(Activity activity, Point location) { ActivityDesigner designer = ActivityDesigner.GetDesigner(activity); if (designer != null) { FreeformActivityDesigner freeformDesigner = (designer.ParentDesigner != null) ? designer.ParentDesigner as FreeformActivityDesigner : designer as FreeformActivityDesigner; if (freeformDesigner != null) { designer.Location = location; if (freeformDesigner.AutoSize) freeformDesigner.PerformLayout(); } } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [DesignOnly(true)] [MergableProperty(false)] [Browsable(false)] public Size GetSize(Activity activity) { Size size = Size.Empty; ActivityDesigner designer = ActivityDesigner.GetDesigner(activity); if (designer != null) size = designer.Size; return size; } public void SetSize(Activity activity, Size size) { ActivityDesigner designer = ActivityDesigner.GetDesigner(activity); if (designer != null) { FreeformActivityDesigner freeformDesigner = (designer.ParentDesigner != null) ? designer.ParentDesigner as FreeformActivityDesigner : designer as FreeformActivityDesigner; if (freeformDesigner != null) { designer.Size = size; if (freeformDesigner.AutoSize) freeformDesigner.PerformLayout(); } } } #endregion bool IExtenderProvider.CanExtend(object extendee) { bool canExtend = false; Activity activity = extendee as Activity; if (activity != null) { ActivityDesigner designer = ActivityDesigner.GetDesigner(activity); if (designer != null) { FreeformActivityDesigner freeformDesigner = (designer.ParentDesigner != null) ? designer.ParentDesigner as FreeformActivityDesigner : designer as FreeformActivityDesigner; if (freeformDesigner != null) canExtend = true; } } return canExtend; } } #endregion #endregion } #endregion #region Class FreeFormDesignerVerbProvider internal sealed class FreeFormDesignerVerbProvider : IDesignerVerbProvider { #region IDesignerVerbProvider Members ActivityDesignerVerbCollection IDesignerVerbProvider.GetVerbs(ActivityDesigner activityDesigner) { ActivityDesignerVerbCollection verbs = new ActivityDesignerVerbCollection(); if (activityDesigner.ParentDesigner is FreeformActivityDesigner) { ActivityDesignerVerb verb = new ActivityDesignerVerb(activityDesigner, DesignerVerbGroup.Actions, DR.GetString(DR.BringToFront), new EventHandler(OnZOrderChanged), new EventHandler(OnZOrderStatusUpdate)); verb.Properties[DesignerUserDataKeys.ZOrderKey] = ZOrder.Foreground; verbs.Add(verb); verb = new ActivityDesignerVerb(activityDesigner, DesignerVerbGroup.Actions, DR.GetString(DR.SendToBack), new EventHandler(OnZOrderChanged), new EventHandler(OnZOrderStatusUpdate)); verb.Properties[DesignerUserDataKeys.ZOrderKey] = ZOrder.Background; verbs.Add(verb); } return verbs; } #endregion #region Helpers private void OnZOrderChanged(object sender, EventArgs e) { ActivityDesignerVerb designerVerb = sender as ActivityDesignerVerb; if (designerVerb != null && designerVerb.Properties.Contains(DesignerUserDataKeys.ZOrderKey)) { FreeformActivityDesigner freeformDesigner = designerVerb.ActivityDesigner.ParentDesigner as FreeformActivityDesigner; if (freeformDesigner != null) { if ((ZOrder)designerVerb.Properties[DesignerUserDataKeys.ZOrderKey] == ZOrder.Foreground) freeformDesigner.BringToFront(designerVerb.ActivityDesigner); else if ((ZOrder)designerVerb.Properties[DesignerUserDataKeys.ZOrderKey] == ZOrder.Background) freeformDesigner.SendToBack(designerVerb.ActivityDesigner); } } } private void OnZOrderStatusUpdate(object sender, EventArgs e) { ActivityDesignerVerb designerVerb = sender as ActivityDesignerVerb; if (designerVerb != null && designerVerb.Properties.Contains(DesignerUserDataKeys.ZOrderKey)) { FreeformActivityDesigner freeformDesigner = designerVerb.ActivityDesigner.ParentDesigner as FreeformActivityDesigner; if (freeformDesigner != null) designerVerb.Enabled = freeformDesigner.CanUpdateZOrder(designerVerb.ActivityDesigner, (ZOrder)designerVerb.Properties[DesignerUserDataKeys.ZOrderKey]); } } #endregion } #endregion } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. namespace System.Workflow.ComponentModel.Design { using System; using System.IO; using System.Drawing; using System.Diagnostics; using System.Collections; using System.Windows.Forms; using System.ComponentModel; using System.Drawing.Drawing2D; using System.Collections.Generic; using System.ComponentModel.Design; using System.Collections.ObjectModel; using System.Workflow.ComponentModel.Design; using System.ComponentModel.Design.Serialization; using System.Workflow.ComponentModel.Serialization; #region Interface IConnectableDesigner internal interface IConnectableDesigner { bool CanConnect(ConnectionPoint source, ConnectionPoint target); void OnConnected(ConnectionPoint source, ConnectionPoint target); } #endregion #region Enum ZOrder internal enum ZOrder { Foreground = 1, Background = 2 } #endregion #region Class FreeformActivityDesigner // //By default this designer will use the CompositeActivityDesigner theme [DesignerSerializer(typeof(FreeformActivityDesignerLayoutSerializer), typeof(WorkflowMarkupSerializer))] public class FreeformActivityDesigner : CompositeActivityDesigner { #region Class FreeformDesignerAccessibleObject internal class FreeformDesignerAccessibleObject : CompositeDesignerAccessibleObject { public FreeformDesignerAccessibleObject(FreeformActivityDesigner activityDesigner) : base(activityDesigner) { } public override AccessibleObject GetChild(int index) { FreeformActivityDesigner designer = (FreeformActivityDesigner)this.ActivityDesigner; if (designer.ShowConnectorsInForeground) { int connectorsCount = designer.Connectors.Count; if (index < connectorsCount) return designer.Connectors[index].AccessibilityObject; else return designer.ContainedDesigners[index - connectorsCount].AccessibilityObject; } else { int containedDesignersCount = designer.ContainedDesigners.Count; if (index < containedDesignersCount) return designer.ContainedDesigners[index].AccessibilityObject; else return designer.Connectors[index - containedDesignersCount].AccessibilityObject; } } public override int GetChildCount() { FreeformActivityDesigner designer = (FreeformActivityDesigner)this.ActivityDesigner; int count = base.GetChildCount() + designer.Connectors.Count; return count; } } #endregion Class FreeformDesignerAccessibleObject #region Members internal static Size DefaultAutoSizeMargin = new Size(40, 40); private FreeformDesignerAccessibleObject accessibilityObject; private bool autoSize = true; private AutoSizeMode autoSizeMode = AutoSizeMode.GrowOnly; private Size autoSizeMargin = FreeformActivityDesigner.DefaultAutoSizeMargin; private bool enableUserDrawnConnectors = true; private List connectors = new List (); private bool retainContainedDesignerLocations = false; public event ConnectorEventHandler ConnectorAdded; public event ConnectorEventHandler ConnectorChanged; public event ConnectorEventHandler ConnectorRemoved; #endregion #region Construction / Destruction public FreeformActivityDesigner() { } #endregion #region Properties #region Public Properties public override AccessibleObject AccessibilityObject { get { if (this.accessibilityObject == null) this.accessibilityObject = new FreeformDesignerAccessibleObject(this); return this.accessibilityObject; } } /// /// Gets or Sets value indicating if the designer will be resized automatically based on the child designers /// [DefaultValue(true)] public bool AutoSize { get { return this.autoSize; } set { if (this.autoSize == value) return; this.autoSize = value; PerformLayout(); } } ////// Gets or Sets the auto sizing mode /// [DefaultValue(AutoSizeMode.GrowOnly)] public AutoSizeMode AutoSizeMode { get { return this.autoSizeMode; } set { if (this.autoSizeMode == value) return; this.autoSizeMode = value; PerformLayout(); } } ////// Gets the margins left around the contained designers when autosizing /// public Size AutoSizeMargin { get { Size margin = this.autoSizeMargin; if (WorkflowTheme.CurrentTheme.AmbientTheme.ShowGrid) { Size gridSize = WorkflowTheme.CurrentTheme.AmbientTheme.GridSize; margin.Width += gridSize.Width / 2; margin.Height += gridSize.Height / 2; } return margin; } set { if (this.autoSizeMargin == value) return; this.autoSizeMargin = value; PerformLayout(); } } ////// Allows user to drag and draw connectors on the design surface /// [DefaultValue(true)] public bool EnableUserDrawnConnectors { get { return (this.enableUserDrawnConnectors && IsEditable); } set { this.enableUserDrawnConnectors = value; } } public override bool CanExpandCollapse { get { return false; } } public override object FirstSelectableObject { get { IListchilddesigners = ContainedDesigners; return (childdesigners.Count > 0) ? childdesigners[0].Activity : null; } } public override object LastSelectableObject { get { IList childdesigners = ContainedDesigners; return (childdesigners.Count > 0) ? childdesigners[childdesigners.Count - 1].Activity : null; } } public override Size MinimumSize { get { //Now go thru all the activity designers and consider the bottom coordinate + selection size + page separator as the min size Size minimumSize = base.MinimumSize; if (Activity != null && ((IComponent)Activity).Site != null && !(ParentDesigner is FreeformActivityDesigner)) { minimumSize.Width *= 4; minimumSize.Height *= 4; } //If the designer is root designer and not inlined then we should occupy the area of workflow view if (IsRootDesigner && InvokingDesigner == null) { WorkflowView workflowView = ParentView; minimumSize.Width = Math.Max(minimumSize.Width, workflowView.ViewPortSize.Width - 2 * WorkflowRootLayout.Separator.Width); minimumSize.Height = Math.Max(minimumSize.Height, workflowView.ViewPortSize.Height - 2 * WorkflowRootLayout.Separator.Height); } if (AutoSize) { Rectangle childRectangle = GetEnclosingRectangle(); if (!childRectangle.IsEmpty) { minimumSize.Width = Math.Max(minimumSize.Width, childRectangle.Width); minimumSize.Height = Math.Max(minimumSize.Height, childRectangle.Height); } } return minimumSize; } } public override Point Location { get { return base.Location; } set { if (Location == value) return; //Please note that we require this logic to maintain the contained designer location when //resizing the designer ReadOnlyCollection containedDesigners = ContainedDesigners; List containedDesignerLocations = new List (); if (this.retainContainedDesignerLocations) { foreach (ActivityDesigner activityDesigner in containedDesigners) containedDesignerLocations.Add(activityDesigner.Location); } else { Size moveDelta = new Size(value.X - base.Location.X, value.Y - base.Location.Y); FreeformActivityDesigner freeFormActivityDesigner = this; Collection connectors = new Collection (); while (freeFormActivityDesigner != null) { foreach (Connector connector in freeFormActivityDesigner.Connectors) if (connector.RenderingOwner == this) connectors.Add(connector); freeFormActivityDesigner = freeFormActivityDesigner.ParentDesigner as FreeformActivityDesigner; } foreach (Connector connector in connectors) { connector.Offset(moveDelta); } } base.Location = value; if (this.retainContainedDesignerLocations && containedDesigners.Count == containedDesignerLocations.Count) { for (int i = 0; i < containedDesigners.Count; i++) containedDesigners[i].Location = containedDesignerLocations[i]; } Invalidate(); } } /// /// Returns collection of connectors /// public ReadOnlyCollectionConnectors { get { return this.connectors.AsReadOnly(); } } #endregion #region Protected Properties /// /// Get the value indicating if the connectors are drawn in the forground /// protected virtual bool ShowConnectorsInForeground { get { return false; } } protected internal override bool EnableVisualResizing { get { if (AutoSize && AutoSizeMode == AutoSizeMode.GrowAndShrink) return false; else return true; } } protected internal override ActivityDesignerGlyphCollection Glyphs { get { ActivityDesignerGlyphCollection glyphs = new ActivityDesignerGlyphCollection(); glyphs.AddRange(base.Glyphs); //Now go thru all the designers and for the designers which are connectable, return connection glyphs //Also return the move glyphs for movable designer ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService; if (selectionService != null) { foreach (object selectedObject in selectionService.GetSelectedComponents()) { ConnectorHitTestInfo connectorHitInfo = selectedObject as ConnectorHitTestInfo; if (connectorHitInfo != null && connectorHitInfo.AssociatedDesigner == this) glyphs.Add(new FreeFormConnectorSelectionGlyph(connectorHitInfo.MapToIndex(), (connectorHitInfo == selectionService.PrimarySelection))); } } return glyphs; } } #endregion #region Private Properties internal override WorkflowLayout SupportedLayout { get { return new WorkflowRootLayout(Activity.Site); } } #region Properties used during serialization only //NOTE THAT THIS WILL ONLY BE USED FOR SERIALIZATION PURPOSES [EditorBrowsable(EditorBrowsableState.Never)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] internal ListDesignerConnectors { get { List connectors = new List (this.connectors); return connectors; } } #endregion #endregion #endregion #region Methods #region Public Methods /// /// Adds connector to the designer /// /// Connector to add public Connector AddConnector(ConnectionPoint source, ConnectionPoint target) { if (source == null) throw new ArgumentNullException("source"); if (source.AssociatedDesigner == null) throw new ArgumentException("source", SR.GetString(SR.Error_AssociatedDesignerMissing)); if (target == null) throw new ArgumentNullException("target"); if (target.AssociatedDesigner == null) throw new ArgumentException("target", SR.GetString(SR.Error_AssociatedDesignerMissing)); //This check can be eliminated if it slows down connections, this is just to ensure we are adding connectors //to correct activity designer FreeformActivityDesigner connectorContainer = ConnectionManager.GetConnectorContainer(source.AssociatedDesigner); if (this != connectorContainer) throw new InvalidOperationException(DR.GetString(DR.Error_AddConnector1)); if ((Activity != source.AssociatedDesigner.Activity && !Helpers.IsChildActivity(Activity as CompositeActivity, source.AssociatedDesigner.Activity)) || (Activity != target.AssociatedDesigner.Activity && !Helpers.IsChildActivity(Activity as CompositeActivity, target.AssociatedDesigner.Activity))) throw new ArgumentException(DR.GetString(DR.Error_AddConnector2)); Connector connector = CreateConnector(source, target); if (connector != null) { if (this.connectors.Contains(connector)) throw new InvalidOperationException(DR.GetString(DR.Error_AddConnector3)); this.connectors.Add(connector); connector.SetParent(this); OnConnectorAdded(new ConnectorEventArgs(connector)); } PerformLayout(); return connector; } ////// Removes connector from the designer /// /// Connector to remove public void RemoveConnector(Connector connector) { if (connector == null) throw new ArgumentNullException("connector"); if (this.connectors.Contains(connector)) { OnConnectorRemoved(new ConnectorEventArgs(connector)); connector.SetParent(null); this.connectors.Remove(connector); } } ////// Sends the contained designer to back of z-order /// /// Designer to send to back public void SendToBack(ActivityDesigner containedDesigner) { if (containedDesigner == null) throw new ArgumentNullException("containedDesigner"); if (!ContainedDesigners.Contains(containedDesigner)) throw new ArgumentException(DR.GetString(DR.InvalidDesignerSpecified, "containedDesigner")); UpdateZOrder(containedDesigner, ZOrder.Background); } ////// Brings the contained designer to top of z-order /// /// Designer to bring to front public void BringToFront(ActivityDesigner containedDesigner) { if (containedDesigner == null) throw new ArgumentNullException("containedDesigner"); if (!ContainedDesigners.Contains(containedDesigner)) throw new ArgumentException(DR.GetString(DR.InvalidDesignerSpecified, "containedDesigner")); UpdateZOrder(containedDesigner, ZOrder.Foreground); } ////// Moves specified contained designer to specified location inside designer /// /// Designer to move /// Location to move to. public void MoveContainedDesigner(ActivityDesigner containedDesigner, Point newLocation) { if (containedDesigner == null) throw new ArgumentNullException("containedDesigner"); if (!ContainedDesigners.Contains(containedDesigner)) throw new ArgumentException(DR.GetString(DR.InvalidDesignerSpecified, "containedDesigner")); FreeformActivityDesigner.SetDesignerBounds(containedDesigner, new Rectangle(newLocation, containedDesigner.Size)); PerformLayout(); Invalidate(); } ////// Resizes specified contained designer to specified size /// /// Designer to resize /// Size to resize it to public void ResizeContainedDesigner(ActivityDesigner containedDesigner, Size newSize) { if (containedDesigner == null) throw new ArgumentNullException("containedDesigner"); if (!ContainedDesigners.Contains(containedDesigner)) throw new ArgumentException(DR.GetString(DR.InvalidDesignerSpecified, "containedDesigner")); FreeformActivityDesigner.SetDesignerBounds(containedDesigner, new Rectangle(containedDesigner.Location, newSize)); PerformLayout(); } public override HitTestInfo HitTest(Point point) { HitTestInfo hitInfo = base.HitTest(point); //First check that if the drag drop is in progress and the drop operation has been initiated based on //A child designer then if the queried point is also on the drop initiated designer then we return freeform //designer as the designer where hittest occured ReadOnlyCollectioncontainedDesigners = ContainedDesigners; WorkflowView workflowView = ParentView; DragDropManager dragDropManager = GetService(typeof(DragDropManager)) as DragDropManager; if (workflowView != null && dragDropManager != null && workflowView.DragDropInProgress && hitInfo.AssociatedDesigner != null && dragDropManager.DraggedActivities.Contains(hitInfo.AssociatedDesigner.Activity) && hitInfo.AssociatedDesigner.Bounds.Contains(point)) { if (Activity == hitInfo.AssociatedDesigner.Activity) return HitTestInfo.Nowhere; else if (containedDesigners.Contains(hitInfo.AssociatedDesigner)) return new HitTestInfo(this, HitTestLocations.Designer); } //Now try going through the connectors if (!(hitInfo is ConnectionPointHitTestInfo) && (hitInfo.HitLocation == HitTestLocations.None || hitInfo.AssociatedDesigner == this || ShowConnectorsInForeground)) { //Now go thru all the connectors and try to select them for (int i = 0; i < this.connectors.Count; i++) { if (this.connectors[i].HitTest(point)) return new ConnectorHitTestInfo(this, HitTestLocations.Designer | HitTestLocations.Connector, i); } } return hitInfo; } //activities being moved within the same container private List movedActivities = null; private List MovingActivities { get { if(this.movedActivities == null) this.movedActivities = new List (); return this.movedActivities; } } public override void MoveActivities(HitTestInfo moveLocation, ReadOnlyCollection activitiesToMove) { if (moveLocation == null) throw new ArgumentNullException("moveLocation"); if (activitiesToMove == null) throw new ArgumentNullException("activitiesToMove"); FreeformActivityDesigner connectorContainer = ConnectionManager.GetConnectorContainer(this); try { connectorContainer.MovingActivities.Clear(); if (connectorContainer != null && connectorContainer.Connectors.Count > 0) { foreach (Activity movingActivity in activitiesToMove) { ActivityDesigner designerToMove = ActivityDesigner.GetDesigner(movingActivity); FreeformActivityDesigner topMostParentDesigner = ConnectionManager.GetConnectorContainer(designerToMove); if (topMostParentDesigner == connectorContainer) connectorContainer.MovingActivities.Add(designerToMove); } } base.MoveActivities(moveLocation, activitiesToMove); } finally { connectorContainer.MovingActivities.Clear(); } } public override object GetNextSelectableObject(object current, DesignerNavigationDirection navigate) { object nextObject = null; ArrayList activityDesigners = new ArrayList(ContainedDesigners); ActivityDesigner activityDesigner = (current is Activity) ? ActivityDesigner.GetDesigner(current as Activity) : ActivityDesigner.GetParentDesigner(current); int index = (activityDesigner != null) ? activityDesigners.IndexOf(activityDesigner) : -1; if ((navigate == DesignerNavigationDirection.Left || navigate == DesignerNavigationDirection.Up) && index >= 0 && index < activityDesigners.Count) nextObject = ((ActivityDesigner)activityDesigners[(index > 0) ? index - 1 : activityDesigners.Count - 1]).Activity; else if ((navigate == DesignerNavigationDirection.Right || navigate == DesignerNavigationDirection.Down) && index <= activityDesigners.Count - 1) nextObject = ((ActivityDesigner)activityDesigners[(index < activityDesigners.Count - 1) ? index + 1 : 0]).Activity; return nextObject; } #endregion #region Protected Methods protected override void Initialize(Activity activity) { base.Initialize(activity); //We only add the designer property extender here, it will be removed when the design surface is //destroyed EnsureDesignerExtender(); } protected override void Dispose(bool disposing) { //Dispose the connectors for (int i = 0; i < this.connectors.Count; i++) ((IDisposable)this.connectors[i]).Dispose(); this.connectors.Clear(); base.Dispose(disposing); } // protected override void OnContainedActivitiesChanging(ActivityCollectionChangeEventArgs listChangeArgs) { base.OnContainedActivitiesChanging(listChangeArgs); if (listChangeArgs.Action == ActivityCollectionChangeAction.Remove) { FreeformActivityDesigner connectorContainer = ConnectionManager.GetConnectorContainer(this); List connectorsToDelete = new List (); //check if the removed designer is being moved within the same container //in this case dont remove the connector... ActivityDesigner activityDesigner = this; while (activityDesigner != null) { FreeformActivityDesigner freeFormDesigner = activityDesigner as FreeformActivityDesigner; if (freeFormDesigner != null && freeFormDesigner.Connectors.Count > 0) { foreach (Activity activityToRemove in listChangeArgs.RemovedItems) { ActivityDesigner designerToRemove = ActivityDesigner.GetDesigner(activityToRemove); //if the designer is being moved within the same container, ignore it //otherwise remove all related connectors if (!connectorContainer.MovingActivities.Contains(designerToRemove)) { foreach (Connector connector in freeFormDesigner.Connectors) { if (designerToRemove == connector.Source.AssociatedDesigner || designerToRemove == connector.Target.AssociatedDesigner) connectorsToDelete.Add(connector); } } } } activityDesigner = activityDesigner.ParentDesigner; } foreach (Connector connectorToDelete in connectorsToDelete) { connectorToDelete.ParentDesigner.RemoveConnector(connectorToDelete); ((IDisposable)connectorToDelete).Dispose(); } } } /// /// Creates the connector between specified connection points. /// /// Source connection point /// Target connection point ///protected internal virtual Connector CreateConnector(ConnectionPoint source, ConnectionPoint target) { return new Connector(source, target); } /// /// Called to check if contained designers can be connected /// /// Source connection point /// Target connection point ///protected internal virtual bool CanConnectContainedDesigners(ConnectionPoint source, ConnectionPoint target) { return (((IConnectableDesigner)source.AssociatedDesigner).CanConnect(source, target) && ((IConnectableDesigner)target.AssociatedDesigner).CanConnect(source, target)); } /// /// Called when the connection between contained designers is established /// /// Source connection point /// Target connection point protected internal virtual void OnContainedDesignersConnected(ConnectionPoint source, ConnectionPoint target) { ((IConnectableDesigner)source.AssociatedDesigner).OnConnected(source, target); ((IConnectableDesigner)target.AssociatedDesigner).OnConnected(source, target); } ////// Called to find if the contained designer can be visually resized by the user /// /// Designer to visually resize ///True if the designer can be visually resize, false otherwise protected internal virtual bool CanResizeContainedDesigner(ActivityDesigner containedDesigner) { return (containedDesigner is FreeformActivityDesigner); } ////// Called when a new connector has been added in the freeform designer /// /// Event args containing connector protected virtual void OnConnectorAdded(ConnectorEventArgs e) { if (ConnectorAdded != null) ConnectorAdded(this, e); } ////// Called when the user changed the end points of the connector /// /// protected internal virtual void OnConnectorChanged(ConnectorEventArgs e) { if (ConnectorChanged != null) ConnectorChanged(this, e); } protected virtual void OnConnectorRemoved(ConnectorEventArgs e) { if (ConnectorRemoved != null) ConnectorRemoved(this, e); } protected override void OnLayoutPosition(ActivityDesignerLayoutEventArgs e) { base.OnLayoutPosition(e); if (AutoSize) { Point newLocation = Location; Rectangle childRectangle = GetEnclosingRectangle(); if (!childRectangle.IsEmpty) { if (AutoSizeMode == AutoSizeMode.GrowOnly) { newLocation.X = Math.Min(newLocation.X, childRectangle.Left); newLocation.Y = Math.Min(newLocation.Y, childRectangle.Top); } else { newLocation = childRectangle.Location; } } this.retainContainedDesignerLocations = true; Location = newLocation; this.retainContainedDesignerLocations = false; } foreach (Connector connector in this.connectors) connector.OnLayout(e); } protected override Size OnLayoutSize(ActivityDesignerLayoutEventArgs e) { Rectangle bounds = Bounds; Size size = bounds.Size; base.OnLayoutSize(e); if (AutoSize) { if (AutoSizeMode == AutoSizeMode.GrowOnly) { Rectangle childRectangle = GetEnclosingRectangle(); if (!childRectangle.IsEmpty) { size.Width += Math.Max(bounds.Left - childRectangle.Left, 0); size.Width += Math.Max(childRectangle.Right - bounds.Right, 0); size.Height += Math.Max(bounds.Top - childRectangle.Top, 0); size.Height += Math.Max(childRectangle.Bottom - bounds.Bottom, 0); } } else { size = MinimumSize; } } return size; } protected override void OnThemeChange(ActivityDesignerTheme newTheme) { base.OnThemeChange(newTheme); if (WorkflowTheme.CurrentTheme.AmbientTheme.ShowGrid) { foreach (ActivityDesigner containedDesigner in ContainedDesigners) containedDesigner.Location = DesignerHelpers.SnapToGrid(containedDesigner.Location); PerformLayout(); } } protected override void OnDragOver(ActivityDragEventArgs e) { bool ctrlKeyPressed = ((e.KeyState & 8) == 8); if (ctrlKeyPressed && (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) e.Effect = DragDropEffects.Copy; else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move) e.Effect = DragDropEffects.Move; } protected override void OnDragDrop(ActivityDragEventArgs e) { //Set the correct drag drop effect bool ctrlKeyPressed = ((e.KeyState & 8) == 8); if (ctrlKeyPressed && (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) e.Effect = DragDropEffects.Copy; else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move) e.Effect = DragDropEffects.Move; //Now there can be set of activities which are inserted and set of activities which are moved //So first lets get the list of activities which need to be inserted ListactivitiesToInsert = new List (); List newActivities = new List (); foreach (Activity activity in e.Activities) { if (activity.Site == null || activity.Parent != Activity) activitiesToInsert.Add(activity); if (activity.Site == null) newActivities.Add(activity); } //If the component are sited then that means that we are inserting it if (activitiesToInsert.Count > 0) CompositeActivityDesigner.InsertActivities(this, new ConnectorHitTestInfo(this, HitTestLocations.Designer, ((CompositeActivity)Activity).Activities.Count), activitiesToInsert.AsReadOnly(), SR.GetString(SR.DragDropActivities)); Point dropPoint = new Point(e.X, e.Y); Point[] movedLocations = FreeFormDragDropManager.GetDesignerLocations(e.DragInitiationPoint, dropPoint, e.Activities); if (movedLocations.Length == e.Activities.Count) { for (int i = 0; i < e.Activities.Count; i++) { ActivityDesigner designerToMove = ActivityDesigner.GetDesigner(e.Activities[i]); if (designerToMove != null) { Point location = (newActivities.Contains(designerToMove.Activity)) ? dropPoint : movedLocations[i]; MoveContainedDesigner(designerToMove, location); } } } else { Debug.Assert(false); } } public override void InsertActivities(HitTestInfo insertLocation, ReadOnlyCollection activitiesToInsert) { base.InsertActivities(insertLocation, activitiesToInsert); //Now go through all the designers for activities and make sure that if their locations are 0,0 then we set the //locations at Location.X + AutoSizeMargin if (AutoSize) { Size autoSizeMargin = AutoSizeMargin; Point location = Location; foreach (Activity activity in activitiesToInsert) { ActivityDesigner designer = ActivityDesigner.GetDesigner(activity); if (designer.Location.IsEmpty) designer.Location = new Point(location.X + autoSizeMargin.Width, location.Y + autoSizeMargin.Height); } } } protected override void OnResizing(ActivityDesignerResizeEventArgs e) { //If we are in AutoSize mode with grow and shrink option then dont allow resizing if (AutoSize) { if (AutoSizeMode == AutoSizeMode.GrowOnly) { Rectangle minRectangle = GetEnclosingRectangle(); if (!minRectangle.IsEmpty) { Rectangle bounds = Rectangle.Empty; bounds.X = Math.Min(minRectangle.Left, e.Bounds.Left); bounds.Y = Math.Min(minRectangle.Top, e.Bounds.Top); bounds.Width = Math.Max(minRectangle.Right - bounds.Left, e.Bounds.Right - bounds.Left); bounds.Height = Math.Max(minRectangle.Bottom - bounds.Top, e.Bounds.Bottom - bounds.Top); if (bounds != e.Bounds) e = new ActivityDesignerResizeEventArgs(e.SizingEdge, bounds); } } else { PerformLayout(); } } this.retainContainedDesignerLocations = true; base.OnResizing(e); this.retainContainedDesignerLocations = false; } protected override void OnKeyDown(KeyEventArgs e) { if (e == null) throw new ArgumentNullException("e"); ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService; object selectedObject = (selectionService != null) ? selectionService.PrimarySelection : null; if (selectedObject == null) return; List topLevelActivities = new List (Helpers.GetTopLevelActivities(selectionService.GetSelectedComponents())); if (e.KeyCode == Keys.Left || e.KeyCode == Keys.Right || e.KeyCode == Keys.Up || e.KeyCode == Keys.Down) { Size direction = Size.Empty; const int step = 5; if (e.KeyCode == Keys.Left) direction = new Size(-step, 0); else if (e.KeyCode == Keys.Right) direction = new Size(step, 0); else if (e.KeyCode == Keys.Up) direction = new Size(0, -step); else if (e.KeyCode == Keys.Down) direction = new Size(0, step); foreach (Activity selectedActivity in topLevelActivities) { //move designer by 'direction' ActivityDesigner designer = ActivityDesigner.GetDesigner(selectedActivity); if (designer != null) { //refresh designer area both before and after move ParentView.InvalidateClientRectangle(new Rectangle(designer.Location, designer.Size)); designer.Location += direction; ParentView.InvalidateClientRectangle(new Rectangle(designer.Location, designer.Size)); } } //update layout to grow the parent if needed after all designers have been moved // PerformLayout(); e.Handled = true; } else if (e.KeyCode == Keys.Delete) { //if there is a connector selected, delete it ICollection components = selectionService.GetSelectedComponents(); foreach (object component in components) { ConnectorHitTestInfo connector = component as ConnectorHitTestInfo; if (connector != null) { FreeformActivityDesigner freeformDesigner = connector.AssociatedDesigner as FreeformActivityDesigner; if (freeformDesigner != null) { ReadOnlyCollection connectors = freeformDesigner.Connectors; int connectorIndex = connector.MapToIndex(); if (connectorIndex < connectors.Count) { selectionService.SetSelectedComponents(new object[] { connector }, SelectionTypes.Remove); freeformDesigner.RemoveConnector(connectors[connectorIndex]); object nextSelectableObject = freeformDesigner; if (connectors.Count > 0) nextSelectableObject = new ConnectorHitTestInfo(freeformDesigner, HitTestLocations.Connector | HitTestLocations.Designer, (connectorIndex > 0) ? connectorIndex - 1 : connectorIndex); selectionService.SetSelectedComponents(new object[] { nextSelectableObject }, SelectionTypes.Replace); } } } } e.Handled = true; } if(!e.Handled) { //let the base handle all other keys including tabs base.OnKeyDown(e); } } #endregion #region Private Methods internal static void SetDesignerBounds(ActivityDesigner designer, Rectangle bounds) { if (designer == null || designer.Activity == null || designer.Activity.Site == null) return; PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(designer); PropertyDescriptor sizeProperty = (properties != null) ? properties["Size"] : null; if (sizeProperty != null) sizeProperty.SetValue(designer.Activity, bounds.Size); else designer.Size = bounds.Size; PropertyDescriptor locationProperty = (properties != null) ? properties["Location"] : null; if (locationProperty != null) locationProperty.SetValue(designer.Activity, bounds.Location); else designer.Location = bounds.Location; WorkflowView workflowView = designer.Activity.Site.GetService(typeof(WorkflowView)) as WorkflowView; if (workflowView != null) { if (designer.ParentDesigner != null) workflowView.InvalidateLogicalRectangle(designer.ParentDesigner.Bounds); else workflowView.Invalidate(); } } internal override void OnPaintContainedDesigners(ActivityDesignerPaintEventArgs e) { if (ShowConnectorsInForeground) base.OnPaintContainedDesigners(e); FreeformActivityDesigner connectorContainer = ConnectionManager.GetConnectorContainer(this); if (connectorContainer != null && Activity != null && Activity.Site != null) { Region clipRegion = null; Region oldClipRegion = e.Graphics.Clip; try { if (oldClipRegion != null) { clipRegion = new Region(connectorContainer.Bounds); clipRegion.Intersect(e.ViewPort); e.Graphics.Clip = clipRegion; } //Lets draw all the connectors before the designers so that designers always overlap connectors foreach (Connector connector in connectorContainer.Connectors) { if (this == connector.RenderingOwner) connector.OnPaint(e); } } finally { if (oldClipRegion != null) { e.Graphics.Clip = oldClipRegion; clipRegion.Dispose(); } } } if (!ShowConnectorsInForeground) base.OnPaintContainedDesigners(e); } private Rectangle GetEnclosingRectangle() { Point leftTop = new Point(int.MaxValue, int.MaxValue), rightBottom = new Point(int.MinValue, int.MinValue); foreach (ActivityDesigner activityDesigner in ContainedDesigners) { if (activityDesigner.IsVisible) { leftTop.X = (activityDesigner.Bounds.Left < leftTop.X) ? activityDesigner.Bounds.Left : leftTop.X; leftTop.Y = (activityDesigner.Bounds.Top < leftTop.Y) ? activityDesigner.Bounds.Top : leftTop.Y; rightBottom.X = (rightBottom.X < activityDesigner.Bounds.Right) ? activityDesigner.Bounds.Right : rightBottom.X; rightBottom.Y = (rightBottom.Y < activityDesigner.Bounds.Bottom) ? activityDesigner.Bounds.Bottom : rightBottom.Y; } } //for the invoked workflow dont take connectors into account //this causes un-necessary growth of the workflow... if (this.InvokingDesigner == null) { foreach (Connector connector in Connectors) { leftTop.X = (connector.Bounds.Left < leftTop.X) ? connector.Bounds.Left : leftTop.X; leftTop.Y = (connector.Bounds.Top < leftTop.Y) ? connector.Bounds.Top : leftTop.Y; rightBottom.X = (rightBottom.X < connector.Bounds.Right) ? connector.Bounds.Right : rightBottom.X; rightBottom.Y = (rightBottom.Y < connector.Bounds.Bottom) ? connector.Bounds.Bottom : rightBottom.Y; } } Rectangle enclosingRectangle = Rectangle.Empty; if (leftTop.X != int.MaxValue && rightBottom.X != int.MinValue) { enclosingRectangle.X = leftTop.X; enclosingRectangle.Width = rightBottom.X - leftTop.X; } if (leftTop.Y != int.MaxValue && rightBottom.Y != int.MinValue) { enclosingRectangle.Y = leftTop.Y; enclosingRectangle.Height = rightBottom.Y - leftTop.Y; } if (!enclosingRectangle.IsEmpty) enclosingRectangle.Inflate(AutoSizeMargin); return enclosingRectangle; } internal bool CanUpdateZOrder(ActivityDesigner activityDesigner, ZOrder zorder) { bool canUpdateZOrder = false; CompositeActivityDesigner parentDesigner = this; ActivityDesigner childDesigner = activityDesigner; while (parentDesigner != null && childDesigner != null) { if (parentDesigner is FreeformActivityDesigner) { ReadOnlyCollection containedDesigners = parentDesigner.ContainedDesigners; if (containedDesigners.Count > 1 && containedDesigners[(zorder == ZOrder.Background) ? 0 : containedDesigners.Count - 1] != childDesigner) { canUpdateZOrder = true; break; } } childDesigner = parentDesigner; parentDesigner = parentDesigner.ParentDesigner; } return canUpdateZOrder; } private void UpdateZOrder(ActivityDesigner activityDesigner, ZOrder zorder) { IDesignerHost designerHost = GetService(typeof(IDesignerHost)) as IDesignerHost; DesignerTransaction transaction = null; if (designerHost != null) transaction = designerHost.CreateTransaction(DR.GetString(DR.ZOrderUndoDescription, activityDesigner.Text)); try { bool zOrderChanged = false; CompositeActivityDesigner parentDesigner = this; ActivityDesigner childDesigner = activityDesigner; while (parentDesigner != null && childDesigner != null) { if (parentDesigner is FreeformActivityDesigner) { ReadOnlyCollection containedDesigners = parentDesigner.ContainedDesigners; if (containedDesigners.Count > 1 && containedDesigners[(zorder == ZOrder.Background) ? 0 : containedDesigners.Count - 1] != childDesigner) { int moveIndex = (zorder == ZOrder.Background) ? 0 : containedDesigners.Count; parentDesigner.MoveActivities(new ConnectorHitTestInfo(this, HitTestLocations.Designer, moveIndex), new List (new Activity[] { childDesigner.Activity }).AsReadOnly()); zOrderChanged = true; } } childDesigner = parentDesigner; parentDesigner = parentDesigner.ParentDesigner; } if (zOrderChanged) Invalidate(); if (transaction != null) transaction.Commit(); } catch (Exception e) { if (transaction != null) transaction.Cancel(); throw e; } } private void EnsureDesignerExtender() { bool addExtender = true; IExtenderListService extenderListService = GetService(typeof(IExtenderListService)) as IExtenderListService; if (extenderListService != null) { foreach (IExtenderProvider extenderProvider in extenderListService.GetExtenderProviders()) { if (extenderProvider.GetType() == typeof(FreeFormDesignerPropertyExtender)) { addExtender = false; break; } } } if (addExtender) { IExtenderProviderService extenderProviderService = GetService(typeof(IExtenderProviderService)) as IExtenderProviderService; if (extenderProviderService != null) { extenderProviderService.AddExtenderProvider(new FreeFormDesignerPropertyExtender()); TypeDescriptor.Refresh(Activity); } } } #endregion #endregion #region Private Classes #region Class FreeFormConnectorSelectionGlyph // private sealed class FreeFormConnectorSelectionGlyph : ConnectorSelectionGlyph { internal FreeFormConnectorSelectionGlyph(int connectorIndex, bool isPrimarySelectionGlyph) : base(connectorIndex, isPrimarySelectionGlyph) { } public override Rectangle GetBounds(ActivityDesigner designer, bool activated) { //FreeformActivityDesigner connectorContainer = designer as FreeformActivityDesigner; //return (connectorContainer != null) ? DesignerGeometryHelper.RectangleFromLineSegments(connectorContainer.Connectors[this.connectorIndex].ConnectorSegments) : Rectangle.Empty; return Rectangle.Empty; } protected override void OnPaint(Graphics graphics, bool activated, AmbientTheme ambientTheme, ActivityDesigner designer) { /*IConnectorContainer connectorContainer = designer as IConnectorContainer; if (connectorContainer == null) return; Connector connector = connectorContainer[this.connectorIndex]; Rectangle[] grabHandles = new Rectangle[connector.Segments.Length]; for (int i = 0; i < connector.Segments.Length; i++) { grabHandles[i].X = connector.Segments[i].X - ambientTheme.SelectionSize.Width / 2; grabHandles[i].Y = connector.Segments[i].Y - ambientTheme.SelectionSize.Height / 2; grabHandles[i].Size = ambientTheme.SelectionSize; } ActivityDesignerPaint.DrawGrabHandles(graphics, grabHandles, this.isPrimarySelectionGlyph);*/ } public override bool IsPrimarySelection { get { return this.isPrimarySelectionGlyph; } } } #endregion #region Class FreeFormDesignerPropertyExtender [ProvideProperty("Location", typeof(Activity))] [ProvideProperty("Size", typeof(Activity))] private sealed class FreeFormDesignerPropertyExtender : IExtenderProvider { #region Properties [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [DesignOnly(true)] [MergableProperty(false)] [Browsable(false)] public Point GetLocation(Activity activity) { Point location = Point.Empty; ActivityDesigner designer = ActivityDesigner.GetDesigner(activity); if (designer != null) location = designer.Location; return location; } public void SetLocation(Activity activity, Point location) { ActivityDesigner designer = ActivityDesigner.GetDesigner(activity); if (designer != null) { FreeformActivityDesigner freeformDesigner = (designer.ParentDesigner != null) ? designer.ParentDesigner as FreeformActivityDesigner : designer as FreeformActivityDesigner; if (freeformDesigner != null) { designer.Location = location; if (freeformDesigner.AutoSize) freeformDesigner.PerformLayout(); } } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [DesignOnly(true)] [MergableProperty(false)] [Browsable(false)] public Size GetSize(Activity activity) { Size size = Size.Empty; ActivityDesigner designer = ActivityDesigner.GetDesigner(activity); if (designer != null) size = designer.Size; return size; } public void SetSize(Activity activity, Size size) { ActivityDesigner designer = ActivityDesigner.GetDesigner(activity); if (designer != null) { FreeformActivityDesigner freeformDesigner = (designer.ParentDesigner != null) ? designer.ParentDesigner as FreeformActivityDesigner : designer as FreeformActivityDesigner; if (freeformDesigner != null) { designer.Size = size; if (freeformDesigner.AutoSize) freeformDesigner.PerformLayout(); } } } #endregion bool IExtenderProvider.CanExtend(object extendee) { bool canExtend = false; Activity activity = extendee as Activity; if (activity != null) { ActivityDesigner designer = ActivityDesigner.GetDesigner(activity); if (designer != null) { FreeformActivityDesigner freeformDesigner = (designer.ParentDesigner != null) ? designer.ParentDesigner as FreeformActivityDesigner : designer as FreeformActivityDesigner; if (freeformDesigner != null) canExtend = true; } } return canExtend; } } #endregion #endregion } #endregion #region Class FreeFormDesignerVerbProvider internal sealed class FreeFormDesignerVerbProvider : IDesignerVerbProvider { #region IDesignerVerbProvider Members ActivityDesignerVerbCollection IDesignerVerbProvider.GetVerbs(ActivityDesigner activityDesigner) { ActivityDesignerVerbCollection verbs = new ActivityDesignerVerbCollection(); if (activityDesigner.ParentDesigner is FreeformActivityDesigner) { ActivityDesignerVerb verb = new ActivityDesignerVerb(activityDesigner, DesignerVerbGroup.Actions, DR.GetString(DR.BringToFront), new EventHandler(OnZOrderChanged), new EventHandler(OnZOrderStatusUpdate)); verb.Properties[DesignerUserDataKeys.ZOrderKey] = ZOrder.Foreground; verbs.Add(verb); verb = new ActivityDesignerVerb(activityDesigner, DesignerVerbGroup.Actions, DR.GetString(DR.SendToBack), new EventHandler(OnZOrderChanged), new EventHandler(OnZOrderStatusUpdate)); verb.Properties[DesignerUserDataKeys.ZOrderKey] = ZOrder.Background; verbs.Add(verb); } return verbs; } #endregion #region Helpers private void OnZOrderChanged(object sender, EventArgs e) { ActivityDesignerVerb designerVerb = sender as ActivityDesignerVerb; if (designerVerb != null && designerVerb.Properties.Contains(DesignerUserDataKeys.ZOrderKey)) { FreeformActivityDesigner freeformDesigner = designerVerb.ActivityDesigner.ParentDesigner as FreeformActivityDesigner; if (freeformDesigner != null) { if ((ZOrder)designerVerb.Properties[DesignerUserDataKeys.ZOrderKey] == ZOrder.Foreground) freeformDesigner.BringToFront(designerVerb.ActivityDesigner); else if ((ZOrder)designerVerb.Properties[DesignerUserDataKeys.ZOrderKey] == ZOrder.Background) freeformDesigner.SendToBack(designerVerb.ActivityDesigner); } } } private void OnZOrderStatusUpdate(object sender, EventArgs e) { ActivityDesignerVerb designerVerb = sender as ActivityDesignerVerb; if (designerVerb != null && designerVerb.Properties.Contains(DesignerUserDataKeys.ZOrderKey)) { FreeformActivityDesigner freeformDesigner = designerVerb.ActivityDesigner.ParentDesigner as FreeformActivityDesigner; if (freeformDesigner != null) designerVerb.Enabled = freeformDesigner.CanUpdateZOrder(designerVerb.ActivityDesigner, (ZOrder)designerVerb.Properties[DesignerUserDataKeys.ZOrderKey]); } } #endregion } #endregion } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ProfileManager.cs
- SimpleTypeResolver.cs
- XmlLoader.cs
- FloaterBaseParaClient.cs
- OLEDB_Util.cs
- SqlServer2KCompatibilityCheck.cs
- RTLAwareMessageBox.cs
- DataServiceResponse.cs
- Constants.cs
- DecoratedNameAttribute.cs
- TextPointer.cs
- EncoderParameters.cs
- PTProvider.cs
- Matrix3DConverter.cs
- XhtmlTextWriter.cs
- UInt64.cs
- EventSourceCreationData.cs
- TargetException.cs
- CodeSubDirectory.cs
- SelectionPattern.cs
- FixedPageAutomationPeer.cs
- DbProviderSpecificTypePropertyAttribute.cs
- JoinSymbol.cs
- SchemaObjectWriter.cs
- RTLAwareMessageBox.cs
- BindableAttribute.cs
- UidManager.cs
- BitmapEffectInputData.cs
- ColorAnimationBase.cs
- ItemCheckEvent.cs
- HMACSHA1.cs
- Int64Converter.cs
- DocumentPageViewAutomationPeer.cs
- ColumnCollection.cs
- QueryExpression.cs
- QueryCacheKey.cs
- Tracer.cs
- recordstatefactory.cs
- _RequestCacheProtocol.cs
- Membership.cs
- UserInitiatedNavigationPermission.cs
- SqlProvider.cs
- TableLayoutCellPaintEventArgs.cs
- CookielessHelper.cs
- PlatformCulture.cs
- MetabaseReader.cs
- Certificate.cs
- BindingMAnagerBase.cs
- XmlNamespaceDeclarationsAttribute.cs
- NameValueCollection.cs
- TypeValidationEventArgs.cs
- VScrollBar.cs
- DbBuffer.cs
- ApplicationHost.cs
- ArrayWithOffset.cs
- AssemblyAttributes.cs
- VariantWrapper.cs
- BoolExpr.cs
- AssociationSetMetadata.cs
- PropertyRef.cs
- Deserializer.cs
- OdbcCommand.cs
- QilTypeChecker.cs
- HtmlWindowCollection.cs
- InkCanvas.cs
- DataFormats.cs
- __Filters.cs
- CellCreator.cs
- GridViewUpdatedEventArgs.cs
- ListItemCollection.cs
- StylusTip.cs
- BamlResourceDeserializer.cs
- EventPrivateKey.cs
- GridViewColumnHeader.cs
- ToolStripItemRenderEventArgs.cs
- QueryOpeningEnumerator.cs
- DrawingGroup.cs
- NamedPipeConnectionPoolSettingsElement.cs
- ItemContainerProviderWrapper.cs
- CaseStatement.cs
- ExternalException.cs
- ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
- NativeWindow.cs
- SqlCacheDependencyDatabase.cs
- ItemList.cs
- CatalogPartChrome.cs
- PageThemeParser.cs
- filewebresponse.cs
- SByteConverter.cs
- ZeroOpNode.cs
- FormViewDeletedEventArgs.cs
- RadioButtonRenderer.cs
- WebPartConnection.cs
- EmptyImpersonationContext.cs
- XPathNodeInfoAtom.cs
- SqlUDTStorage.cs
- DataGridViewAutoSizeColumnModeEventArgs.cs
- ping.cs
- TemplateKeyConverter.cs
- AxisAngleRotation3D.cs