536cd135cc
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
827 lines
30 KiB
C#
827 lines
30 KiB
C#
#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 StructuredCompositeActivityDesigner Class
|
|
/// <summary>
|
|
/// Base class for CompositActivityDesigner which have a structured layouts where contained ContainedDesigners
|
|
/// are connected to each other using connectors. Class is used when the user needs to provide different types
|
|
/// of layouts for CompositeActivityDesigner
|
|
/// </summary>
|
|
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
|
public abstract class StructuredCompositeActivityDesigner : CompositeActivityDesigner
|
|
{
|
|
#region Fields
|
|
private int currentDropTarget = -1;
|
|
|
|
private List<DesignerView> views = null;
|
|
private DesignerView activeView;
|
|
private ItemPalette itemPalette = null;
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
#region Public Properties
|
|
public override ReadOnlyCollection<ActivityDesigner> ContainedDesigners
|
|
{
|
|
get
|
|
{
|
|
List<ActivityDesigner> containedDesigners = new List<ActivityDesigner>();
|
|
ActivityDesigner activeDesigner = ActiveDesigner;
|
|
if (activeDesigner != null)
|
|
{
|
|
if (activeDesigner == this)
|
|
{
|
|
//We need to remove the secondary activities
|
|
containedDesigners.AddRange(base.ContainedDesigners);
|
|
|
|
List<ActivityDesigner> designersToRemove = new List<ActivityDesigner>();
|
|
IList<ActivityDesigner> mappedDesigners = DesignersFromSupportedViews;
|
|
|
|
foreach (ActivityDesigner containedDesigner in containedDesigners)
|
|
{
|
|
bool isAlternateFlowActivityAttribute = Helpers.IsAlternateFlowActivity(containedDesigner.Activity);
|
|
if (mappedDesigners.Contains(containedDesigner) || isAlternateFlowActivityAttribute)
|
|
designersToRemove.Add(containedDesigner);
|
|
}
|
|
|
|
foreach (ActivityDesigner activityDesigner in designersToRemove)
|
|
containedDesigners.Remove(activityDesigner);
|
|
}
|
|
else
|
|
{
|
|
containedDesigners.Add(activeDesigner);
|
|
}
|
|
}
|
|
|
|
return containedDesigners.AsReadOnly();
|
|
}
|
|
}
|
|
|
|
public override object FirstSelectableObject
|
|
{
|
|
get
|
|
{
|
|
ActivityDesigner activeDesigner = ActiveDesigner;
|
|
if (activeDesigner != null && activeDesigner != this)
|
|
return activeDesigner.Activity;
|
|
else
|
|
return base.FirstSelectableObject;
|
|
}
|
|
}
|
|
|
|
public override object LastSelectableObject
|
|
{
|
|
get
|
|
{
|
|
ActivityDesigner activeDesigner = ActiveDesigner;
|
|
if (activeDesigner != null && activeDesigner != this && activeDesigner is CompositeActivityDesigner)
|
|
return ((CompositeActivityDesigner)activeDesigner).LastSelectableObject;
|
|
else
|
|
return base.LastSelectableObject;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the ActiveView supported by the designer
|
|
/// </summary>
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public DesignerView ActiveView
|
|
{
|
|
get
|
|
{
|
|
if (this.activeView == null)
|
|
this.activeView = ValidatedViews[0];
|
|
return this.activeView;
|
|
}
|
|
|
|
set
|
|
{
|
|
if (this.activeView == value || value == null)
|
|
return;
|
|
|
|
DesignerView previousView = this.activeView;
|
|
|
|
this.activeView = value;
|
|
|
|
value.OnActivate();
|
|
|
|
ActivityDesigner designer = value.AssociatedDesigner;
|
|
if (designer == null)
|
|
{
|
|
value.OnDeactivate();
|
|
this.activeView = previousView;
|
|
return;
|
|
}
|
|
|
|
if (previousView != null)
|
|
previousView.OnDeactivate();
|
|
|
|
OnViewChanged(this.activeView);
|
|
|
|
//When we change the view we want to make sure that if we hide any of the child
|
|
//activities with errors we want to reveal these activities
|
|
DesignerHelpers.RefreshDesignerActions(Activity.Site);
|
|
|
|
//Keep the dynamic action and designer verbs in sync
|
|
RefreshDesignerVerbs();
|
|
}
|
|
}
|
|
|
|
public override Size MinimumSize
|
|
{
|
|
get
|
|
{
|
|
Size minimumSize = base.MinimumSize;
|
|
|
|
ActivityDesigner activeDesigner = ActiveDesigner;
|
|
if (activeDesigner != null && activeDesigner != this && Expanded)
|
|
{
|
|
minimumSize.Width = Math.Max(minimumSize.Width, 160);
|
|
minimumSize.Height = Math.Max(minimumSize.Height, 160);
|
|
}
|
|
|
|
return minimumSize;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the array of views supported by the current designer
|
|
/// </summary>
|
|
public virtual ReadOnlyCollection<DesignerView> Views
|
|
{
|
|
get
|
|
{
|
|
if (this.views == null)
|
|
{
|
|
this.views = new List<DesignerView>();
|
|
this.views.AddRange(SecondaryViewProvider.GetViews(this));
|
|
}
|
|
|
|
return this.views.AsReadOnly();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Protected Properties
|
|
/// <summary>
|
|
/// Gets the index of the cuurent drop target in the array of drop targets returned by method GetDropTargets
|
|
/// This property is only used when the drag drop operation is in progress
|
|
/// </summary>
|
|
protected virtual int CurrentDropTarget
|
|
{
|
|
get
|
|
{
|
|
return this.currentDropTarget;
|
|
}
|
|
|
|
set
|
|
{
|
|
this.currentDropTarget = value;
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
protected override bool ShowSmartTag
|
|
{
|
|
get
|
|
{
|
|
return (!String.IsNullOrEmpty(Text) && !TextRectangle.Size.IsEmpty && Views.Count > 1);
|
|
}
|
|
}
|
|
|
|
protected override ReadOnlyCollection<ActivityDesignerVerb> SmartTagVerbs
|
|
{
|
|
get
|
|
{
|
|
List<ActivityDesignerVerb> smartTagVerbs = new List<ActivityDesignerVerb>(base.SmartTagVerbs);
|
|
|
|
//Return smarttag actions only if there is more than one view
|
|
if (Views.Count > 1)
|
|
{
|
|
for (int i = 0; i < Views.Count; i++)
|
|
{
|
|
DesignerView view = Views[i];
|
|
ActivityDesignerVerb smartVerb = new ActivityDesignerVerb(this, DesignerVerbGroup.Actions, view.Text, new EventHandler(OnSmartTagVerb), new EventHandler(OnSmartTagVerbStatus));
|
|
smartVerb.Properties[DesignerUserDataKeys.DesignerView] = view;
|
|
smartVerb.Properties[DesignerUserDataKeys.Image] = view.Image;
|
|
smartTagVerbs.Add(smartVerb);
|
|
}
|
|
}
|
|
|
|
return smartTagVerbs.AsReadOnly();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Private Properties
|
|
internal ActivityDesigner ActiveDesigner
|
|
{
|
|
get
|
|
{
|
|
if (ActiveView != null)
|
|
return ActiveView.AssociatedDesigner;
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
internal override bool SmartTagVisible
|
|
{
|
|
get
|
|
{
|
|
if (this.itemPalette != null && this.itemPalette.IsVisible)
|
|
return true;
|
|
|
|
return base.SmartTagVisible;
|
|
}
|
|
|
|
set
|
|
{
|
|
base.SmartTagVisible = value;
|
|
}
|
|
}
|
|
|
|
private ReadOnlyCollection<DesignerView> ValidatedViews
|
|
{
|
|
get
|
|
{
|
|
ReadOnlyCollection<DesignerView> views = Views;
|
|
if (views.Count == 0)
|
|
#pragma warning suppress 56503
|
|
throw new InvalidOperationException(DR.GetString(DR.Error_MultiviewSequentialActivityDesigner));
|
|
return views;
|
|
}
|
|
}
|
|
|
|
private IList<ActivityDesigner> DesignersFromSupportedViews
|
|
{
|
|
get
|
|
{
|
|
List<ActivityDesigner> mappedDesigners = new List<ActivityDesigner>();
|
|
foreach (DesignerView view in ValidatedViews)
|
|
{
|
|
ActivityDesigner mappedDesigner = view.AssociatedDesigner;
|
|
if (mappedDesigner != null)
|
|
mappedDesigners.Add(mappedDesigner);
|
|
}
|
|
|
|
return mappedDesigners.AsReadOnly();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
#region Public Methods
|
|
public override bool CanInsertActivities(HitTestInfo insertLocation, ReadOnlyCollection<Activity> activitiesToInsert)
|
|
{
|
|
if (insertLocation == null)
|
|
throw new ArgumentNullException("insertLocation");
|
|
|
|
if (activitiesToInsert == null)
|
|
throw new ArgumentNullException("activitiesToInsert");
|
|
|
|
ActivityDesigner hostedDesigner = (ActiveView != null) ? ActiveView.AssociatedDesigner : null;
|
|
if (hostedDesigner != this)
|
|
return false;
|
|
|
|
IList<Type> secondaryViewTypes = SecondaryViewProvider.GetActivityTypes(this);
|
|
foreach (Activity activity in activitiesToInsert)
|
|
{
|
|
if (activity == null)
|
|
throw new ArgumentException("activitiesToInsert", SR.GetString(SR.Error_CollectionHasNullEntry));
|
|
|
|
if (secondaryViewTypes.Contains(activity.GetType()))
|
|
return false;
|
|
}
|
|
|
|
return base.CanInsertActivities(GetUpdatedLocation(insertLocation), activitiesToInsert);
|
|
}
|
|
|
|
public override void InsertActivities(HitTestInfo insertLocation, ReadOnlyCollection<Activity> activitiesToInsert)
|
|
{
|
|
if (insertLocation == null)
|
|
throw new ArgumentNullException("insertLocation");
|
|
|
|
if (activitiesToInsert == null)
|
|
throw new ArgumentNullException("activitiesToInsert");
|
|
|
|
base.InsertActivities(GetUpdatedLocation(insertLocation), activitiesToInsert);
|
|
}
|
|
|
|
public override void MoveActivities(HitTestInfo moveLocation, ReadOnlyCollection<Activity> activitiesToMove)
|
|
{
|
|
if (moveLocation == null)
|
|
throw new ArgumentNullException("moveLocation");
|
|
|
|
if (activitiesToMove == null)
|
|
throw new ArgumentNullException("activitiesToMove");
|
|
|
|
base.MoveActivities(GetUpdatedLocation(moveLocation), activitiesToMove);
|
|
}
|
|
|
|
public override bool CanRemoveActivities(ReadOnlyCollection<Activity> activitiesToRemove)
|
|
{
|
|
if (activitiesToRemove == null)
|
|
throw new ArgumentNullException("activitiesToRemove");
|
|
|
|
return base.CanRemoveActivities(activitiesToRemove);
|
|
}
|
|
|
|
public override void EnsureVisibleContainedDesigner(ActivityDesigner containedDesigner)
|
|
{
|
|
if (containedDesigner == null)
|
|
throw new ArgumentNullException("containedDesigner");
|
|
|
|
//we could be collapsed, make sure the view itself is visible
|
|
this.Expanded = true;
|
|
|
|
ActivityDesigner activeDesigner = ActiveDesigner;
|
|
if (containedDesigner != activeDesigner && containedDesigner != this)
|
|
{
|
|
DesignerView viewToActivate = null;
|
|
ReadOnlyCollection<DesignerView> views = ValidatedViews;
|
|
|
|
//Go thru the views and check if the child designer is one of the views
|
|
foreach (DesignerView view in views)
|
|
{
|
|
if (containedDesigner == view.AssociatedDesigner)
|
|
{
|
|
viewToActivate = view;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//This means that the child designer is in our main flow
|
|
if (viewToActivate == null)
|
|
viewToActivate = views[0];
|
|
|
|
ActiveView = viewToActivate;
|
|
|
|
//Invoking a verb might change the shown view so we map again
|
|
CompositeActivityDesigner activeCompositeDesigner = ActiveDesigner as CompositeActivityDesigner;
|
|
if (activeCompositeDesigner != null)
|
|
{
|
|
if (activeCompositeDesigner != this)
|
|
activeCompositeDesigner.EnsureVisibleContainedDesigner(containedDesigner);
|
|
else
|
|
base.EnsureVisibleContainedDesigner(containedDesigner);
|
|
}
|
|
}
|
|
}
|
|
|
|
public override object GetNextSelectableObject(object current, DesignerNavigationDirection direction)
|
|
{
|
|
object nextObject = null;
|
|
|
|
ActivityDesigner activeDesigner = ActiveDesigner;
|
|
if (activeDesigner != null)
|
|
{
|
|
if (activeDesigner != this)
|
|
{
|
|
if (current != activeDesigner.Activity && activeDesigner is CompositeActivityDesigner)
|
|
nextObject = ((CompositeActivityDesigner)activeDesigner).GetNextSelectableObject(current, direction);
|
|
}
|
|
else
|
|
{
|
|
nextObject = base.GetNextSelectableObject(current, direction);
|
|
}
|
|
}
|
|
|
|
return nextObject;
|
|
}
|
|
#endregion
|
|
|
|
#region Protected Methods
|
|
protected override void Initialize(Activity activity)
|
|
{
|
|
base.Initialize(activity);
|
|
|
|
ActiveView = ValidatedViews[0];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the collection of points which represents the inner connections of the designer. The designer can have connectors
|
|
/// within it, the points returned are the connection points used for connectable designer.
|
|
/// </summary>
|
|
/// <param name="edges">Designer Edge along which the connection point lies</param>
|
|
/// <returns>List of connection Points</returns>
|
|
protected virtual ReadOnlyCollection<Point> GetInnerConnections(DesignerEdges edges)
|
|
{
|
|
List<Point> connectionPoints = new List<Point>(GetConnections(edges));
|
|
if (connectionPoints.Count > 0 && (edges & DesignerEdges.Top) > 0)
|
|
connectionPoints[0] = new Point(connectionPoints[0].X, connectionPoints[0].Y + TitleHeight);
|
|
return connectionPoints.AsReadOnly();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns array of rectangles representing the valid drop locations with the designer
|
|
/// </summary>
|
|
/// <param name="dropPoint"></param>
|
|
/// <returns></returns>
|
|
protected virtual Rectangle[] GetDropTargets(Point dropPoint)
|
|
{
|
|
return new Rectangle[] { Bounds };
|
|
}
|
|
|
|
protected override void OnContainedActivitiesChanging(ActivityCollectionChangeEventArgs listChangeArgs)
|
|
{
|
|
base.OnContainedActivitiesChanging(listChangeArgs);
|
|
|
|
if (listChangeArgs.Action == ActivityCollectionChangeAction.Remove && listChangeArgs.RemovedItems[0] != null)
|
|
{
|
|
ActivityDesigner activeDesigner = ActiveDesigner;
|
|
if (activeDesigner != null && listChangeArgs.RemovedItems[0] == activeDesigner.Activity)
|
|
ActiveView = ValidatedViews[0];
|
|
SecondaryViewProvider.OnViewRemoved(this, listChangeArgs.RemovedItems[0].GetType());
|
|
}
|
|
}
|
|
|
|
protected void DrawConnectors(Graphics graphics, Pen pen, Point[] points, LineAnchor startCap, LineAnchor endCap)
|
|
{
|
|
Size arrowCapSize = Size.Empty;
|
|
Size maxCapSize = Size.Empty;
|
|
|
|
CompositeDesignerTheme compositeDesignerTheme = DesignerTheme as CompositeDesignerTheme;
|
|
if (compositeDesignerTheme != null)
|
|
{
|
|
arrowCapSize = new Size(compositeDesignerTheme.ConnectorSize.Width / 3, compositeDesignerTheme.ConnectorSize.Height / 3);
|
|
maxCapSize = compositeDesignerTheme.ConnectorSize;
|
|
}
|
|
ActivityDesignerPaint.DrawConnectors(graphics, pen, points, arrowCapSize, maxCapSize, startCap, endCap);
|
|
}
|
|
|
|
protected override void OnDragEnter(ActivityDragEventArgs e)
|
|
{
|
|
base.OnDragEnter(e);
|
|
|
|
CurrentDropTarget = CanDrop(e);
|
|
e.Effect = CheckDragEffect(e);
|
|
e.DragImageSnapPoint = SnapInToDropTarget(e);
|
|
}
|
|
|
|
protected override void OnDragOver(ActivityDragEventArgs e)
|
|
{
|
|
base.OnDragOver(e);
|
|
|
|
CurrentDropTarget = CanDrop(e);
|
|
e.Effect = CheckDragEffect(e);
|
|
e.DragImageSnapPoint = SnapInToDropTarget(e);
|
|
}
|
|
|
|
protected override void OnDragLeave()
|
|
{
|
|
base.OnDragLeave();
|
|
|
|
//Clear earlier drop target information
|
|
CurrentDropTarget = -1;
|
|
}
|
|
|
|
protected override void OnDragDrop(ActivityDragEventArgs e)
|
|
{
|
|
base.OnDragDrop(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;
|
|
|
|
//If the component is sited then that means that we are moving it
|
|
try
|
|
{
|
|
CompositeActivityDesigner.InsertActivities(this, new ConnectorHitTestInfo(this, HitTestLocations.Designer, CurrentDropTarget), e.Activities, SR.GetString(SR.DragDropActivities));
|
|
}
|
|
finally
|
|
{
|
|
CurrentDropTarget = -1;
|
|
}
|
|
}
|
|
|
|
protected override void OnLayoutPosition(ActivityDesignerLayoutEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
|
|
base.OnLayoutPosition(e);
|
|
|
|
if (Expanded)
|
|
{
|
|
ActivityDesigner activeDesigner = ActiveDesigner;
|
|
if (activeDesigner != null && activeDesigner != this)
|
|
{
|
|
Point location = Location;
|
|
location.X += (Size.Width - activeDesigner.Size.Width) / 2;
|
|
location.Y += e.AmbientTheme.SelectionSize.Height;
|
|
activeDesigner.Location = location;
|
|
}
|
|
|
|
int titleHeight = TitleHeight;
|
|
foreach (ActivityDesigner activityDesigner in ContainedDesigners)
|
|
activityDesigner.Location = new Point(activityDesigner.Location.X, activityDesigner.Location.Y + titleHeight);
|
|
}
|
|
}
|
|
|
|
protected override Size OnLayoutSize(ActivityDesignerLayoutEventArgs e)
|
|
{
|
|
Size containerSize = base.OnLayoutSize(e);
|
|
|
|
if (Expanded)
|
|
{
|
|
ActivityDesigner activeDesigner = ActiveDesigner;
|
|
if (activeDesigner != null && activeDesigner != this)
|
|
{
|
|
containerSize.Width = Math.Max(containerSize.Width, activeDesigner.Size.Width);
|
|
containerSize.Height += activeDesigner.Size.Height;
|
|
|
|
containerSize.Width += 2 * e.AmbientTheme.SelectionSize.Width;
|
|
containerSize.Width += 3 * e.AmbientTheme.Margin.Width;
|
|
containerSize.Height += e.AmbientTheme.Margin.Height;
|
|
containerSize.Height += 2 * e.AmbientTheme.SelectionSize.Height;
|
|
}
|
|
}
|
|
|
|
return containerSize;
|
|
}
|
|
|
|
protected override void SaveViewState(BinaryWriter writer)
|
|
{
|
|
if (writer == null)
|
|
throw new ArgumentNullException("writer");
|
|
|
|
List<DesignerView> views = new List<DesignerView>(ValidatedViews);
|
|
writer.Write("ActiveView");
|
|
writer.Write(views.IndexOf(this.activeView));
|
|
|
|
base.SaveViewState(writer);
|
|
}
|
|
|
|
protected override void LoadViewState(BinaryReader reader)
|
|
{
|
|
if (reader == null)
|
|
throw new ArgumentNullException("reader");
|
|
|
|
string str = reader.ReadString();
|
|
if (str != null && str.Equals("ActiveView", StringComparison.Ordinal))
|
|
{
|
|
int activeDesignerIndex = reader.ReadInt32();
|
|
ReadOnlyCollection<DesignerView> views = ValidatedViews;
|
|
if (activeDesignerIndex != -1 && activeDesignerIndex < views.Count)
|
|
ActiveView = views[activeDesignerIndex];
|
|
}
|
|
|
|
base.LoadViewState(reader);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the current view of the designer changes
|
|
/// </summary>
|
|
/// <param name="view">View which is being set.</param>
|
|
protected virtual void OnViewChanged(DesignerView view)
|
|
{
|
|
PerformLayout();
|
|
}
|
|
|
|
protected override void OnShowSmartTagVerbs(Point smartTagPoint)
|
|
{
|
|
if (this.itemPalette == null)
|
|
{
|
|
this.itemPalette = new ItemPalette();
|
|
this.itemPalette.Closed += new EventHandler(OnPaletteClosed);
|
|
this.itemPalette.SelectionChanged += new SelectionChangeEventHandler<SelectionChangeEventArgs>(OnSmartAction);
|
|
}
|
|
|
|
//we need to update the font every time the menu is shown
|
|
this.itemPalette.SetFont(WorkflowTheme.CurrentTheme.AmbientTheme.Font);
|
|
|
|
this.itemPalette.Items.Clear();
|
|
|
|
foreach (ActivityDesignerVerb smartVerb in SmartTagVerbs)
|
|
{
|
|
Image image = smartVerb.Properties[DesignerUserDataKeys.Image] as Image;
|
|
ItemInfo smartVerbItem = new ItemInfo(smartVerb.Id, image, smartVerb.Text);
|
|
smartVerbItem.UserData[DesignerUserDataKeys.DesignerVerb] = smartVerb;
|
|
this.itemPalette.Items.Add(smartVerbItem);
|
|
}
|
|
|
|
Point location = PointToScreen(smartTagPoint);
|
|
this.itemPalette.Show(location);
|
|
}
|
|
|
|
protected override void OnActivityChanged(ActivityChangedEventArgs e)
|
|
{
|
|
ReadOnlyCollection<DesignerView> newViews = SecondaryViewProvider.GetViews(this);
|
|
ReadOnlyCollection<DesignerView> oldViews = Views;
|
|
if (newViews.Count != oldViews.Count)
|
|
{
|
|
this.views = null;
|
|
|
|
//
|
|
|
|
|
|
PerformLayout();
|
|
}
|
|
|
|
base.OnActivityChanged(e);
|
|
}
|
|
#endregion
|
|
|
|
#region Private Methods
|
|
internal override void OnPaintContainedDesigners(ActivityDesignerPaintEventArgs e)
|
|
{
|
|
//Draw all the activity designers contained by the activity designer
|
|
//We know that all the children which are in drawing range will be always
|
|
//consecutive both for parallel and for sequential containers hence
|
|
//once we go in the invisible range we bail out of drawing logic for rest of
|
|
//the children
|
|
bool bDrawingVisibleChildren = false;
|
|
|
|
foreach (ActivityDesigner activityDesigner in ContainedDesigners)
|
|
{
|
|
Rectangle designerBounds = activityDesigner.Bounds;
|
|
if (e.ViewPort.IntersectsWith(designerBounds))
|
|
{
|
|
bDrawingVisibleChildren = true;
|
|
using (PaintEventArgs paintEventArgs = new PaintEventArgs(e.Graphics, e.ViewPort))
|
|
{
|
|
((IWorkflowDesignerMessageSink)activityDesigner).OnPaint(paintEventArgs, e.ViewPort);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bDrawingVisibleChildren)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private Point SnapInToDropTarget(ActivityDragEventArgs e)
|
|
{
|
|
if (CurrentDropTarget >= 0)
|
|
{
|
|
Rectangle[] dropTargets = GetDropTargets(new Point(e.X, e.Y));
|
|
if (CurrentDropTarget < dropTargets.Length)
|
|
{
|
|
Rectangle dropConnector = dropTargets[CurrentDropTarget];
|
|
return new Point(dropConnector.Left + dropConnector.Width / 2, dropConnector.Top + dropConnector.Height / 2);
|
|
}
|
|
}
|
|
|
|
return Point.Empty;
|
|
}
|
|
|
|
private int CanDrop(ActivityDragEventArgs e)
|
|
{
|
|
if (e.Activities.Count == 0)
|
|
return -1;
|
|
|
|
Point dropPoint = new Point(e.X, e.Y);
|
|
int dropIndex = -1;
|
|
Rectangle[] dropTargets = GetDropTargets(dropPoint);
|
|
for (int i = 0; i < dropTargets.Length; i++)
|
|
{
|
|
if (dropTargets[i].Contains(dropPoint))
|
|
{
|
|
dropIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dropIndex >= 0 && !CanInsertActivities(new ConnectorHitTestInfo(this, HitTestLocations.Designer, dropIndex), e.Activities))
|
|
dropIndex = -1;
|
|
|
|
bool ctrlKeyPressed = ((e.KeyState & 8) == 8);
|
|
if (dropIndex >= 0 && !ctrlKeyPressed && (e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move)
|
|
{
|
|
ConnectorHitTestInfo moveLocation = new ConnectorHitTestInfo(this, HitTestLocations.Designer, dropIndex);
|
|
foreach (Activity activity in e.Activities)
|
|
{
|
|
if (activity.Site != null)
|
|
{
|
|
ActivityDesigner activityDesigner = ActivityDesigner.GetDesigner(activity);
|
|
if (activityDesigner == null || activityDesigner.ParentDesigner == null || !activityDesigner.ParentDesigner.CanMoveActivities(moveLocation, new List<Activity>(new Activity[] { activity }).AsReadOnly()))
|
|
{
|
|
dropIndex = -1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return dropIndex;
|
|
}
|
|
|
|
private DragDropEffects CheckDragEffect(ActivityDragEventArgs e)
|
|
{
|
|
if (e.Activities.Count == 0)
|
|
{
|
|
return DragDropEffects.None;
|
|
}
|
|
else if (CurrentDropTarget >= 0)
|
|
{
|
|
bool ctrlKeyPressed = ((e.KeyState & 8) == 8);
|
|
if (ctrlKeyPressed && (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy)
|
|
return DragDropEffects.Copy;
|
|
else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move)
|
|
return DragDropEffects.Move;
|
|
}
|
|
|
|
return e.Effect;
|
|
}
|
|
|
|
private void OnSmartTagVerbStatus(object sender, EventArgs e)
|
|
{
|
|
ActivityDesignerVerb verb = sender as ActivityDesignerVerb;
|
|
|
|
DesignerView view = verb.Properties[DesignerUserDataKeys.DesignerView] as DesignerView;
|
|
if (view != null)
|
|
verb.Checked = (view == ActiveView);
|
|
}
|
|
|
|
private void OnSmartTagVerb(object sender, EventArgs e)
|
|
{
|
|
ActivityDesignerVerb verb = sender as ActivityDesignerVerb;
|
|
|
|
DesignerView view = verb.Properties[DesignerUserDataKeys.DesignerView] as DesignerView;
|
|
if (view != null)
|
|
{
|
|
ActiveView = view;
|
|
|
|
if (Expanded && view.AssociatedDesigner != null)
|
|
{
|
|
ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
|
|
if (selectionService != null)
|
|
selectionService.SetSelectedComponents(new object[] { view.AssociatedDesigner.Activity }, SelectionTypes.Replace);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnSmartAction(object sender, SelectionChangeEventArgs e)
|
|
{
|
|
ItemInfo itemInfo = e.CurrentItem as ItemInfo;
|
|
if (itemInfo != null)
|
|
{
|
|
ActivityDesignerVerb smartVerb = itemInfo.UserData[DesignerUserDataKeys.DesignerVerb] as ActivityDesignerVerb;
|
|
if (smartVerb != null)
|
|
smartVerb.Invoke();
|
|
}
|
|
}
|
|
|
|
private void OnPaletteClosed(object sender, EventArgs e)
|
|
{
|
|
Invalidate(DesignerSmartTag.GetBounds(this, true));
|
|
}
|
|
|
|
private HitTestInfo GetUpdatedLocation(HitTestInfo location)
|
|
{
|
|
int lockedActivityOffset = 0;
|
|
foreach (DesignerView secondaryView in Views)
|
|
{
|
|
if (secondaryView.AssociatedDesigner != null &&
|
|
this != secondaryView.AssociatedDesigner &&
|
|
Helpers.IsActivityLocked(secondaryView.AssociatedDesigner.Activity))
|
|
{
|
|
lockedActivityOffset++;
|
|
}
|
|
}
|
|
|
|
return new ConnectorHitTestInfo(this, location.HitLocation, lockedActivityOffset + location.MapToIndex());
|
|
}
|
|
#endregion
|
|
|
|
#endregion
|
|
}
|
|
#endregion
|
|
|
|
}
|