|
namespace System.Workflow.ComponentModel.Design
{
using System;
using System.IO;
using System.Xml;
using System.Text;
using System.CodeDom;
using System.Drawing;
using System.Reflection;
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.Windows.Forms;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Design;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.ComponentModel.Design.Serialization;
#region ActivityHostDesigner Class
/// <summary>
/// Base class used to display inlined workflows. This class is for internal use.
///
internal abstract class ActivityHostDesigner : SequentialActivityDesigner
{
#region Fields
private IWorkflowRootDesigner containedRootDesigner;
private ContainedDesignerLoader containedLoader;
private ContainedDesignSurface containedDesignSurface;
private MemoryStream lastInvokedWorkflowState;
#endregion
#region Constructor
public ActivityHostDesigner()
{
}
#endregion
#region Properties
#region Public Properties
public override ReadOnlyCollection<ActivityDesigner> ContainedDesigners
{
get
{
List<ActivityDesigner> containedDesigners = new List<ActivityDesigner>();
if (this.containedRootDesigner != null)
containedDesigners.Add((ActivityDesigner)this.containedRootDesigner);
return containedDesigners.AsReadOnly();
}
}
#endregion
#region Protected Properties
protected void RefreshHostedActivity()
{
// get currest state
if (this.containedRootDesigner != null)
{
this.lastInvokedWorkflowState = new MemoryStream();
BinaryWriter writer = new BinaryWriter(this.lastInvokedWorkflowState);
SaveViewState(writer);
}
//Refresh the designer
this.containedRootDesigner = LoadHostedWorkflow();
if (this.lastInvokedWorkflowState != null)
{
// set state
this.lastInvokedWorkflowState.Position = 0;
BinaryReader reader = new BinaryReader(this.lastInvokedWorkflowState);
try
{
LoadViewState(reader);
}
catch
{
// tried to apply serialized state to the wrong hosted activity... ignore
}
}
PerformLayout();
}
protected abstract Activity RootActivity
{
get;
}
#endregion
#region Private Properties
#endregion
#endregion
#region Methods
#region Public Methods
public override bool CanInsertActivities(HitTestInfo insertLocation, ReadOnlyCollection<Activity> activitiesToInsert)
{
return false;
}
public override void InsertActivities(HitTestInfo insertLocation, ReadOnlyCollection<Activity> activitiesToInsert)
{
}
public override bool CanRemoveActivities(ReadOnlyCollection<Activity> activitiesToRemove)
{
return false;
}
public override void RemoveActivities(ReadOnlyCollection<Activity> activitiesToRemove)
{
}
#endregion
#region Protected Methods
protected override void Dispose(bool disposing)
{
try
{
if (disposing)
{
//Both of these objects are disposed in design surface dispose.
this.containedRootDesigner = null;
this.containedLoader = null;
if (this.containedDesignSurface != null)
{
this.containedDesignSurface.Dispose();
this.containedDesignSurface = null;
}
if (this.lastInvokedWorkflowState != null)
{
this.lastInvokedWorkflowState.Close();
this.lastInvokedWorkflowState = null;
}
}
}
finally
{
base.Dispose(disposing);
}
}
protected override void SaveViewState(BinaryWriter writer)
{
base.SaveViewState(writer);
if (this.containedDesignSurface != null)
{
// mark persistence for invoked workflow
writer.Write(true);
IDesignerHost designerHost = this.containedDesignSurface.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (designerHost == null)
throw new Exception(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));
DesignerHelpers.SerializeDesignerStates(designerHost, writer);
}
else
{
// no persistnce data for invoked workflow
writer.Write(false);
}
}
protected override void LoadViewState(BinaryReader reader)
{
base.LoadViewState(reader);
if (reader.ReadBoolean())
{
//verify the hosted surface and designer are loaded
if (this.containedDesignSurface == null)
this.containedRootDesigner = LoadHostedWorkflow();
if (this.containedDesignSurface != null)
{
IDesignerHost designerHost = this.containedDesignSurface.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (designerHost == null)
throw new Exception(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));
DesignerHelpers.DeserializeDesignerStates(designerHost, reader);
}
}
}
#endregion
#region Private Methods
private IWorkflowRootDesigner LoadHostedWorkflow()
{
if (RootActivity != null)
{
this.containedLoader = new ContainedDesignerLoader(RootActivity as Activity);
this.containedDesignSurface = new ContainedDesignSurface(Activity.Site, this);
if (this.containedDesignSurface.IsLoaded == false)
this.containedDesignSurface.BeginLoad(this.containedLoader);
return ActivityDesigner.GetSafeRootDesigner(this.containedDesignSurface.GetService(typeof(IDesignerHost)) as IServiceProvider) as IWorkflowRootDesigner;
}
else
{
return null;
}
}
#endregion
#endregion
#region DesignSurface Hosting Related Functionality
#region Class ContainedDesignSurface
private class ContainedDesignSurface : DesignSurface
{
#region Members and Constructor
private CompositeActivityDesigner parentDesigner;
internal ContainedDesignSurface(IServiceProvider parentServiceProvider, CompositeActivityDesigner parentDesigner)
: base(parentServiceProvider)
{
this.parentDesigner = parentDesigner;
if (ServiceContainer != null)
ServiceContainer.RemoveService(typeof(ISelectionService));
}
#endregion
#region Properties and Methods
//internal CompositeActivityDesigner ContainingDesigner
//{
// get
// {
// return this.parentDesigner;
// }
//}
protected override IDesigner CreateDesigner(IComponent component, bool rootDesigner)
{
IDesigner designer = base.CreateDesigner(component, rootDesigner);
if (rootDesigner)
{
IWorkflowRootDesigner workflowRootDesigner = designer as IWorkflowRootDesigner;
if (workflowRootDesigner != null)
workflowRootDesigner.InvokingDesigner = this.parentDesigner;
}
return designer;
}
#endregion
}
#endregion
#region Class ContainedDesignerLoader
private sealed class ContainedDesignerLoader : WorkflowDesignerLoader
{
#region Members and Constructor
private Activity rootActivity;
internal ContainedDesignerLoader(Activity rootActivity)
{
this.rootActivity = rootActivity;
}
#endregion
#region Methods and Properties
protected override void Initialize()
{
base.Initialize();
ServiceCreatorCallback callback = new ServiceCreatorCallback(OnCreateService);
LoaderHost.RemoveService(typeof(IReferenceService));
LoaderHost.AddService(typeof(IReferenceService), callback);
}
private object OnCreateService(IServiceContainer container, Type serviceType)
{
object createdService = null;
if (serviceType == typeof(IReferenceService))
createdService = new ReferenceService(LoaderHost);
return createdService;
}
public override string FileName
{
get
{
return String.Empty;
}
}
public override TextReader GetFileReader(string filePath)
{
return null;
}
public override TextWriter GetFileWriter(string filePath)
{
return null;
}
public override void ForceReload()
{
}
protected override void PerformLoad(IDesignerSerializationManager serializationManager)
{
IDesignerHost designerHost = (IDesignerHost)GetService(typeof(IDesignerHost));
if (this.rootActivity != null && this.rootActivity is Activity)
{
AddActivityToDesigner(this.rootActivity as Activity);
SetBaseComponentClassName(this.rootActivity.GetType().FullName);
}
}
public override void Flush()
{
}
#endregion
}
#endregion
#endregion
}
#endregion
#region Class InvokeWorkflowDesigner
[ActivityDesignerTheme(typeof(InvokeWorkflowDesignerTheme))]
internal sealed class InvokeWorkflowDesigner : ActivityHostDesigner
{
#region members and initializers
internal const string InvokeWorkflowRef = "System.Workflow.Activities.InvokeWorkflowActivity, " + AssemblyRef.ActivitiesAssemblyRef;
private static readonly ArrayList ReservedParameterNames = new ArrayList(new string[] { "Name", "Enabled", "Description", "TargetWorkflow", "Invoking", "ParameterBindings" });
private Type targetWorkflowType = null;
protected override void Initialize(Activity activity)
{
base.Initialize(activity);
HelpText = DR.GetString(DR.SpecifyTargetWorkflow);
RefreshTargetWorkflowType();
}
#endregion
#region Properties and Methods
protected override Activity RootActivity
{
get
{
if (this.targetWorkflowType == null || this.targetWorkflowType is DesignTimeType)
return null;
else
return Activator.CreateInstance(this.targetWorkflowType) as Activity;
}
}
protected override void PreFilterProperties(IDictionary properties)
{
base.PreFilterProperties(properties);
if (this.targetWorkflowType != null)
{
try
{
foreach (PropertyInfo parameterProperty in this.targetWorkflowType.GetProperties())
{
if (!parameterProperty.CanWrite)
continue;
if (parameterProperty.DeclaringType == typeof(DependencyObject) ||
parameterProperty.DeclaringType == typeof(Activity) ||
parameterProperty.DeclaringType == typeof(CompositeActivity) ||
((parameterProperty.DeclaringType == Type.GetType(DesignerHelpers.SequentialWorkflowTypeRef) ||
parameterProperty.DeclaringType == Type.GetType(DesignerHelpers.StateMachineWorkflowTypeRef)) &&
string.Equals(parameterProperty.Name, "DynamicUpdateCondition", StringComparison.Ordinal)))
continue;
bool ignoreProperty = false;
Type dependencyObjectType = this.targetWorkflowType;
while (dependencyObjectType != null && dependencyObjectType is DesignTimeType)
dependencyObjectType = dependencyObjectType.BaseType;
if (dependencyObjectType != null)
{
foreach (DependencyProperty dependencyProperty in DependencyProperty.FromType(dependencyObjectType))
{
if (dependencyProperty.Name == parameterProperty.Name && dependencyProperty.DefaultMetadata.IsMetaProperty)
{
ignoreProperty = true;
break;
}
}
}
if (!ignoreProperty)
{
PropertyDescriptor prop = new ParameterInfoBasedPropertyDescriptor(Type.GetType(InvokeWorkflowRef), parameterProperty.Name, parameterProperty.PropertyType, ReservedParameterNames.Contains(parameterProperty.Name), DesignOnlyAttribute.Yes);
properties[prop.Name] = prop;
}
}
}
catch (MissingMemberException)
{
// targetServiceType has no default CTor, ignore
}
}
}
protected override void OnActivityChanged(ActivityChangedEventArgs e)
{
base.OnActivityChanged(e);
if (e.Member != null)
{
if (string.Equals(e.Member.Name, "TargetWorkflow", StringComparison.Ordinal))
{
//We need to clear the parameter bindings if target workflow type changes
if (e.OldValue != e.NewValue && Activity != null)
{
PropertyInfo parameterProperty = Activity.GetType().GetProperty("ParameterBindings", BindingFlags.Instance | BindingFlags.Public);
if (parameterProperty != null)
{
WorkflowParameterBindingCollection bindings = parameterProperty.GetValue(Activity, null) as WorkflowParameterBindingCollection;
if (bindings != null)
bindings.Clear();
}
}
RefreshTargetWorkflowType();
}
}
}
#endregion
#region Helpers
internal void RefreshTargetWorkflowType()
{
if (Activity == null)
return;
ITypeFilterProvider typeFilterProvider = Activity as ITypeFilterProvider;
Type workflowType = Activity.GetType().InvokeMember("TargetWorkflow", BindingFlags.GetProperty | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.ExactBinding, null, Activity, new object[] { }, CultureInfo.InvariantCulture) as Type;
if (workflowType != null && typeFilterProvider.CanFilterType(workflowType, false))
{
ITypeProvider typeProvider = (ITypeProvider)GetService(typeof(ITypeProvider));
if (typeProvider != null)
{
Type updatedWorkflowType = null;
if (workflowType.Assembly == null && typeProvider.LocalAssembly != null)
updatedWorkflowType = typeProvider.LocalAssembly.GetType(workflowType.FullName);
else
updatedWorkflowType = typeProvider.GetType(workflowType.FullName);
if (updatedWorkflowType != null)
workflowType = updatedWorkflowType;
}
}
else
{
workflowType = null;
}
if (this.targetWorkflowType != workflowType)
{
this.targetWorkflowType = workflowType;
RefreshHostedActivity();
if (this.targetWorkflowType is DesignTimeType)
HelpText = DR.GetString(DR.BuildTargetWorkflow);
else
HelpText = DR.GetString(DR.SpecifyTargetWorkflow);
}
TypeDescriptor.Refresh(Activity);
}
#endregion
}
#endregion
#region InvokeWorkflowDesignerTheme
internal sealed class InvokeWorkflowDesignerTheme : CompositeDesignerTheme
{
public InvokeWorkflowDesignerTheme(WorkflowTheme theme)
: base(theme)
{
this.ShowDropShadow = false;
this.ConnectorStartCap = LineAnchor.None;
this.ConnectorEndCap = LineAnchor.ArrowAnchor;
this.ForeColor = Color.FromArgb(0xFF, 0x00, 0x00, 0x00);
this.BorderColor = Color.FromArgb(0xFF, 0xE0, 0xE0, 0xE0);
this.BorderStyle = System.Drawing.Drawing2D.DashStyle.Dash;
this.BackColorStart = Color.FromArgb(0x00, 0x00, 0x00, 0x00);
this.BackColorEnd = Color.FromArgb(0x00, 0x00, 0x00, 0x00);
}
}
#endregion
}
|