You've already forked linux-packaging-mono
Rewrite with hard-coded offsets into the PE file format to discern if a binary is PE32 or PE32+, and then to determine if it contains a "CLR Data Directory" entry that looks valid. Tested with PE32 and PE32+ compiled Mono binaries, PE32 and PE32+ native binaries, and a random assortment of garbage files. Former-commit-id: 9e7ac86ec84f653a2f79b87183efd5b0ebda001b
3137 lines
121 KiB
C#
3137 lines
121 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 ActivityDesigner Class
|
|
/// <summary>
|
|
/// ActivityDesigner provides a simple designer which allows user to visually design activities in the design mode.
|
|
/// ActivityDesigner provides simple mechanism using which the activities can participate in rendering the Workflow.
|
|
/// ActivityDesigner enables the user to customize layouting, drawing associated with the activity.
|
|
/// It also enables the user to extend the meta data associated with the activity.
|
|
/// </summary>
|
|
[ActivityDesignerTheme(typeof(ActivityDesignerTheme))]
|
|
[SRCategory("ActivityDesigners", "System.Workflow.ComponentModel.Design.DesignerResources")]
|
|
[DesignerSerializer(typeof(ActivityDesignerLayoutSerializer), typeof(WorkflowMarkupSerializer))]
|
|
[ToolboxItemFilter("Microsoft.Workflow.VSDesigner", ToolboxItemFilterType.Require)]
|
|
[ToolboxItemFilter("System.Workflow.ComponentModel.Design.ActivitySet", ToolboxItemFilterType.Custom)]
|
|
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
|
public class ActivityDesigner : IDisposable,
|
|
IDesignerFilter,
|
|
IDesigner,
|
|
IToolboxUser,
|
|
IPersistUIState,
|
|
IWorkflowDesignerMessageSink,
|
|
IWorkflowRootDesigner,
|
|
IConnectableDesigner
|
|
{
|
|
#region Fields
|
|
//Members which determine the linesize of text in ActivityDesigner
|
|
private const int MaximumCharsPerLine = 8;
|
|
private const int MaximumTextLines = 2;
|
|
private const int MaximumIdentifierLength = 25;
|
|
private const int MaximumDescriptionLength = 80;
|
|
private const uint FrameworkVersion_3_5 = 0x00030005;
|
|
private const uint FrameworkVersion_3_0 = 0x00030000;
|
|
|
|
//ActivityDesigner Related Members
|
|
private Activity activity;
|
|
private ActivityDesignerAccessibleObject accessibilityObject;
|
|
private ActivityDesignerVerbCollection designerVerbs;
|
|
private List<DesignerAction> designerActions;
|
|
|
|
[Flags]
|
|
internal enum DrawingStates { Valid = 0, InvalidPosition = 1, InvalidSize = 2, InvalidDraw = 4 };
|
|
private DrawingStates drawingState = DrawingStates.Valid;
|
|
|
|
private Point location = Point.Empty;
|
|
private Size size = Size.Empty;
|
|
private Image image;
|
|
private string text = String.Empty;
|
|
private Size textSize = Size.Empty;
|
|
private bool smartTagVisible = false;
|
|
private SmartTag smartTag = new SmartTag();
|
|
private bool isVisible = true;
|
|
private string rulesText = null;
|
|
|
|
//RootDesigner Related Members
|
|
private CompositeActivityDesigner invokingDesigner;
|
|
private WorkflowView workflowView;
|
|
#endregion
|
|
|
|
#region Construction and Destruction
|
|
public ActivityDesigner()
|
|
{
|
|
}
|
|
|
|
~ActivityDesigner()
|
|
{
|
|
Dispose(false);
|
|
}
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
#region Public Properties
|
|
/// <summary>
|
|
/// Gets activity being designed by the designer.
|
|
/// </summary>
|
|
public Activity Activity
|
|
{
|
|
get
|
|
{
|
|
return this.activity;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the parent designer of existing designer
|
|
/// </summary>
|
|
public CompositeActivityDesigner ParentDesigner
|
|
{
|
|
get
|
|
{
|
|
CompositeActivityDesigner parentDesigner = null;
|
|
IWorkflowRootDesigner rootDesigner = this as IWorkflowRootDesigner;
|
|
if (rootDesigner != null && IsRootDesigner)
|
|
parentDesigner = rootDesigner.InvokingDesigner;
|
|
else if (Activity != null && Activity.Parent != null)
|
|
parentDesigner = ActivityDesigner.GetDesigner(Activity.Parent) as CompositeActivityDesigner;
|
|
return parentDesigner;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets value indicating if the activity associated with the designer is selected.
|
|
/// </summary>
|
|
public bool IsSelected
|
|
{
|
|
get
|
|
{
|
|
ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
|
|
return (selectionService != null && selectionService.GetComponentSelected(Activity));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets value indicating if the activity associated with the designer is primary selection.
|
|
/// </summary>
|
|
public bool IsPrimarySelection
|
|
{
|
|
get
|
|
{
|
|
ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
|
|
return (selectionService != null && selectionService.PrimarySelection == Activity);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the accessibility object associated with the designer
|
|
/// </summary>
|
|
public virtual AccessibleObject AccessibilityObject
|
|
{
|
|
get
|
|
{
|
|
if (this.accessibilityObject == null)
|
|
this.accessibilityObject = new ActivityDesignerAccessibleObject(this);
|
|
return this.accessibilityObject;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the value indicating if a designer is visible on the workflow.
|
|
/// Designer is said to be invisible if the parent of the designer is collapsed or in cases where
|
|
/// designer is not shown on the workflow.
|
|
/// </summary>
|
|
public virtual bool IsVisible
|
|
{
|
|
get
|
|
{
|
|
return this.isVisible;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get value indicating if the activity associated with the designer can be modified.
|
|
/// This property also controls the position of the designer in the workflow.
|
|
/// It is used in edit operations such as drag drop, delete, cut/copy/paste etc.
|
|
/// </summary>
|
|
public bool IsLocked
|
|
{
|
|
get
|
|
{
|
|
if (Helpers.IsActivityLocked(Activity))
|
|
return true;
|
|
|
|
if (DrawingState != DrawingStates.Valid)
|
|
return true;
|
|
|
|
WorkflowDesignerLoader loader = GetService(typeof(WorkflowDesignerLoader)) as WorkflowDesignerLoader;
|
|
if (loader != null && loader.InDebugMode)
|
|
return true;
|
|
|
|
IWorkflowRootDesigner rootDesigner = ActivityDesigner.GetSafeRootDesigner(Activity.Site) as IWorkflowRootDesigner;
|
|
if (rootDesigner != null && rootDesigner.InvokingDesigner != null)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or Sets the location of the designer in logical coordinates.
|
|
/// </summary>
|
|
public virtual Point Location
|
|
{
|
|
get
|
|
{
|
|
return this.location;
|
|
}
|
|
|
|
set
|
|
{
|
|
if (ParentDesigner is FreeformActivityDesigner)
|
|
value = DesignerHelpers.SnapToGrid(value);
|
|
|
|
if (this.location != value)
|
|
this.location = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or Sets the size of the designer.
|
|
/// </summary>
|
|
public virtual Size Size
|
|
{
|
|
get
|
|
{
|
|
return this.size;
|
|
}
|
|
|
|
set
|
|
{
|
|
value.Width = Math.Max(value.Width, MinimumSize.Width);
|
|
value.Height = Math.Max(value.Height, MinimumSize.Height);
|
|
|
|
if (this.size != value)
|
|
this.size = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the minimum size of the designer
|
|
/// </summary>
|
|
public virtual Size MinimumSize
|
|
{
|
|
get
|
|
{
|
|
return DesignerTheme.Size;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get value for enclosing rectangle of the designer in logical coordinates.
|
|
/// </summary>
|
|
public Rectangle Bounds
|
|
{
|
|
get
|
|
{
|
|
//Bounds contain designer rectangle + the selection area
|
|
return new Rectangle(Location, Size);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the image associated with the designer.
|
|
/// </summary>
|
|
public virtual Image Image
|
|
{
|
|
get
|
|
{
|
|
return this.image;
|
|
}
|
|
protected set
|
|
{
|
|
this.image = value;
|
|
PerformLayout();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the text associated with the designer.
|
|
/// </summary>
|
|
public virtual string Text
|
|
{
|
|
get
|
|
{
|
|
return this.text;
|
|
}
|
|
protected set
|
|
{
|
|
if (value == null || value.Length == 0 || this.text == value)
|
|
return;
|
|
|
|
this.text = value;
|
|
PerformLayout();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the current theme to be used for the designer
|
|
/// </summary>
|
|
public ActivityDesignerTheme DesignerTheme
|
|
{
|
|
get
|
|
{
|
|
return WorkflowTheme.CurrentTheme.GetDesignerTheme(this);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the value indicating if the designer is root designer.
|
|
/// </summary>
|
|
public bool IsRootDesigner
|
|
{
|
|
get
|
|
{
|
|
bool isRootDesigner = false;
|
|
IDesignerHost designerHost = GetService(typeof(IDesignerHost)) as IDesignerHost;
|
|
if (designerHost != null)
|
|
isRootDesigner = (designerHost.RootComponent == Activity);
|
|
return isRootDesigner;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Protected Properties
|
|
/// <summary>
|
|
/// Returns the WorkflowView containing the designer
|
|
/// </summary>
|
|
protected internal WorkflowView ParentView
|
|
{
|
|
get
|
|
{
|
|
return GetService(typeof(WorkflowView)) as WorkflowView;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the collection of verbs to be associated with the designer.
|
|
/// The verbs are shown on context menu and the top level workflow menu.
|
|
/// </summary>
|
|
protected virtual ActivityDesignerVerbCollection Verbs
|
|
{
|
|
get
|
|
{
|
|
if (this.designerVerbs == null)
|
|
{
|
|
this.designerVerbs = new ActivityDesignerVerbCollection();
|
|
if (!IsLocked)
|
|
this.designerVerbs.Add(new ActivityDesignerVerb(this, DesignerVerbGroup.General, DR.GetString(DR.GenerateEventHandlers), new EventHandler(OnGenerateEventHandler), new EventHandler(OnGenerateEventHandlerStatusUpdate)));
|
|
|
|
// Add the item to choose an activity datasource
|
|
WorkflowDesignerLoader loader = GetService(typeof(WorkflowDesignerLoader)) as WorkflowDesignerLoader;
|
|
if (this.Activity.Parent != null)
|
|
this.designerVerbs.Add(new ActivityDesignerVerb(this, DesignerVerbGroup.General, DR.GetString(DR.PromoteBindings), new EventHandler(OnPromoteBindings), new EventHandler(OnPromoteBindingsStatusUpdate)));
|
|
|
|
this.designerVerbs.Add(new ActivityDesignerVerb(this, DesignerVerbGroup.General, DR.GetString(DR.BindSelectedProperty), new EventHandler(OnBindProperty), new EventHandler(OnBindPropertyStatusUpdate)));
|
|
|
|
ActivityDesignerVerb designerVerb = new ActivityDesignerVerb(this, DesignerVerbGroup.General, DR.GetString(DR.MoveLeftDesc), new EventHandler(OnMoveBranch), new EventHandler(OnStatusMoveBranch));
|
|
designerVerb.Properties[DesignerUserDataKeys.MoveBranchKey] = true;
|
|
this.designerVerbs.Add(designerVerb);
|
|
|
|
designerVerb = new ActivityDesignerVerb(this, DesignerVerbGroup.General, DR.GetString(DR.MoveRightDesc), new EventHandler(OnMoveBranch), new EventHandler(OnStatusMoveBranch));
|
|
designerVerb.Properties[DesignerUserDataKeys.MoveBranchKey] = false;
|
|
this.designerVerbs.Add(designerVerb);
|
|
|
|
foreach (ActivityDesignerVerb smartVerb in SmartTagVerbs)
|
|
this.designerVerbs.Add(smartVerb);
|
|
}
|
|
|
|
return this.designerVerbs;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the value indicating if smarttag should be shown.
|
|
/// </summary>
|
|
protected virtual bool ShowSmartTag
|
|
{
|
|
get
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the array of actions which the designer wants to associated with the smarttag.
|
|
/// </summary>
|
|
protected virtual ReadOnlyCollection<ActivityDesignerVerb> SmartTagVerbs
|
|
{
|
|
get
|
|
{
|
|
return new List<ActivityDesignerVerb>().AsReadOnly();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the Rectangle where the smarttag needs to be displayed
|
|
/// </summary>
|
|
protected virtual Rectangle SmartTagRectangle
|
|
{
|
|
get
|
|
{
|
|
Rectangle smartTagRectangle = Rectangle.Empty;
|
|
|
|
Rectangle imageRectangle = ImageRectangle;
|
|
if (!imageRectangle.Size.IsEmpty)
|
|
{
|
|
smartTagRectangle = imageRectangle;
|
|
}
|
|
|
|
return smartTagRectangle;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the array of actions associated with the configuration errors.
|
|
/// </summary>
|
|
protected internal virtual ReadOnlyCollection<DesignerAction> DesignerActions
|
|
{
|
|
get
|
|
{
|
|
if (this.designerActions == null)
|
|
{
|
|
this.designerActions = new List<DesignerAction>();
|
|
|
|
Activity activity = Activity;
|
|
if (activity != null)
|
|
{
|
|
bool isNestedInComment = ActivityDesigner.IsCommentedActivity(activity);
|
|
|
|
WorkflowDesignerLoader loader = GetService(typeof(WorkflowDesignerLoader)) as WorkflowDesignerLoader;
|
|
bool debugMode = (loader != null && loader.InDebugMode);
|
|
|
|
if (activity.Enabled && !isNestedInComment && !IsLocked && activity.Site != null && !debugMode)
|
|
{
|
|
ValidationErrorCollection validationErrors = new ValidationErrorCollection();
|
|
try
|
|
{
|
|
ValidationManager validationManager = new ValidationManager(Activity.Site, false);
|
|
using (WorkflowCompilationContext.CreateScope(validationManager))
|
|
{
|
|
Activity rootActivity = Helpers.GetRootActivity(this.Activity);
|
|
foreach (Validator validator in validationManager.GetValidators(activity.GetType()))
|
|
validationErrors.AddRange(validator.Validate(validationManager, activity));
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
Debug.WriteLine("Validate call failed");
|
|
}
|
|
|
|
//Populate the validation errors
|
|
if (validationErrors.Count > 0)
|
|
{
|
|
for (int i = 0; i < validationErrors.Count; i++)
|
|
{
|
|
ValidationError error = validationErrors[i] as ValidationError;
|
|
Debug.Assert(error != null, "someone inserted a null or no 'ValidationError' type error in errors collection.");
|
|
if (error != null && !error.IsWarning)
|
|
{
|
|
DesignerAction designerAction = new DesignerAction(this, i, error.ErrorText, AmbientTheme.ConfigErrorImage);
|
|
designerAction.PropertyName = error.PropertyName;
|
|
foreach (DictionaryEntry entry in error.UserData)
|
|
designerAction.UserData[entry.Key] = entry.Value;
|
|
this.designerActions.Add(designerAction);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return this.designerActions.AsReadOnly();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the array of glyphs with which to adorn the designer.
|
|
/// </summary>
|
|
protected internal virtual ActivityDesignerGlyphCollection Glyphs
|
|
{
|
|
get
|
|
{
|
|
ActivityDesignerGlyphCollection glyphs = new ActivityDesignerGlyphCollection();
|
|
|
|
if (IsSelected)
|
|
{
|
|
if (IsPrimarySelection)
|
|
glyphs.Add(PrimarySelectionGlyph.Default);
|
|
else
|
|
glyphs.Add(NonPrimarySelectionGlyph.Default);
|
|
}
|
|
|
|
bool isNestedInComment = ActivityDesigner.IsCommentedActivity(Activity);
|
|
|
|
WorkflowDesignerLoader loader = GetService(typeof(WorkflowDesignerLoader)) as WorkflowDesignerLoader;
|
|
bool debugMode = (loader != null && loader.InDebugMode);
|
|
|
|
if (WorkflowTheme.CurrentTheme.AmbientTheme.ShowConfigErrors &&
|
|
Activity.Enabled && !isNestedInComment && !debugMode &&
|
|
DesignerActions.Count > 0)
|
|
glyphs.Add(ConfigErrorGlyph.Default);
|
|
|
|
//Add comment glyph only for ctop level comments
|
|
if (!Activity.Enabled && !isNestedInComment)
|
|
glyphs.Add(CommentGlyph.Default);
|
|
|
|
//
|
|
if (Helpers.IsActivityLocked(Activity))
|
|
glyphs.Add(LockedActivityGlyph.Default);
|
|
|
|
if (SmartTagVisible && ShowSmartTag)
|
|
glyphs.Add(this.smartTag);
|
|
|
|
return glyphs;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the value of text rectangle in logical coordinates.
|
|
/// </summary>
|
|
protected virtual Rectangle TextRectangle
|
|
{
|
|
get
|
|
{
|
|
//BY DEFAULT THE TEXT IS ALIGNED TO THE BOTTOM
|
|
if (String.IsNullOrEmpty(Text))
|
|
return Rectangle.Empty;
|
|
|
|
AmbientTheme ambientTheme = WorkflowTheme.CurrentTheme.AmbientTheme;
|
|
ActivityDesignerTheme designerTheme = DesignerTheme;
|
|
|
|
Rectangle bounds = Bounds;
|
|
Rectangle textRectangle = Rectangle.Empty;
|
|
textRectangle.X = bounds.Left + ambientTheme.Margin.Width;
|
|
textRectangle.X += (Image != null) ? designerTheme.ImageSize.Width + ambientTheme.Margin.Width : 0;
|
|
textRectangle.Y = bounds.Top + (bounds.Height - this.textSize.Height) / 2;
|
|
textRectangle.Size = this.textSize;
|
|
return textRectangle;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the value for enclosing bounds image associated with the designer in logical coordinates.
|
|
/// </summary>
|
|
protected virtual Rectangle ImageRectangle
|
|
{
|
|
get
|
|
{
|
|
//BY DEFAULT THE ICON RECTANGLE IS ALIGNED TO TOP / CENTER
|
|
if (Image == null)
|
|
return Rectangle.Empty;
|
|
|
|
AmbientTheme ambientTheme = WorkflowTheme.CurrentTheme.AmbientTheme;
|
|
ActivityDesignerTheme designerTheme = DesignerTheme;
|
|
|
|
Rectangle bounds = Bounds;
|
|
Rectangle imageRectangle = Rectangle.Empty;
|
|
imageRectangle.X = bounds.Left + WorkflowTheme.CurrentTheme.AmbientTheme.Margin.Width;
|
|
imageRectangle.Y = bounds.Top + (bounds.Height - DesignerTheme.ImageSize.Height) / 2;
|
|
imageRectangle.Size = designerTheme.ImageSize;
|
|
return imageRectangle;
|
|
}
|
|
}
|
|
|
|
protected virtual CompositeActivityDesigner InvokingDesigner
|
|
{
|
|
get
|
|
{
|
|
return this.invokingDesigner;
|
|
}
|
|
|
|
set
|
|
{
|
|
this.invokingDesigner = value;
|
|
}
|
|
}
|
|
|
|
protected virtual ReadOnlyCollection<WorkflowDesignerMessageFilter> MessageFilters
|
|
{
|
|
get
|
|
{
|
|
List<WorkflowDesignerMessageFilter> stockFilters = new List<WorkflowDesignerMessageFilter>();
|
|
stockFilters.Add(new ConnectionManager());
|
|
stockFilters.Add(new ResizingMessageFilter());
|
|
stockFilters.Add(new DynamicActionMessageFilter());
|
|
stockFilters.Add(new AutoScrollingMessageFilter());
|
|
stockFilters.Add(new AutoExpandingMessageFilter());
|
|
stockFilters.Add(new DragSelectionMessageFilter());
|
|
stockFilters.Add(new FreeFormDragDropManager());
|
|
return stockFilters.AsReadOnly();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get if the designer is resizable using the rubberbanding when dropped in FreeformDesigner
|
|
/// </summary>
|
|
protected internal virtual bool EnableVisualResizing
|
|
{
|
|
get
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Private Properties
|
|
|
|
#region Properties used during serialization only
|
|
//Note that the following property is used by ActivityDesignerLayoutSerializer to
|
|
//associate a designer with activity
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
|
internal string Name
|
|
{
|
|
get
|
|
{
|
|
return ((Activity != null) ? Activity.Name : null);
|
|
}
|
|
|
|
set
|
|
{
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
internal virtual bool SupportsLayoutPersistence
|
|
{
|
|
get
|
|
{
|
|
bool supportsLayoutPersistence = false;
|
|
IDesignerHost designerHost = GetService(typeof(IDesignerHost)) as IDesignerHost;
|
|
if (designerHost != null)
|
|
{
|
|
foreach (IComponent component in designerHost.Container.Components)
|
|
{
|
|
Activity activity = component as Activity;
|
|
if (activity != null && ActivityDesigner.GetDesigner(activity) is FreeformActivityDesigner)
|
|
{
|
|
supportsLayoutPersistence = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return supportsLayoutPersistence;
|
|
}
|
|
}
|
|
|
|
internal virtual WorkflowLayout SupportedLayout
|
|
{
|
|
get
|
|
{
|
|
return new ActivityRootLayout(Activity.Site);
|
|
}
|
|
}
|
|
|
|
internal SmartTag DesignerSmartTag
|
|
{
|
|
get
|
|
{
|
|
return this.smartTag;
|
|
}
|
|
}
|
|
|
|
internal DrawingStates DrawingState
|
|
{
|
|
get
|
|
{
|
|
return this.drawingState;
|
|
}
|
|
|
|
set
|
|
{
|
|
this.drawingState = value;
|
|
}
|
|
}
|
|
|
|
internal Image StockImage
|
|
{
|
|
get
|
|
{
|
|
if (Activity == null)
|
|
return null;
|
|
|
|
Image designerImage = DesignerTheme.DesignerImage;
|
|
if (designerImage == null)
|
|
designerImage = ActivityToolboxItem.GetToolboxImage(Activity.GetType());
|
|
|
|
return designerImage;
|
|
}
|
|
}
|
|
|
|
internal virtual bool SmartTagVisible
|
|
{
|
|
get
|
|
{
|
|
if (ShowSmartTag && this.smartTag.ActiveDesigner != null)
|
|
return true;
|
|
|
|
return this.smartTagVisible;
|
|
}
|
|
|
|
set
|
|
{
|
|
if (this.smartTagVisible == value)
|
|
return;
|
|
|
|
this.smartTagVisible = value;
|
|
OnSmartTagVisibilityChanged(this.smartTagVisible);
|
|
}
|
|
}
|
|
|
|
private PropertyDescriptor[] EventHandlerProperties
|
|
{
|
|
get
|
|
{
|
|
List<PropertyDescriptor> propertyDescriptors = new List<PropertyDescriptor>();
|
|
|
|
//Site can be null when we are dragging item from the toolbox onto the design surface
|
|
if (Activity.Site != null)
|
|
{
|
|
foreach (PropertyDescriptor propertyDescriptor in PropertyDescriptorFilter.GetPropertiesForEvents(Activity.Site, Activity))
|
|
propertyDescriptors.Add(propertyDescriptor);
|
|
}
|
|
|
|
return propertyDescriptors.ToArray();
|
|
}
|
|
}
|
|
|
|
private PropertyDescriptor[] BindableProperties
|
|
{
|
|
get
|
|
{
|
|
List<PropertyDescriptor> propertyDescriptors = new List<PropertyDescriptor>();
|
|
|
|
if (!Helpers.IsActivityLocked(Activity))
|
|
{
|
|
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(Activity, new Attribute[] { new BrowsableAttribute(true) });
|
|
if (properties != null)
|
|
{
|
|
foreach (PropertyDescriptor propDesc in properties)
|
|
{
|
|
if (propDesc.Converter is ActivityBindTypeConverter)
|
|
propertyDescriptors.Add(propDesc);
|
|
}
|
|
}
|
|
}
|
|
return propertyDescriptors.ToArray();
|
|
}
|
|
}
|
|
|
|
private string InfoTipTitle
|
|
{
|
|
get
|
|
{
|
|
string title = String.Empty;
|
|
if (Activity.Parent == null)
|
|
{
|
|
title = Activity.GetType().Name;
|
|
}
|
|
else
|
|
{
|
|
string activityName = (Activity.Name.Length > MaximumIdentifierLength) ? Activity.Name.Substring(0, MaximumIdentifierLength) + "..." : Activity.Name;
|
|
title = DR.GetString(DR.InfoTipTitle, Activity.GetType().Name, activityName);
|
|
}
|
|
return title;
|
|
}
|
|
}
|
|
|
|
private string InfoTipText
|
|
{
|
|
get
|
|
{
|
|
string tipText = (!String.IsNullOrEmpty(Activity.Description)) ? Activity.Description : ActivityDesigner.GetActivityDescription(Activity.GetType());
|
|
tipText = (tipText.Length > MaximumDescriptionLength) ? tipText.Substring(0, MaximumDescriptionLength) + "..." : tipText;
|
|
if (RulesText.Length > 0)
|
|
tipText += "\n\n" + RulesText;
|
|
|
|
return tipText;
|
|
}
|
|
}
|
|
|
|
private string RulesText
|
|
{
|
|
get
|
|
{
|
|
if (this.rulesText == null)
|
|
{
|
|
this.rulesText = String.Empty;
|
|
|
|
IDictionary<string, string> rules = DesignerHelpers.GetDeclarativeRules(Activity);
|
|
if (rules.Count > 0)
|
|
{
|
|
this.rulesText = DR.GetString(DR.Rules);
|
|
|
|
int maxRulesLength = 3 * (MaximumIdentifierLength + MaximumDescriptionLength);
|
|
foreach (KeyValuePair<string, string> rule in rules)
|
|
{
|
|
this.rulesText += "\n";
|
|
|
|
string ruleName = rule.Key as string;
|
|
ruleName = (ruleName.Length > MaximumIdentifierLength) ? ruleName.Substring(0, MaximumIdentifierLength) + "..." : ruleName;
|
|
|
|
string ruleDescription = rule.Value as string;
|
|
ruleDescription = (ruleDescription.Length > MaximumDescriptionLength) ? ruleDescription.Substring(0, MaximumDescriptionLength) + "..." : ruleDescription;
|
|
if (ruleDescription.Length == 0)
|
|
ruleDescription = DR.GetString(DR.Empty);
|
|
|
|
this.rulesText += String.Format(CultureInfo.CurrentCulture, "{0}: {1}", ruleName, ruleDescription);
|
|
if (this.rulesText.Length > maxRulesLength)
|
|
break;
|
|
}
|
|
|
|
if (this.rulesText.Length > maxRulesLength)
|
|
this.rulesText += "\n\n" + DR.GetString(DR.More);
|
|
}
|
|
}
|
|
|
|
return this.rulesText;
|
|
}
|
|
}
|
|
|
|
private void OnMoveBranch(object sender, EventArgs e)
|
|
{
|
|
ActivityDesignerVerb moveBranchVerb = sender as ActivityDesignerVerb;
|
|
if (moveBranchVerb != null)
|
|
ParallelActivityDesigner.MoveDesigners(this, (bool)moveBranchVerb.Properties[DesignerUserDataKeys.MoveBranchKey]);
|
|
}
|
|
|
|
private void OnStatusMoveBranch(object sender, EventArgs e)
|
|
{
|
|
ActivityDesignerVerb moveBranchVerb = sender as ActivityDesignerVerb;
|
|
if (moveBranchVerb == null)
|
|
return;
|
|
|
|
bool enableVerb = false;
|
|
|
|
CompositeActivityDesigner parentDesigner = ParentDesigner;
|
|
if (!IsLocked && parentDesigner != null)
|
|
{
|
|
List<Activity> activities = new List<Activity>();
|
|
|
|
foreach (Activity containedActivity in ((CompositeActivity)parentDesigner.Activity).Activities)
|
|
{
|
|
if (!Helpers.IsAlternateFlowActivity(containedActivity))
|
|
activities.Add(containedActivity);
|
|
}
|
|
|
|
//ActivityCollection activities = ((CompositeActivity)parentDesigner.Activity).Activities;
|
|
bool moveleft = (bool)moveBranchVerb.Properties[DesignerUserDataKeys.MoveBranchKey];
|
|
int index = activities.IndexOf(Activity as Activity);
|
|
// "Move Left" should be disabled if the immediate proceeding branch is locked.
|
|
int proceedingLockedIndex = (index > 0) ? index - 1 : -1;
|
|
enableVerb = (index >= 0 && ((moveleft && index > 0 && (index - proceedingLockedIndex) > 0) || (!moveleft && index < activities.Count - 1)));
|
|
}
|
|
|
|
moveBranchVerb.Visible = (parentDesigner is ParallelActivityDesigner || parentDesigner is ActivityPreviewDesigner && !Helpers.IsAlternateFlowActivity(Activity));
|
|
moveBranchVerb.Enabled = enableVerb;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
#region Public Static Methods
|
|
public static ActivityDesigner GetRootDesigner(IServiceProvider serviceProvider)
|
|
{
|
|
if (serviceProvider == null)
|
|
throw new ArgumentNullException("serviceProvider");
|
|
|
|
IDesignerHost designerHost = serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost;
|
|
return (designerHost != null) ? GetDesigner(designerHost.RootComponent as Activity) as ActivityDesigner : null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns if the Activity is commented or is inside commented activity
|
|
/// </summary>
|
|
/// <param name="designer"></param>
|
|
/// <returns></returns>
|
|
public static bool IsCommentedActivity(Activity activity)
|
|
{
|
|
if (activity == null)
|
|
throw new ArgumentNullException("activity");
|
|
|
|
bool isNestedComment = false;
|
|
CompositeActivity parentActivity = activity.Parent;
|
|
while (parentActivity != null && !isNestedComment)
|
|
{
|
|
isNestedComment = (parentActivity != null && !parentActivity.Enabled);
|
|
parentActivity = parentActivity.Parent;
|
|
}
|
|
|
|
return isNestedComment;
|
|
}
|
|
#endregion
|
|
|
|
#region Public Methods
|
|
/// <summary>
|
|
/// Returns if a CompositeActivity can be set as parent of activity associated with designer.
|
|
/// This method is called in case of insertion operation such as Drag-Drop or Paste.
|
|
/// </summary>
|
|
/// <param name="parentActivity">CompositeActivity which can be potentially set as parent.</param>
|
|
/// <returns>True if the CompositeActivity can be set as parent of activity associated with designer, false otherwise.</returns>
|
|
public virtual bool CanBeParentedTo(CompositeActivityDesigner parentActivityDesigner)
|
|
{
|
|
if (parentActivityDesigner == null)
|
|
throw new ArgumentNullException("parentActivityDesigner");
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allows detection of the area hit on the designer.
|
|
/// </summary>
|
|
/// <param name="point">Point to test in logical coordinates.</param>
|
|
/// <returns>Information indicating where the hit happened</returns>
|
|
public virtual HitTestInfo HitTest(Point point)
|
|
{
|
|
HitTestInfo hitInfo = HitTestInfo.Nowhere;
|
|
if (ParentDesigner is FreeformActivityDesigner ||
|
|
(ParentDesigner == null && this is FreeformActivityDesigner))
|
|
{
|
|
//Check if the hit is on connection
|
|
ReadOnlyCollection<ConnectionPoint> connectionPoints = GetConnectionPoints(DesignerEdges.All);
|
|
for (int j = 0; j < connectionPoints.Count; j++)
|
|
{
|
|
if (connectionPoints[j].Bounds.Contains(point))
|
|
{
|
|
hitInfo = new ConnectionPointHitTestInfo(connectionPoints[j]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle bounds = Bounds;
|
|
if (bounds.Contains(point) && hitInfo == HitTestInfo.Nowhere)
|
|
{
|
|
HitTestLocations flags = (bounds.Contains(point)) ? HitTestLocations.Designer : HitTestLocations.None;
|
|
|
|
Rectangle hitRectangle = new Rectangle(bounds.Left, bounds.Top, bounds.Left - bounds.Left, bounds.Height);
|
|
flags |= (hitRectangle.Contains(point)) ? HitTestLocations.Left : flags;
|
|
|
|
hitRectangle = new Rectangle(bounds.Left, bounds.Top, bounds.Width, bounds.Height - bounds.Height);
|
|
flags |= (hitRectangle.Contains(point)) ? HitTestLocations.Top : flags;
|
|
|
|
hitRectangle = new Rectangle(bounds.Right, bounds.Top, bounds.Width - bounds.Width, bounds.Height);
|
|
flags |= (hitRectangle.Contains(point)) ? HitTestLocations.Right : flags;
|
|
|
|
hitRectangle = new Rectangle(bounds.Left, bounds.Bottom, bounds.Width, bounds.Bottom - bounds.Bottom);
|
|
flags |= (hitRectangle.Contains(point)) ? HitTestLocations.Bottom : flags;
|
|
|
|
hitInfo = new HitTestInfo(this, flags);
|
|
}
|
|
|
|
return hitInfo;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Brings designer in viewable area
|
|
/// </summary>
|
|
public void EnsureVisible()
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
parentView.EnsureVisible(Activity);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the points used to connect the designer. Points are in logical coordinates.
|
|
/// </summary>
|
|
public virtual ReadOnlyCollection<ConnectionPoint> GetConnectionPoints(DesignerEdges edges)
|
|
{
|
|
List<ConnectionPoint> connectionPoints = new List<ConnectionPoint>();
|
|
|
|
if ((edges & DesignerEdges.Left) > 0)
|
|
{
|
|
for (int i = 0; i < GetConnections(DesignerEdges.Left).Count; i++)
|
|
connectionPoints.Add(new ConnectionPoint(this, DesignerEdges.Left, i));
|
|
}
|
|
|
|
if ((edges & DesignerEdges.Right) > 0)
|
|
{
|
|
for (int i = 0; i < GetConnections(DesignerEdges.Right).Count; i++)
|
|
connectionPoints.Add(new ConnectionPoint(this, DesignerEdges.Right, i));
|
|
}
|
|
|
|
if ((edges & DesignerEdges.Top) > 0)
|
|
{
|
|
for (int i = 0; i < GetConnections(DesignerEdges.Top).Count; i++)
|
|
connectionPoints.Add(new ConnectionPoint(this, DesignerEdges.Top, i));
|
|
}
|
|
|
|
if ((edges & DesignerEdges.Bottom) > 0)
|
|
{
|
|
for (int i = 0; i < GetConnections(DesignerEdges.Bottom).Count; i++)
|
|
connectionPoints.Add(new ConnectionPoint(this, DesignerEdges.Bottom, i));
|
|
}
|
|
|
|
return connectionPoints.AsReadOnly();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invalidates the entire workflow designer
|
|
/// </summary>
|
|
public void Invalidate()
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
{
|
|
parentView.InvalidateLogicalRectangle(Bounds);
|
|
|
|
GlyphManager glyphManager = GetService(typeof(IDesignerGlyphProviderService)) as GlyphManager;
|
|
if (glyphManager != null)
|
|
{
|
|
foreach (DesignerGlyph glyph in glyphManager.GetDesignerGlyphs(this))
|
|
parentView.InvalidateLogicalRectangle(glyph.GetBounds(this, false));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invalidates specified rectangle on the designer
|
|
/// </summary>
|
|
/// <param name="rectangle">Rectangle to invalidate</param>
|
|
public void Invalidate(Rectangle rectangle)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
{
|
|
rectangle = Rectangle.Intersect(Bounds, rectangle);
|
|
parentView.InvalidateLogicalRectangle(rectangle);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get image of the activity designer on specified graphics
|
|
/// </summary>
|
|
/// <param name="compatibleGraphics">Graphics objects to draw image</param>
|
|
/// <returns>Image which is drawn</returns>
|
|
public Image GetPreviewImage(Graphics compatibleGraphics)
|
|
{
|
|
if (compatibleGraphics == null)
|
|
throw new ArgumentNullException("compatibleGraphics");
|
|
|
|
//Update the layout
|
|
if (Activity.Site == null)
|
|
{
|
|
((IWorkflowDesignerMessageSink)this).OnLayoutSize(compatibleGraphics);
|
|
((IWorkflowDesignerMessageSink)this).OnLayoutPosition(compatibleGraphics);
|
|
}
|
|
|
|
AmbientTheme ambientTheme = WorkflowTheme.CurrentTheme.AmbientTheme;
|
|
Bitmap designerImage = new Bitmap(Size.Width + (4 * ambientTheme.Margin.Width), Size.Height + (4 * ambientTheme.Margin.Height), PixelFormat.Format32bppArgb);
|
|
|
|
GlyphManager glyphManager = (Activity != null && Activity.Site != null) ? GetService(typeof(IDesignerGlyphProviderService)) as GlyphManager : null;
|
|
|
|
using (Graphics graphics = Graphics.FromImage(designerImage))
|
|
using (Brush transparentBrush = new SolidBrush(Color.FromArgb(0, 255, 0, 255)))
|
|
{
|
|
graphics.FillRectangle(transparentBrush, 0, 0, designerImage.Width, designerImage.Height);
|
|
graphics.TranslateTransform(-Location.X + 2 * ambientTheme.Margin.Width, -Location.Y + 2 * ambientTheme.Margin.Height);
|
|
|
|
//We need to go thru nested designers to generate the preview
|
|
Rectangle bounds = Bounds;
|
|
Rectangle viewPort = new Rectangle(bounds.Location, new Size(bounds.Width + 1, bounds.Height + 1));
|
|
Queue<ActivityDesigner> designers = new Queue<ActivityDesigner>();
|
|
designers.Enqueue(this);
|
|
while (designers.Count > 0)
|
|
{
|
|
ActivityDesigner designer = designers.Dequeue();
|
|
designer.OnPaint(new ActivityDesignerPaintEventArgs(graphics, designer.Bounds, viewPort, designer.DesignerTheme));
|
|
|
|
ActivityDesignerGlyphCollection glyphs = (glyphManager != null) ? glyphManager.GetDesignerGlyphs(designer) : Glyphs;
|
|
foreach (DesignerGlyph glyph in glyphs)
|
|
{
|
|
//
|
|
if (!(glyph is SelectionGlyph))
|
|
glyph.Draw(graphics, designer);
|
|
}
|
|
|
|
CompositeActivityDesigner compositeDesigner = designer as CompositeActivityDesigner;
|
|
if (compositeDesigner != null)
|
|
{
|
|
foreach (ActivityDesigner containedDesigner in compositeDesigner.ContainedDesigners)
|
|
{
|
|
if (containedDesigner != null && compositeDesigner.Expanded && compositeDesigner.IsContainedDesignerVisible(containedDesigner))
|
|
designers.Enqueue(containedDesigner);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return designerImage;
|
|
}
|
|
#endregion
|
|
|
|
#region Protected Methods
|
|
/// <summary>
|
|
/// Initializes the designer with associated activity.
|
|
/// </summary>
|
|
/// <param name="activity">Activity with which the designer needs to be initialized.</param>
|
|
protected virtual void Initialize(Activity activity)
|
|
{
|
|
if (activity == null)
|
|
throw new ArgumentNullException("activity");
|
|
|
|
if (IsRootDesigner)
|
|
{
|
|
// Listen for the completed load. When finished, we need to select the form. We don'
|
|
// want to do it before we're done, however, or else the dimensions of the selection rectangle
|
|
// could be off because during load, change events are not fired.
|
|
IDesignerHost designerHost = (IDesignerHost)GetService(typeof(IDesignerHost));
|
|
if (designerHost != null && InvokingDesigner == null)
|
|
designerHost.LoadComplete += new EventHandler(OnLoadComplete);
|
|
|
|
IComponentChangeService changeService = GetService(typeof(IComponentChangeService)) as IComponentChangeService;
|
|
if (changeService != null)
|
|
{
|
|
changeService.ComponentChanged += new ComponentChangedEventHandler(OnComponentChanged);
|
|
changeService.ComponentRename += new ComponentRenameEventHandler(OnComponentRenamed);
|
|
}
|
|
}
|
|
|
|
this.Text = (!String.IsNullOrEmpty(activity.Name)) ? activity.Name : activity.GetType().Name;
|
|
this.Image = StockImage;
|
|
|
|
//We need to update the Verbs when the designer first loads up
|
|
RefreshDesignerVerbs();
|
|
|
|
if (IsLocked)
|
|
DesignerHelpers.MakePropertiesReadOnly(activity.Site, activity);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Disposes the resources held by the designer.
|
|
/// </summary>
|
|
/// <param name="disposing">True if the designer is being disposed, false if the designer is being finalized.</param>
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
if (IsRootDesigner)
|
|
{
|
|
if (this.workflowView != null)
|
|
{
|
|
this.workflowView.Dispose();
|
|
this.workflowView = null;
|
|
}
|
|
|
|
IDesignerHost designerHost = GetService(typeof(IDesignerHost)) as IDesignerHost;
|
|
if (designerHost != null && InvokingDesigner == null && Activity == designerHost.RootComponent)
|
|
designerHost.LoadComplete -= new EventHandler(OnLoadComplete);
|
|
|
|
IComponentChangeService changeService = GetService(typeof(IComponentChangeService)) as IComponentChangeService;
|
|
if (changeService != null)
|
|
{
|
|
changeService.ComponentChanged -= new ComponentChangedEventHandler(OnComponentChanged);
|
|
changeService.ComponentRename -= new ComponentRenameEventHandler(OnComponentRenamed);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the points used to connect the designer. Points are in logical coordinates.
|
|
/// </summary>
|
|
protected internal virtual ReadOnlyCollection<Point> GetConnections(DesignerEdges edges)
|
|
{
|
|
Rectangle bounds = Bounds;
|
|
|
|
List<Point> connections = new List<Point>();
|
|
if ((edges & DesignerEdges.Left) > 0)
|
|
connections.Add(new Point(bounds.Left, bounds.Top + bounds.Height / 2));
|
|
|
|
if ((edges & DesignerEdges.Top) > 0)
|
|
connections.Add(new Point(bounds.Left + bounds.Width / 2, bounds.Top));
|
|
|
|
if ((edges & DesignerEdges.Right) > 0)
|
|
connections.Add(new Point(bounds.Right, bounds.Top + bounds.Height / 2));
|
|
|
|
if ((edges & DesignerEdges.Bottom) > 0)
|
|
connections.Add(new Point(bounds.Left + bounds.Width / 2, bounds.Bottom));
|
|
|
|
return connections.AsReadOnly();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Perform default UI action associated with the designer.
|
|
/// Example: Emit method associated with default event in code beside file on double click.
|
|
/// </summary>
|
|
protected virtual void DoDefaultAction()
|
|
{
|
|
if (IsLocked)
|
|
return;
|
|
|
|
DefaultEventAttribute defaultEventAttribute = TypeDescriptor.GetAttributes(Activity)[typeof(DefaultEventAttribute)] as DefaultEventAttribute;
|
|
if (defaultEventAttribute == null || defaultEventAttribute.Name == null || defaultEventAttribute.Name.Length == 0)
|
|
return;
|
|
|
|
ActivityBindPropertyDescriptor defaultPropEvent = TypeDescriptor.GetProperties(Activity)[defaultEventAttribute.Name] as ActivityBindPropertyDescriptor;
|
|
if (defaultPropEvent != null)
|
|
{
|
|
object value = defaultPropEvent.GetValue(Activity);
|
|
if (!(value is ActivityBind))
|
|
{
|
|
IEventBindingService eventBindingService = (IEventBindingService)GetService(typeof(IEventBindingService));
|
|
if (eventBindingService != null)
|
|
{
|
|
EventDescriptor eventDesc = eventBindingService.GetEvent(defaultPropEvent.RealPropertyDescriptor);
|
|
if (eventDesc != null)
|
|
{
|
|
string handler = defaultPropEvent.RealPropertyDescriptor.GetValue(Activity) as string;
|
|
if (string.IsNullOrEmpty(handler))
|
|
handler = DesignerHelpers.CreateUniqueMethodName(Activity, eventDesc.Name, eventDesc.EventType);
|
|
|
|
defaultPropEvent.SetValue(Activity, handler);
|
|
eventBindingService.ShowCode(Activity, eventDesc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// When overridden in a derived class, allows a designer to add items to the set of attributes that it exposes through a TypeDescriptor.
|
|
/// </summary>
|
|
/// <param name="attributes">The Attribute objects for the class of the activity. The keys in the dictionary of attributes are the TypeID values of the attributes.</param>
|
|
protected virtual void PreFilterAttributes(IDictionary attributes)
|
|
{
|
|
if (attributes == null)
|
|
throw new ArgumentNullException("attributes");
|
|
}
|
|
|
|
/// <summary>
|
|
/// When overridden in a derived class, allows a designer to add items to the set of properties that it exposes through a TypeDescriptor.
|
|
/// </summary>
|
|
/// <param name="properties">The PropertyDescriptor objects that represent the properties of the class of the activity. The keys in the dictionary of properties are property names.</param>
|
|
protected virtual void PreFilterProperties(IDictionary properties)
|
|
{
|
|
if (properties == null)
|
|
throw new ArgumentNullException("properties");
|
|
}
|
|
|
|
/// <summary>
|
|
/// When overridden in a derived class, allows a designer to add items to the set of events that it exposes through a TypeDescriptor.
|
|
/// </summary>
|
|
/// <param name="events">The EventDescriptor objects that represent the events of the class of the activity. The keys in the dictionary of events are event names.</param>
|
|
protected virtual void PreFilterEvents(IDictionary events)
|
|
{
|
|
if (events == null)
|
|
throw new ArgumentNullException("events");
|
|
}
|
|
|
|
/// <summary>
|
|
/// When overridden in a derived class, allows a designer to change or remove items from the set of attributes that it exposes through a TypeDescriptor.
|
|
/// </summary>
|
|
/// <param name="attributes">The Attribute objects for the class of the activity. The keys in the dictionary of attributes are the TypeID values of the attributes.</param>
|
|
protected virtual void PostFilterAttributes(IDictionary attributes)
|
|
{
|
|
if (attributes == null)
|
|
throw new ArgumentNullException("attributes");
|
|
}
|
|
|
|
/// <summary>
|
|
/// When overridden in a derived class, allows a designer to change or remove items from the set of properties that it exposes through a TypeDescriptor.
|
|
/// </summary>
|
|
/// <param name="properties">The PropertyDescriptor objects that represent the properties of the class of the activity. The keys in the dictionary of properties are property names.</param>
|
|
protected virtual void PostFilterProperties(IDictionary properties)
|
|
{
|
|
if (properties == null)
|
|
throw new ArgumentNullException("properties");
|
|
|
|
// NOTE: I have to do this work around, reason being IExtenderProvider.CanExtend is not used
|
|
// to determine whether the properties should be extended or not. So I am fixing it
|
|
// on designer part
|
|
StringCollection removedProperties = new StringCollection();
|
|
foreach (DictionaryEntry entry in properties)
|
|
{
|
|
PropertyDescriptor prop = entry.Value as PropertyDescriptor;
|
|
ExtenderProvidedPropertyAttribute eppa = prop.Attributes[typeof(ExtenderProvidedPropertyAttribute)] as ExtenderProvidedPropertyAttribute;
|
|
if (eppa != null && eppa.Provider != null && !eppa.Provider.CanExtend(Activity))
|
|
removedProperties.Add(entry.Key as string);
|
|
}
|
|
|
|
foreach (string removedPropoerty in removedProperties)
|
|
properties.Remove(removedPropoerty);
|
|
|
|
PropertyDescriptorFilter.FilterProperties(Activity.Site, Activity, properties);
|
|
}
|
|
|
|
/// <summary>
|
|
/// When overridden in a derived class, allows a designer to change or remove items from the set of events that it exposes through a TypeDescriptor.
|
|
/// </summary>
|
|
/// <param name="events">The EventDescriptor objects that represent the events of the class of the activity. The keys in the dictionary of events are event names.</param>
|
|
protected virtual void PostFilterEvents(IDictionary events)
|
|
{
|
|
if (events == null)
|
|
throw new ArgumentNullException("events");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Attempts to retrieve the specified type of service from the designer's activity's design mode site.
|
|
/// </summary>
|
|
/// <param name="serviceType">The type of service to request.</param>
|
|
/// <returns>An object implementing the requested service, or a null reference (Nothing in Visual Basic) if the service cannot be resolved.</returns>
|
|
protected object GetService(Type serviceType)
|
|
{
|
|
if (serviceType == null)
|
|
throw new ArgumentNullException("serviceType");
|
|
|
|
if (this.activity != null && this.activity.Site != null)
|
|
return this.activity.Site.GetService(serviceType);
|
|
else
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the users begins to drag mouse on the designer.
|
|
/// </summary>
|
|
/// <param name="initialDragPoint">Point where the drag started in logical coordinates</param>
|
|
/// <param name="e">MouseEventArgs containing event data.</param>
|
|
protected virtual void OnMouseDragBegin(Point initialDragPoint, MouseEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the users drags mouse over the designer.
|
|
/// </summary>
|
|
/// <param name="e">MouseEventArgs containing event data.</param>
|
|
protected virtual void OnMouseDragMove(MouseEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the mouse drag ends.
|
|
/// </summary>
|
|
protected virtual void OnMouseDragEnd()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the mouse cursor enters the designer bounds.
|
|
/// </summary>
|
|
/// <param name="e">MouseEventArgs containing event data.</param>
|
|
protected virtual void OnMouseEnter(MouseEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
|
|
if (IsVisible)
|
|
{
|
|
if (ShowSmartTag)
|
|
SmartTagVisible = true;
|
|
|
|
ShowInfoTip(InfoTipTitle, InfoTipText);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the mouse button is clicked when mouse cursor is in designer bounds.
|
|
/// </summary>
|
|
/// <param name="e">MouseEventArgs containing event data.</param>
|
|
protected virtual void OnMouseDown(MouseEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the mouse cursor is moving in designer bounds.
|
|
/// </summary>
|
|
/// <param name="e">MouseEventArgs containing event data.</param>
|
|
protected virtual void OnMouseMove(MouseEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
|
|
if (IsVisible)
|
|
ShowInfoTip(InfoTipTitle, InfoTipText);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Called when the mouse cursor is in designer bounds.
|
|
/// </summary>
|
|
/// <param name="e">MouseEventArgs containing event data.</param>
|
|
protected virtual void OnMouseHover(MouseEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
|
|
if (IsVisible)
|
|
ShowInfoTip(InfoTipTitle, InfoTipText);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the moused button is released when mouse cursor is in designer bounds.
|
|
/// </summary>
|
|
/// <param name="e">MouseEventArgs containing event data.</param>
|
|
protected virtual void OnMouseUp(MouseEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the mouse button is clicked multiple times on the designer
|
|
/// </summary>
|
|
/// <param name="e">MouseEventArgs containing event data.</param>
|
|
protected virtual void OnMouseDoubleClick(MouseEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the mouse cursor leaves designer bounds.
|
|
/// </summary>
|
|
protected virtual void OnMouseLeave()
|
|
{
|
|
if (ShowSmartTag)
|
|
SmartTagVisible = false;
|
|
|
|
ShowInfoTip(String.Empty);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the mouse capture changes
|
|
/// </summary>
|
|
protected virtual void OnMouseCaptureChanged()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the drag drop operation is in progress and mouse cursor enters the designer bounds.
|
|
/// </summary>
|
|
/// <param name="e">Drag drop event arguments.</param>
|
|
protected virtual void OnDragEnter(ActivityDragEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the drag drop operation is in progress and mouse cursor is inside the designer bounds.
|
|
/// </summary>
|
|
/// <param name="e">Drag drop event arguments.</param>
|
|
protected virtual void OnDragOver(ActivityDragEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the drag drop operation is in progress and mouse cursor leaves the designer bounds.
|
|
/// </summary>
|
|
protected virtual void OnDragLeave()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the drag drop operation is completed inside designer bounds.
|
|
/// </summary>
|
|
/// <param name="e">Drag drop event arguments.</param>
|
|
protected virtual void OnDragDrop(ActivityDragEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the visual cues for feedback given to the user when performing drag drop operation.
|
|
/// </summary>
|
|
/// <param name="e">A GiveFeedbackEventArgs that contains the event data.</param>
|
|
protected virtual void OnGiveFeedback(GiveFeedbackEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Controls if the drag drop operation should continue.
|
|
/// </summary>
|
|
/// <param name="e">A QueryContinueDragEventArgs that contains the event data.</param>
|
|
protected virtual void OnQueryContinueDrag(QueryContinueDragEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when key is pressed when designer has keyboard focus.
|
|
/// </summary>
|
|
/// <param name="e"></param>
|
|
protected virtual void OnKeyDown(KeyEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when key is released when designer has keyboard focus.
|
|
/// </summary>
|
|
/// <param name="e"></param>
|
|
protected virtual void OnKeyUp(KeyEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when scroll position is changed
|
|
/// </summary>
|
|
/// <param name="sender">Scrollbar sending the message</param>
|
|
/// <param name="value">New value of the scrolled position</param>
|
|
protected virtual void OnScroll(ScrollBar sender, int value)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allows designer to process raw win32 message
|
|
/// </summary>
|
|
/// <param name="message">Message structure containing details of the message to be processed</param>
|
|
protected virtual void OnProcessMessage(Message message)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called to refresh the configuration errors associated with designers.
|
|
/// </summary>
|
|
protected internal virtual void RefreshDesignerActions()
|
|
{
|
|
this.designerActions = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when user clicks on configuration errors associated with the designer.
|
|
/// </summary>
|
|
/// <param name="designerAction">Designer action associated with configuration error.</param>
|
|
protected internal virtual void OnExecuteDesignerAction(DesignerAction designerAction)
|
|
{
|
|
if (designerAction == null)
|
|
throw new ArgumentNullException("designerAction");
|
|
|
|
ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
|
|
if (selectionService != null)
|
|
selectionService.SetSelectedComponents(new object[] { Activity }, SelectionTypes.Replace);
|
|
|
|
string propName = designerAction.PropertyName as string;
|
|
if (propName != null && propName.Length > 0)
|
|
{
|
|
IExtendedUIService uiService = GetService(typeof(IExtendedUIService)) as IExtendedUIService;
|
|
if (uiService != null)
|
|
uiService.NavigateToProperty(propName);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called to notify the designer if the SmartTag is being shown or hidden
|
|
/// </summary>
|
|
/// <param name="visible">Indicates if the SmartTag is being shown or hidden</param>
|
|
protected virtual void OnSmartTagVisibilityChanged(bool visible)
|
|
{
|
|
Rectangle rectangle = smartTag.GetBounds(this, true);
|
|
Rectangle textRectangle = TextRectangle;
|
|
if (!textRectangle.Size.IsEmpty)
|
|
rectangle = Rectangle.Union(textRectangle, rectangle);
|
|
Invalidate(rectangle);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shows the designer verbs associated with smarttag at specific point
|
|
/// </summary>
|
|
/// <param name="smartTagPoint">Point at which to show the actions</param>
|
|
protected virtual void OnShowSmartTagVerbs(Point smartTagPoint)
|
|
{
|
|
ActivityDesignerVerb[] verbs = null;
|
|
SmartTagVerbs.CopyTo(verbs, 0);
|
|
DesignerHelpers.ShowDesignerVerbs(this, PointToScreen(smartTagPoint), verbs);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Notifies the designer that the associated theme has changed.
|
|
/// </summary>
|
|
protected virtual void OnThemeChange(ActivityDesignerTheme newTheme)
|
|
{
|
|
if (newTheme == null)
|
|
throw new ArgumentNullException("newTheme");
|
|
|
|
this.Image = StockImage;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Stores the UI state of the designer in binary stream.
|
|
/// </summary>
|
|
/// <param name="writer">BinaryWriter used to store the state.</param>
|
|
protected virtual void SaveViewState(BinaryWriter writer)
|
|
{
|
|
if (writer == null)
|
|
throw new ArgumentNullException("writer");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restores the UI state of the designer from binary stream.
|
|
/// </summary>
|
|
/// <param name="reader">BinaryReader used to restore the designer state.</param>
|
|
/// <returns></returns>
|
|
protected virtual void LoadViewState(BinaryReader reader)
|
|
{
|
|
if (reader == null)
|
|
throw new ArgumentNullException("reader");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Return if an activity type is valid in context of a root designer. This function is called only if
|
|
/// the designer is a root designer
|
|
/// </summary>
|
|
/// <param name="activityType">Type of the activity being queried</param>
|
|
/// <returns></returns>
|
|
protected virtual bool IsSupportedActivityType(Type activityType)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
protected virtual WorkflowView CreateView(ViewTechnology viewTechnology)
|
|
{
|
|
WorkflowView workflowView = new WorkflowView(Activity.Site as IServiceProvider);
|
|
workflowView.ShowToolContainer = true;
|
|
return workflowView;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Refreshes the ActivityDesignerVerbs associted with the designer by calling status handler.
|
|
/// </summary>
|
|
protected void RefreshDesignerVerbs()
|
|
{
|
|
if (Activity != null && Activity.Site != null)
|
|
{
|
|
DesignerVerbCollection verbs = ((IDesigner)this).Verbs;
|
|
if (verbs != null)
|
|
{
|
|
foreach (DesignerVerb verb in verbs)
|
|
{
|
|
//This will cause us to send the status update for ActivityDesignerVerb
|
|
int status = verb.OleStatus;
|
|
status = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draws the visual representation of activity at design time.
|
|
/// </summary>
|
|
/// <param name="e">ActivityDesignerPaintEventArgs holding drawing arguments</param>
|
|
protected virtual void OnPaint(ActivityDesignerPaintEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
|
|
ActivityDesignerPaint.DrawDesignerBackground(e.Graphics, this);
|
|
|
|
if (!String.IsNullOrEmpty(Text) && !TextRectangle.Size.IsEmpty)
|
|
{
|
|
Font font = (SmartTagVisible) ? e.DesignerTheme.BoldFont : e.DesignerTheme.Font;
|
|
ActivityDesignerPaint.DrawText(e.Graphics, font, Text, TextRectangle, StringAlignment.Near, e.AmbientTheme.TextQuality, e.DesignerTheme.ForegroundBrush);
|
|
}
|
|
|
|
if (Image != null && !ImageRectangle.Size.IsEmpty)
|
|
ActivityDesignerPaint.DrawImage(e.Graphics, Image, ImageRectangle, DesignerContentAlignment.Fill);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called to layout the position of contained visual cues or designers.
|
|
/// </summary>
|
|
/// <param name="e">ActivityDesignerLayoutEventArgs holding layout arguments</param>
|
|
protected virtual void OnLayoutPosition(ActivityDesignerLayoutEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called to set the size of the visual cues or designers contained within the designer.
|
|
/// </summary>
|
|
/// <param name="e">ActivityDesignerLayoutEventArgs holding layout arguments</param>
|
|
protected virtual Size OnLayoutSize(ActivityDesignerLayoutEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
|
|
//GetVisible is an expensive call so we make sure that we keep it buffered in OnLayoutSize
|
|
//otherwise drawing slows down. The visiblity change always triggers layouting and hence we
|
|
//can safely buffer this variable
|
|
this.isVisible = GetVisible();
|
|
|
|
if (!String.IsNullOrEmpty(Text))
|
|
{
|
|
//Calculate the size of the text, we allow 10 characters per line and maximum of 2 lines
|
|
Size actualTextSize = ActivityDesignerPaint.MeasureString(e.Graphics, e.DesignerTheme.BoldFont, Text, StringAlignment.Center, Size.Empty);
|
|
Size requestedLineSize = actualTextSize;
|
|
requestedLineSize.Width /= Text.Length;
|
|
requestedLineSize.Width += ((requestedLineSize.Width % Text.Length) > 0) ? 1 : 0;
|
|
requestedLineSize.Width *= Math.Min(Text.Length, ActivityDesigner.MaximumCharsPerLine - 1);
|
|
|
|
this.textSize.Width = MinimumSize.Width - 2 * e.AmbientTheme.Margin.Width;
|
|
if (Image != null)
|
|
this.textSize.Width -= e.DesignerTheme.ImageSize.Width + e.AmbientTheme.Margin.Width;
|
|
this.textSize.Width = Math.Min(this.textSize.Width, actualTextSize.Width);
|
|
this.textSize.Width = Math.Max(this.textSize.Width, requestedLineSize.Width);
|
|
|
|
//We calculate the text size in onlayoutsize as we get access to the graphics and font information in this function
|
|
this.textSize.Height = requestedLineSize.Height;
|
|
int textLines = actualTextSize.Width / this.textSize.Width;
|
|
textLines += ((actualTextSize.Width % this.textSize.Width) > 0) ? 1 : 0;
|
|
textLines = Math.Min(textLines, ActivityDesigner.MaximumTextLines);
|
|
this.textSize.Height *= textLines;
|
|
}
|
|
else
|
|
{
|
|
this.textSize = Size.Empty;
|
|
}
|
|
|
|
Size size = Size.Empty;
|
|
size.Width = 2 * e.AmbientTheme.Margin.Width + ((Image != null) ? (e.DesignerTheme.ImageSize.Width + e.AmbientTheme.Margin.Width) : 0) + this.textSize.Width;
|
|
size.Height = e.AmbientTheme.Margin.Height + Math.Max(e.DesignerTheme.ImageSize.Height, this.textSize.Height) + e.AmbientTheme.Margin.Height;
|
|
return size;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the user starts to visually resize the designer when designer is inside freeform designer
|
|
/// </summary>
|
|
/// <param name="e"></param>
|
|
protected virtual void OnBeginResizing(ActivityDesignerResizeEventArgs e)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the user is visually resizing the designer when designer is inside freeform designer
|
|
/// </summary>
|
|
/// <param name="e">ActivityDesignerResizeEventArgs specifying the edge being used to resize and new bounds</param>
|
|
protected virtual void OnResizing(ActivityDesignerResizeEventArgs e)
|
|
{
|
|
FreeformActivityDesigner.SetDesignerBounds(this, e.Bounds);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when user is done resizing the designer
|
|
/// </summary>
|
|
protected virtual void OnEndResizing()
|
|
{
|
|
PerformLayout();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called to check if connection can be established between source and target designer
|
|
/// </summary>
|
|
/// <param name="source">Source connection point</param>
|
|
/// <param name="target">Target connection point</param>
|
|
/// <returns>True if connection can be established, false otherwise</returns>
|
|
protected virtual bool CanConnect(ConnectionPoint source, ConnectionPoint target)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when connection is established between two connection points
|
|
/// </summary>
|
|
/// <param name="source">Source connection point</param>
|
|
/// <param name="target">Target connection point</param>
|
|
protected virtual void OnConnected(ConnectionPoint source, ConnectionPoint target)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the activity associated with the designer is changed.
|
|
/// </summary>
|
|
/// <param name="e">A ActivityChangedEventArgs containing information about what changed.</param>
|
|
protected virtual void OnActivityChanged(ActivityChangedEventArgs e)
|
|
{
|
|
if (e == null)
|
|
throw new ArgumentNullException("e");
|
|
|
|
if (e.Member != null && e.Member.Name != null && e.Member.Name.Equals("Name"))
|
|
this.Text = Activity.Name;
|
|
|
|
//Whenever property on the component changes we update the verb status
|
|
//We have to do a type descriptor refresh here as we need to not only update the designer verbs
|
|
//but also the global commands
|
|
//For contained activity changed we refresh thru the activity list changed
|
|
if (!(e.OldValue is ActivityCollectionChangeEventArgs))
|
|
RefreshDesignerVerbs();
|
|
|
|
IUIService uiservice = GetService(typeof(IUIService)) as IUIService;
|
|
if (uiservice != null)
|
|
uiservice.SetUIDirty();
|
|
|
|
//Clear and refresh the rules text
|
|
this.rulesText = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shows specified tooltip
|
|
/// </summary>
|
|
/// <param name="title">String specifying the tooltip title</param>
|
|
/// <param name="infoTip">String specifying the tooltip to display</param>
|
|
protected void ShowInfoTip(string title, string infoTip)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
parentView.ShowInfoTip(title, infoTip);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shows specified tooltip
|
|
/// </summary>
|
|
/// <param name="infoTip">String specifying the tooltip to display</param>
|
|
protected void ShowInfoTip(string infoTip)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
parentView.ShowInfoTip(infoTip);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Shows tooltip at specified location
|
|
/// </summary>
|
|
/// <param name="infoTip">String specifying the tooltip to display</param>
|
|
/// <param name="rectangle">Rectangle where to display tooltip</param>
|
|
protected void ShowInPlaceTip(string infoTip, Rectangle rectangle)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
parentView.ShowInPlaceToolTip(infoTip, parentView.LogicalRectangleToClient(rectangle));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates the layout of the designer
|
|
/// </summary>
|
|
protected void PerformLayout()
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
parentView.PerformLayout(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Transforms point from activity designer coordinate system to screen
|
|
/// </summary>
|
|
/// <param name="point">Point in activity designer coordinate system</param>
|
|
/// <returns>Point in screen coordinate system</returns>
|
|
protected Point PointToScreen(Point point)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
return parentView.LogicalPointToScreen(point);
|
|
else
|
|
return point;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Transforms point from screen coordinate system to activity designer coordinate system
|
|
/// </summary>
|
|
/// <param name="point">Point in screen coordinate system</param>
|
|
/// <returns>Point in activity designer coordinate system</returns>
|
|
protected Point PointToLogical(Point point)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
return parentView.ScreenPointToLogical(point);
|
|
else
|
|
return point;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Transforms rectangle from activity designer coordinate system to screen
|
|
/// </summary>
|
|
/// <param name="rectangle">Rectangle in activity designer coordinate system</param>
|
|
/// <returns>Rectangle in screen coordinate system</returns>
|
|
protected Rectangle RectangleToScreen(Rectangle rectangle)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
return new Rectangle(PointToScreen(rectangle.Location), parentView.LogicalSizeToClient(rectangle.Size));
|
|
else
|
|
return rectangle;
|
|
|
|
}
|
|
|
|
//for the accessible object
|
|
internal Rectangle InternalRectangleToScreen(Rectangle rectangle)
|
|
{
|
|
return RectangleToScreen(rectangle);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Transforms rectangle from screen coordinate system to activity designer coordinate system
|
|
/// </summary>
|
|
/// <param name="rectangle">Rectangle in screen coordinate system</param>
|
|
/// <returns>Rectangle in activity designer coordinate system</returns>
|
|
protected Rectangle RectangleToLogical(Rectangle rectangle)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
return new Rectangle(PointToLogical(rectangle.Location), parentView.ClientSizeToLogical(rectangle.Size));
|
|
else
|
|
return rectangle;
|
|
}
|
|
#endregion
|
|
|
|
#region Private static Methods
|
|
internal static ActivityDesigner GetSafeRootDesigner(IServiceProvider serviceProvider)
|
|
{
|
|
return (serviceProvider != null) ? ActivityDesigner.GetRootDesigner(serviceProvider) : null;
|
|
}
|
|
|
|
internal static ActivityDesigner GetDesigner(Activity activity)
|
|
{
|
|
ActivityDesigner designer = null;
|
|
|
|
if (activity != null && activity.Site != null)
|
|
{
|
|
IDesignerHost designerHost = activity.Site.GetService(typeof(IDesignerHost)) as IDesignerHost;
|
|
if (designerHost != null)
|
|
designer = designerHost.GetDesigner(activity) as ActivityDesigner;
|
|
}
|
|
|
|
return designer;
|
|
}
|
|
|
|
internal static string GetActivityDescription(Type activityType)
|
|
{
|
|
if (activityType == null)
|
|
return null;
|
|
|
|
object[] attribs = activityType.GetCustomAttributes(typeof(DescriptionAttribute), false);
|
|
if (attribs != null && attribs.GetLength(0) == 0)
|
|
attribs = activityType.GetCustomAttributes(typeof(DescriptionAttribute), true);
|
|
|
|
DescriptionAttribute descriptionAttribute = (attribs != null && attribs.GetLength(0) > 0) ? attribs[0] as DescriptionAttribute : null;
|
|
return (descriptionAttribute != null) ? descriptionAttribute.Description : String.Empty;
|
|
}
|
|
|
|
internal static CompositeActivityDesigner GetParentDesigner(object obj)
|
|
{
|
|
// get parent designer
|
|
CompositeActivityDesigner parentDesigner = null;
|
|
if (obj is HitTestInfo)
|
|
{
|
|
parentDesigner = ((HitTestInfo)obj).AssociatedDesigner as CompositeActivityDesigner;
|
|
}
|
|
else if (obj is Activity)
|
|
{
|
|
ActivityDesigner activityDesigner = ActivityDesigner.GetDesigner(obj as Activity);
|
|
if (activityDesigner != null)
|
|
parentDesigner = activityDesigner.ParentDesigner;
|
|
}
|
|
|
|
return parentDesigner;
|
|
}
|
|
|
|
internal static ActivityDesigner CreateTransientDesigner(Activity activity)
|
|
{
|
|
ActivityDesigner activityDesigner = new ActivityDesigner();
|
|
ActivityDesignerTheme designerTheme = activityDesigner.DesignerTheme;
|
|
|
|
using (Bitmap temporaryBitmap = new Bitmap(designerTheme.Size.Width, designerTheme.Size.Height, PixelFormat.Format32bppArgb))
|
|
using (Graphics graphics = Graphics.FromImage(temporaryBitmap))
|
|
{
|
|
activityDesigner.Image = ActivityToolboxItem.GetToolboxImage(activity.GetType());
|
|
activityDesigner.Location = new Point(-1, -1);
|
|
activityDesigner.Location = Point.Empty;
|
|
activityDesigner.Size = activityDesigner.OnLayoutSize(new ActivityDesignerLayoutEventArgs(graphics, activityDesigner.DesignerTheme));
|
|
}
|
|
|
|
return activityDesigner;
|
|
}
|
|
|
|
internal static Type GetDesignerType(IServiceProvider serviceProvider, Type activityType, Type designerBaseType)
|
|
{
|
|
Type designerType = null;
|
|
AttributeCollection attribs = TypeDescriptor.GetAttributes(activityType);
|
|
foreach (Attribute attribute in attribs)
|
|
{
|
|
DesignerAttribute designerAttribute = attribute as DesignerAttribute;
|
|
if (designerAttribute != null && (designerBaseType == null || designerAttribute.DesignerBaseTypeName == designerBaseType.AssemblyQualifiedName))
|
|
{
|
|
int index = designerAttribute.DesignerTypeName.IndexOf(',');
|
|
string designerTypeName = (index >= 0) ? designerAttribute.DesignerTypeName.Substring(0, index) : designerAttribute.DesignerTypeName;
|
|
designerType = activityType.Assembly.GetType(designerTypeName);
|
|
if (designerType == null && serviceProvider != null)
|
|
{
|
|
ITypeResolutionService typeResolutionService = serviceProvider.GetService(typeof(ITypeResolutionService)) as ITypeResolutionService;
|
|
designerType = (typeResolutionService != null) ? typeResolutionService.GetType(designerAttribute.DesignerTypeName) : null;
|
|
}
|
|
|
|
if (designerType == null)
|
|
designerType = Type.GetType(designerAttribute.DesignerTypeName);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return designerType;
|
|
}
|
|
|
|
internal static ActivityDesigner CreateDesigner(IServiceProvider serviceProvider, Activity activity)
|
|
{
|
|
IDesigner designer = null;
|
|
Type designerType = GetDesignerType(serviceProvider, activity.GetType(), typeof(IDesigner));
|
|
if (designerType == null)
|
|
designerType = GetDesignerType(serviceProvider, activity.GetType(), null);
|
|
|
|
if (designerType != null)
|
|
{
|
|
try
|
|
{
|
|
designer = Activator.CreateInstance(designerType, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, null) as IDesigner;
|
|
designer.Initialize(activity);
|
|
}
|
|
catch
|
|
{
|
|
//Eat the exception thrown
|
|
}
|
|
}
|
|
return (designer as ActivityDesigner);
|
|
}
|
|
#endregion
|
|
|
|
#region Private Methods
|
|
private bool GetVisible()
|
|
{
|
|
Activity activity = Activity;
|
|
if (activity == null)
|
|
return false;
|
|
|
|
while (activity != null)
|
|
{
|
|
ActivityDesigner containedDesigner = ActivityDesigner.GetDesigner(activity);
|
|
if (containedDesigner != null)
|
|
{
|
|
CompositeActivityDesigner parentDesigner = containedDesigner.ParentDesigner;
|
|
if (parentDesigner == null && containedDesigner is IRootDesigner)
|
|
return true;
|
|
|
|
if (parentDesigner == null || !parentDesigner.Expanded || !parentDesigner.IsContainedDesignerVisible(containedDesigner))
|
|
return false;
|
|
|
|
activity = parentDesigner.Activity;
|
|
}
|
|
else
|
|
{
|
|
activity = null;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private void OnGenerateEventHandler(object sender, EventArgs e)
|
|
{
|
|
DesignerVerb eventVerb = sender as DesignerVerb;
|
|
if (eventVerb == null)
|
|
return;
|
|
|
|
Activity contextActivity = Helpers.GetRootActivity(Activity);
|
|
if (contextActivity == null)
|
|
return;
|
|
|
|
PropertyDescriptor methodDescriptor = null;
|
|
|
|
PropertyDescriptor[] propertyDescriptors = EventHandlerProperties;
|
|
foreach (PropertyDescriptor propertyDescriptor in propertyDescriptors)
|
|
{
|
|
Type rtType = PropertyDescriptorUtils.GetBaseType(propertyDescriptor, Activity, Activity.Site);
|
|
if (rtType != null)
|
|
{
|
|
object handler = propertyDescriptor.GetValue(Activity);
|
|
if (!(handler is String) || String.IsNullOrEmpty((String)handler))
|
|
handler = DesignerHelpers.CreateUniqueMethodName(Activity, propertyDescriptor.Name, rtType);
|
|
propertyDescriptor.SetValue(Activity, handler);
|
|
methodDescriptor = propertyDescriptor;
|
|
}
|
|
}
|
|
|
|
IEventBindingService eventBindingService = GetService(typeof(IEventBindingService)) as IEventBindingService;
|
|
if (eventBindingService != null)
|
|
{
|
|
if (methodDescriptor is DynamicPropertyDescriptor)
|
|
methodDescriptor = ((DynamicPropertyDescriptor)methodDescriptor).RealPropertyDescriptor;
|
|
|
|
EventDescriptor eventDescriptor = eventBindingService.GetEvent(methodDescriptor);
|
|
if (eventDescriptor != null)
|
|
eventBindingService.ShowCode(Activity, eventDescriptor);
|
|
else
|
|
eventBindingService.ShowCode();
|
|
}
|
|
}
|
|
|
|
private void OnPromoteBindings(object sender, EventArgs e)
|
|
{
|
|
DesignerVerb eventVerb = sender as DesignerVerb;
|
|
if (eventVerb == null)
|
|
return;
|
|
|
|
IServiceProvider serviceProvider = GetService(typeof(DesignSurface)) as IServiceProvider;
|
|
Debug.Assert(serviceProvider != null);
|
|
|
|
List<CustomProperty> properties = CustomActivityDesignerHelper.GetCustomProperties(serviceProvider);
|
|
if (properties == null)
|
|
return;
|
|
|
|
// get all the members of the custom activity to ensure uniqueness
|
|
Type customActivityType = CustomActivityDesignerHelper.GetCustomActivityType(serviceProvider);
|
|
List<String> customPropertyNames = new List<String>();
|
|
foreach (MemberInfo memberInfo in customActivityType.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
|
|
{
|
|
if (!customPropertyNames.Contains(memberInfo.Name))
|
|
customPropertyNames.Add(memberInfo.Name);
|
|
}
|
|
|
|
PropertyDescriptor[] propertyDescriptors = BindableProperties;
|
|
Dictionary<PropertyDescriptor, ActivityBind> promotedProperties = new Dictionary<PropertyDescriptor, ActivityBind>();
|
|
|
|
foreach (PropertyDescriptor propertyDescriptor in propertyDescriptors)
|
|
{
|
|
ActivityBind bind = propertyDescriptor.GetValue(Activity) as ActivityBind;
|
|
if (bind != null)
|
|
continue;
|
|
|
|
CustomProperty newCustomProperty = CustomProperty.CreateCustomProperty(Activity.Site, DesignerHelpers.GenerateUniqueIdentifier(Activity.Site, Activity.Name + "_" + propertyDescriptor.Name, customPropertyNames.ToArray()), propertyDescriptor, Activity);
|
|
|
|
properties.Add(newCustomProperty);
|
|
|
|
// verify this name will not repeat
|
|
customPropertyNames.Add(newCustomProperty.Name);
|
|
|
|
// set a new bind
|
|
promotedProperties.Add(propertyDescriptor, new ActivityBind(ActivityBind.GetRelativePathExpression(Helpers.GetRootActivity(Activity), Activity), newCustomProperty.Name));
|
|
}
|
|
|
|
//We have a restriction that we need to emit the custom properties furst before setting the binding
|
|
CustomActivityDesignerHelper.SetCustomProperties(properties, serviceProvider);
|
|
|
|
foreach (PropertyDescriptor promotedProperty in promotedProperties.Keys)
|
|
promotedProperty.SetValue(Activity, promotedProperties[promotedProperty]);
|
|
}
|
|
|
|
private void OnBindProperty(object sender, EventArgs e)
|
|
{
|
|
IExtendedUIService extendedUIService = GetService(typeof(IExtendedUIService)) as IExtendedUIService;
|
|
if (extendedUIService != null)
|
|
BindUITypeEditor.EditValue(extendedUIService.GetSelectedPropertyContext());
|
|
}
|
|
|
|
private void OnGenerateEventHandlerStatusUpdate(object sender, EventArgs e)
|
|
{
|
|
DesignerVerb verb = sender as DesignerVerb;
|
|
if (verb == null)
|
|
return;
|
|
|
|
bool canGenerateHandlers = false;
|
|
PropertyDescriptor[] propertyDescriptors = EventHandlerProperties;
|
|
foreach (PropertyDescriptor propertyDescriptor in propertyDescriptors)
|
|
{
|
|
object handler = propertyDescriptor.GetValue(Activity);
|
|
if (handler == null)
|
|
{
|
|
canGenerateHandlers = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
verb.Enabled = canGenerateHandlers;
|
|
}
|
|
|
|
private void OnPromoteBindingsStatusUpdate(object sender, EventArgs e)
|
|
{
|
|
DesignerVerb verb = sender as DesignerVerb;
|
|
if (verb == null)
|
|
return;
|
|
|
|
bool canPromoteBindings = false;
|
|
PropertyDescriptor[] propertyDescriptors = this.BindableProperties;
|
|
foreach (PropertyDescriptor propertyDescriptor in propertyDescriptors)
|
|
{
|
|
ActivityBind bind = propertyDescriptor.GetValue(Activity) as ActivityBind;
|
|
if (bind == null)
|
|
{
|
|
canPromoteBindings = true;
|
|
break;
|
|
}
|
|
}
|
|
verb.Enabled = canPromoteBindings;
|
|
}
|
|
|
|
private void OnBindPropertyStatusUpdate(object sender, EventArgs e)
|
|
{
|
|
DesignerVerb verb = sender as DesignerVerb;
|
|
if (verb == null)
|
|
return;
|
|
|
|
bool canBindProperty = false;
|
|
string propertyName = null;
|
|
IExtendedUIService extendedUIService = GetService(typeof(IExtendedUIService)) as IExtendedUIService;
|
|
if (extendedUIService != null)
|
|
{
|
|
ITypeDescriptorContext propertyContext = extendedUIService.GetSelectedPropertyContext();
|
|
canBindProperty = (propertyContext != null && ActivityBindPropertyDescriptor.IsBindableProperty(propertyContext.PropertyDescriptor) && !propertyContext.PropertyDescriptor.IsReadOnly);
|
|
propertyName = (propertyContext != null) ? propertyContext.PropertyDescriptor.Name : null;
|
|
}
|
|
|
|
verb.Properties["Text"] = (propertyName != null && verb.Enabled) ? string.Format(CultureInfo.CurrentCulture, DR.GetString(DR.BindSelectedPropertyFormat), propertyName) : DR.GetString(DR.BindSelectedProperty);
|
|
verb.Enabled = (canBindProperty && !IsLocked);
|
|
}
|
|
|
|
private void OnComponentRenamed(object sender, ComponentRenameEventArgs e)
|
|
{
|
|
ActivityDesigner designer = ActivityDesigner.GetDesigner(e.Component as Activity);
|
|
if (designer != null)
|
|
this.Text = Activity.Name;
|
|
|
|
}
|
|
|
|
private void OnComponentChanged(object sender, ComponentChangedEventArgs e)
|
|
{
|
|
if (e.Component != null && (e.OldValue is ActivityBind && !(e.NewValue is ActivityBind)) ||
|
|
(!(e.OldValue is ActivityBind) && e.NewValue is ActivityBind))
|
|
TypeDescriptor.Refresh(e.Component);
|
|
|
|
IReferenceService referenceService = GetService(typeof(IReferenceService)) as IReferenceService;
|
|
Activity changedActivity = (referenceService != null) ? referenceService.GetComponent(e.Component) as Activity : e.Component as Activity;
|
|
if (changedActivity != null)
|
|
{
|
|
ActivityDesigner designer = ActivityDesigner.GetDesigner(changedActivity);
|
|
if (designer != null)
|
|
designer.OnActivityChanged(new ActivityChangedEventArgs(changedActivity, e.Member, e.OldValue, e.NewValue));
|
|
}
|
|
}
|
|
|
|
private void OnLoadComplete(object sender, EventArgs e)
|
|
{
|
|
WorkflowView workflowView = ((IRootDesigner)this).GetView(ViewTechnology.Default) as WorkflowView;
|
|
if (workflowView != null)
|
|
workflowView.Idle += new EventHandler(OnFirstIdle);
|
|
}
|
|
|
|
private void OnFirstIdle(object sender, EventArgs e)
|
|
{
|
|
WorkflowView workflowView = ((IRootDesigner)this).GetView(ViewTechnology.Default) as WorkflowView;
|
|
if (workflowView != null)
|
|
workflowView.Idle -= new EventHandler(OnFirstIdle);
|
|
|
|
// Select this component.
|
|
ISelectionService selectionService = (ISelectionService)GetService(typeof(ISelectionService));
|
|
if (selectionService != null && selectionService.SelectionCount == 0)
|
|
selectionService.SetSelectedComponents(new object[] { Activity }, SelectionTypes.Replace);
|
|
|
|
DesignerHelpers.RefreshDesignerActions(Activity.Site);
|
|
Invalidate();
|
|
}
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Interface Implementation
|
|
|
|
#region IDisposable Implementation
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
#endregion
|
|
|
|
#region IDesigner Implementation
|
|
IComponent IDesigner.Component
|
|
{
|
|
get
|
|
{
|
|
return this.activity as IComponent;
|
|
}
|
|
}
|
|
|
|
DesignerVerbCollection IDesigner.Verbs
|
|
{
|
|
get
|
|
{
|
|
ActivityDesignerVerbCollection verbs = new ActivityDesignerVerbCollection();
|
|
verbs.AddRange(Verbs);
|
|
|
|
IDesignerVerbProviderService verbProviderService = GetService(typeof(IDesignerVerbProviderService)) as IDesignerVerbProviderService;
|
|
if (verbProviderService != null)
|
|
{
|
|
foreach (IDesignerVerbProvider verbProvider in verbProviderService.VerbProviders)
|
|
verbs.AddRange(verbProvider.GetVerbs(this));
|
|
}
|
|
|
|
return verbs.SafeCollection;
|
|
}
|
|
}
|
|
|
|
void IDesigner.Initialize(IComponent component)
|
|
{
|
|
this.activity = component as Activity;
|
|
if (this.activity == null)
|
|
throw new ArgumentException(DR.GetString(DR.Error_InvalidActivity), "component");
|
|
|
|
Initialize(this.activity);
|
|
}
|
|
|
|
void IDesigner.DoDefaultAction()
|
|
{
|
|
DoDefaultAction();
|
|
}
|
|
#endregion
|
|
|
|
#region IDesignerFilter Implementation
|
|
void IDesignerFilter.PreFilterAttributes(IDictionary attributes)
|
|
{
|
|
PreFilterAttributes(attributes);
|
|
}
|
|
|
|
void IDesignerFilter.PreFilterProperties(IDictionary properties)
|
|
{
|
|
PreFilterProperties(properties);
|
|
}
|
|
|
|
void IDesignerFilter.PreFilterEvents(IDictionary events)
|
|
{
|
|
PreFilterEvents(events);
|
|
}
|
|
|
|
void IDesignerFilter.PostFilterAttributes(IDictionary attributes)
|
|
{
|
|
PostFilterAttributes(attributes);
|
|
}
|
|
|
|
void IDesignerFilter.PostFilterProperties(IDictionary properties)
|
|
{
|
|
PostFilterProperties(properties);
|
|
}
|
|
|
|
void IDesignerFilter.PostFilterEvents(IDictionary events)
|
|
{
|
|
PostFilterEvents(events);
|
|
}
|
|
#endregion
|
|
|
|
#region IConnectableDesigner Implementation
|
|
bool IConnectableDesigner.CanConnect(ConnectionPoint source, ConnectionPoint target)
|
|
{
|
|
return CanConnect(source, target);
|
|
}
|
|
|
|
void IConnectableDesigner.OnConnected(ConnectionPoint source, ConnectionPoint target)
|
|
{
|
|
OnConnected(source, target);
|
|
}
|
|
#endregion
|
|
|
|
#region IWorkflowRootDesigner Implementation
|
|
ViewTechnology[] IRootDesigner.SupportedTechnologies
|
|
{
|
|
get
|
|
{
|
|
return new ViewTechnology[] { ViewTechnology.Default };
|
|
}
|
|
}
|
|
|
|
object IRootDesigner.GetView(ViewTechnology technology)
|
|
{
|
|
DesignSurface surface = GetService(typeof(DesignSurface)) as DesignSurface;
|
|
IDesignerHost designerHost = GetService(typeof(IDesignerHost)) as IDesignerHost;
|
|
if (this.workflowView == null && surface != null && designerHost != null && designerHost.RootComponent == Activity)
|
|
this.workflowView = CreateView(technology);
|
|
return this.workflowView;
|
|
}
|
|
|
|
CompositeActivityDesigner IWorkflowRootDesigner.InvokingDesigner
|
|
{
|
|
get
|
|
{
|
|
return InvokingDesigner;
|
|
}
|
|
|
|
set
|
|
{
|
|
InvokingDesigner = value;
|
|
}
|
|
}
|
|
|
|
ReadOnlyCollection<WorkflowDesignerMessageFilter> IWorkflowRootDesigner.MessageFilters
|
|
{
|
|
get
|
|
{
|
|
return MessageFilters;
|
|
}
|
|
}
|
|
|
|
bool IWorkflowRootDesigner.IsSupportedActivityType(Type activityType)
|
|
{
|
|
return IsSupportedActivityType(activityType);
|
|
}
|
|
|
|
bool IWorkflowRootDesigner.SupportsLayoutPersistence
|
|
{
|
|
get
|
|
{
|
|
return SupportsLayoutPersistence;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region IToolboxUser Implementation
|
|
bool IToolboxUser.GetToolSupported(ToolboxItem toolboxItem)
|
|
{
|
|
// Default is true. If any goes wrong, let the compiler catch it.
|
|
bool itemSupported = true;
|
|
|
|
//get ui service refernce
|
|
IExtendedUIService2 uiService = this.GetService(typeof(IExtendedUIService2)) as IExtendedUIService2;
|
|
//and use it to obtain project's target framework version
|
|
if (null != uiService)
|
|
{
|
|
//in case of target framework less than 3.5 - disable ReceiveActivity and SendActivity
|
|
long targetFramework = uiService.GetTargetFrameworkVersion();
|
|
|
|
if (targetFramework != 0)
|
|
{
|
|
// if target framework is less than 3.0 dont show any toolbox item, because workflow didnt ship then.
|
|
if (targetFramework < ActivityDesigner.FrameworkVersion_3_0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (targetFramework < ActivityDesigner.FrameworkVersion_3_5)
|
|
{
|
|
if (string.Equals(toolboxItem.TypeName, "System.Workflow.Activities.ReceiveActivity") ||
|
|
string.Equals(toolboxItem.TypeName, "System.Workflow.Activities.SendActivity"))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ITypeProvider typeProvider = GetService(typeof(ITypeProvider)) as ITypeProvider;
|
|
if (typeProvider != null)
|
|
{
|
|
Type itemType = null;
|
|
if (typeProvider.LocalAssembly != null)
|
|
itemType = typeProvider.LocalAssembly.GetType(toolboxItem.TypeName, false);
|
|
if (itemType == null)
|
|
{
|
|
try
|
|
{
|
|
itemType = Type.GetType(toolboxItem.TypeName + ", " + toolboxItem.AssemblyName);
|
|
}
|
|
catch (FileNotFoundException) { }
|
|
catch (FileLoadException) { }
|
|
}
|
|
|
|
if (itemType == null)
|
|
return itemSupported;
|
|
|
|
//check if the activity is NOT supported - we ask this to the Root Designer only. If so, bail out.
|
|
IWorkflowRootDesigner rootDesigner = ActivityDesigner.GetSafeRootDesigner(Activity.Site) as IWorkflowRootDesigner;
|
|
if (rootDesigner != null)
|
|
{
|
|
if (!rootDesigner.IsSupportedActivityType(itemType))
|
|
{
|
|
return false;
|
|
}
|
|
else if (rootDesigner.InvokingDesigner != null && rootDesigner.InvokingDesigner.Activity != null)
|
|
{
|
|
rootDesigner = ActivityDesigner.GetSafeRootDesigner(rootDesigner.InvokingDesigner.Activity.Site) as IWorkflowRootDesigner;
|
|
if (rootDesigner != null && !rootDesigner.IsSupportedActivityType(itemType))
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!(toolboxItem is ActivityToolboxItem))
|
|
{
|
|
object[] attributes = itemType.GetCustomAttributes(typeof(ToolboxItemAttribute), false);
|
|
if (attributes.Length > 0)
|
|
{
|
|
itemSupported = false;
|
|
foreach (Attribute attribute in attributes)
|
|
{
|
|
ToolboxItemAttribute toolBoxItemAttribute = attribute as ToolboxItemAttribute;
|
|
if (toolBoxItemAttribute != null && typeof(System.Workflow.ComponentModel.Design.ActivityToolboxItem).IsAssignableFrom(toolBoxItemAttribute.ToolboxItemType))
|
|
{
|
|
itemSupported = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return itemSupported;
|
|
}
|
|
|
|
void IToolboxUser.ToolPicked(ToolboxItem toolboxItem)
|
|
{
|
|
ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
|
|
IToolboxService toolboxService = GetService(typeof(IToolboxService)) as IToolboxService;
|
|
if (toolboxItem == null || selectionService == null)
|
|
return;
|
|
|
|
object selectedObject = selectionService.PrimarySelection;
|
|
if (!(selectedObject is HitTestInfo) && !(selectedObject is CompositeActivity))
|
|
return;
|
|
|
|
//Get the paste target
|
|
HitTestInfo hitInfo = null;
|
|
CompositeActivity compositeActivity = null;
|
|
if (selectedObject is HitTestInfo)
|
|
{
|
|
hitInfo = (HitTestInfo)selectedObject;
|
|
compositeActivity = hitInfo.AssociatedDesigner.Activity as CompositeActivity;
|
|
}
|
|
else if (selectedObject is CompositeActivity)
|
|
{
|
|
compositeActivity = (CompositeActivity)selectedObject;
|
|
hitInfo = new HitTestInfo(ActivityDesigner.GetDesigner(compositeActivity), HitTestLocations.Designer);
|
|
}
|
|
|
|
//Get the parent designer for pasting
|
|
CompositeActivityDesigner compositeActivityDesigner = ActivityDesigner.GetDesigner(compositeActivity) as CompositeActivityDesigner;
|
|
if (compositeActivityDesigner == null)
|
|
return;
|
|
|
|
|
|
Activity[] activities = CompositeActivityDesigner.DeserializeActivitiesFromToolboxItem(Activity.Site, toolboxItem, false);
|
|
if (activities.Length == 0)
|
|
return;
|
|
|
|
if (!compositeActivityDesigner.CanInsertActivities(hitInfo, new List<Activity>(activities).AsReadOnly()))
|
|
return;
|
|
|
|
try
|
|
{
|
|
activities = CompositeActivityDesigner.DeserializeActivitiesFromToolboxItem(Activity.Site, toolboxItem, true);
|
|
if (activities.Length > 0)
|
|
{
|
|
CompositeActivityDesigner.InsertActivities(compositeActivityDesigner, hitInfo, new List<Activity>(activities).AsReadOnly(), SR.GetString(SR.PastingActivities));
|
|
selectionService.SetSelectedComponents(activities, SelectionTypes.Replace);
|
|
ParentView.EnsureVisible(activities[0]);
|
|
}
|
|
}
|
|
catch (CheckoutException ex)
|
|
{
|
|
if (ex != CheckoutException.Canceled)
|
|
throw new Exception(DR.GetString(DR.ActivityInsertError) + "\n" + ex.Message, ex);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region IPersistUIState Implementation
|
|
void IPersistUIState.SaveViewState(BinaryWriter writer)
|
|
{
|
|
SaveViewState(writer);
|
|
}
|
|
|
|
void IPersistUIState.LoadViewState(BinaryReader reader)
|
|
{
|
|
LoadViewState(reader);
|
|
}
|
|
#endregion
|
|
|
|
#region IWorkflowDesignerMessageSink Members
|
|
bool IWorkflowDesignerMessageSink.OnMouseDown(MouseEventArgs e)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
{
|
|
try
|
|
{
|
|
Point logicalPoint = parentView.ClientPointToLogical(new Point(e.X, e.Y));
|
|
OnMouseDown(new MouseEventArgs(e.Button, e.Clicks, logicalPoint.X, logicalPoint.Y, e.Delta));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnMouseMove(MouseEventArgs e)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
{
|
|
try
|
|
{
|
|
Point logicalPoint = parentView.ClientPointToLogical(new Point(e.X, e.Y));
|
|
OnMouseMove(new MouseEventArgs(e.Button, e.Clicks, logicalPoint.X, logicalPoint.Y, e.Delta));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnMouseUp(MouseEventArgs e)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
{
|
|
try
|
|
{
|
|
Point logicalPoint = parentView.ClientPointToLogical(new Point(e.X, e.Y));
|
|
OnMouseUp(new MouseEventArgs(e.Button, e.Clicks, logicalPoint.X, logicalPoint.Y, e.Delta));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnMouseDoubleClick(MouseEventArgs e)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
{
|
|
try
|
|
{
|
|
Point logicalPoint = parentView.ClientPointToLogical(new Point(e.X, e.Y));
|
|
OnMouseDoubleClick(new MouseEventArgs(e.Button, e.Clicks, logicalPoint.X, logicalPoint.Y, e.Delta));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnMouseEnter(MouseEventArgs e)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
{
|
|
try
|
|
{
|
|
Point logicalPoint = parentView.ClientPointToLogical(new Point(e.X, e.Y));
|
|
OnMouseEnter(new MouseEventArgs(e.Button, e.Clicks, logicalPoint.X, logicalPoint.Y, e.Delta));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnMouseHover(MouseEventArgs e)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
{
|
|
try
|
|
{
|
|
Point logicalPoint = parentView.ClientPointToLogical(new Point(e.X, e.Y));
|
|
OnMouseHover(new MouseEventArgs(e.Button, e.Clicks, logicalPoint.X, logicalPoint.Y, e.Delta));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnMouseLeave()
|
|
{
|
|
try
|
|
{
|
|
OnMouseLeave();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnMouseWheel(MouseEventArgs e)
|
|
{
|
|
//Only used in message filters
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnMouseCaptureChanged()
|
|
{
|
|
try
|
|
{
|
|
OnMouseCaptureChanged();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnMouseDragBegin(Point initialPoint, MouseEventArgs e)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
{
|
|
try
|
|
{
|
|
Point logicalPoint = parentView.ClientPointToLogical(new Point(e.X, e.Y));
|
|
OnMouseDragBegin(initialPoint, new MouseEventArgs(e.Button, e.Clicks, logicalPoint.X, logicalPoint.Y, e.Delta));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnMouseDragMove(MouseEventArgs e)
|
|
{
|
|
WorkflowView parentView = ParentView;
|
|
if (parentView != null)
|
|
{
|
|
try
|
|
{
|
|
Point logicalPoint = parentView.ClientPointToLogical(new Point(e.X, e.Y));
|
|
OnMouseDragMove(new MouseEventArgs(e.Button, e.Clicks, logicalPoint.X, logicalPoint.Y, e.Delta));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnMouseDragEnd()
|
|
{
|
|
try
|
|
{
|
|
OnMouseDragEnd();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnDragEnter(DragEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
OnDragEnter(e as ActivityDragEventArgs);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnDragOver(DragEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
OnDragOver(e as ActivityDragEventArgs);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnDragLeave()
|
|
{
|
|
try
|
|
{
|
|
OnDragLeave();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnDragDrop(DragEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
OnDragDrop(e as ActivityDragEventArgs);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnGiveFeedback(GiveFeedbackEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
OnGiveFeedback(e);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnQueryContinueDrag(QueryContinueDragEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
OnQueryContinueDrag(e);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnKeyDown(KeyEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
OnKeyDown(e);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnKeyUp(KeyEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
OnKeyUp(e);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnScroll(ScrollBar sender, int value)
|
|
{
|
|
try
|
|
{
|
|
OnScroll(sender, value);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnShowContextMenu(Point screenMenuPoint)
|
|
{
|
|
//Only used in message filters
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.ProcessMessage(Message message)
|
|
{
|
|
try
|
|
{
|
|
OnProcessMessage(message);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void IWorkflowDesignerMessageSink.OnLayout(LayoutEventArgs layoutEventArgs)
|
|
{
|
|
//Only used in message filters
|
|
}
|
|
|
|
void IWorkflowDesignerMessageSink.OnLayoutPosition(Graphics graphics)
|
|
{
|
|
try
|
|
{
|
|
OnLayoutPosition(new ActivityDesignerLayoutEventArgs(graphics, DesignerTheme));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
void IWorkflowDesignerMessageSink.OnLayoutSize(Graphics graphics)
|
|
{
|
|
try
|
|
{
|
|
Size = OnLayoutSize(new ActivityDesignerLayoutEventArgs(graphics, DesignerTheme));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
void IWorkflowDesignerMessageSink.OnBeginResizing(DesignerEdges sizingEdge)
|
|
{
|
|
try
|
|
{
|
|
OnBeginResizing(new ActivityDesignerResizeEventArgs(sizingEdge, Bounds));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
void IWorkflowDesignerMessageSink.OnResizing(DesignerEdges sizingEdge, Rectangle bounds)
|
|
{
|
|
try
|
|
{
|
|
OnResizing(new ActivityDesignerResizeEventArgs(sizingEdge, bounds));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
void IWorkflowDesignerMessageSink.OnEndResizing()
|
|
{
|
|
try
|
|
{
|
|
OnEndResizing();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
void IWorkflowDesignerMessageSink.OnThemeChange()
|
|
{
|
|
try
|
|
{
|
|
OnThemeChange(DesignerTheme);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnPaint(PaintEventArgs e, Rectangle viewPort)
|
|
{
|
|
try
|
|
{
|
|
Rectangle bounds = Bounds;
|
|
if (IsVisible && viewPort.IntersectsWith(bounds))
|
|
{
|
|
GlyphManager glyphManager = GetService(typeof(IDesignerGlyphProviderService)) as GlyphManager;
|
|
bounds.Width += 1; bounds.Height += 1;
|
|
|
|
using (GraphicsPath graphicsPath = ActivityDesignerPaint.GetDesignerPath(this, Point.Empty, new Size(DesignerTheme.BorderWidth, DesignerTheme.BorderWidth), DesignerEdges.All, false))
|
|
using (Region clipRegion = new Region(graphicsPath))
|
|
{
|
|
Region oldRegion = e.Graphics.Clip;
|
|
clipRegion.Intersect(oldRegion);
|
|
clipRegion.Intersect(viewPort);
|
|
|
|
bool restoredClipState = false;
|
|
try
|
|
{
|
|
ActivityDesignerPaintEventArgs eventArgs = new ActivityDesignerPaintEventArgs(e.Graphics, bounds, viewPort, DesignerTheme);
|
|
|
|
e.Graphics.Clip = clipRegion;
|
|
OnPaint(eventArgs);
|
|
e.Graphics.Clip = oldRegion;
|
|
restoredClipState = true;
|
|
|
|
if (glyphManager != null)
|
|
glyphManager.DrawDesignerGlyphs(eventArgs, this);
|
|
|
|
DrawingState &= (~DrawingStates.InvalidDraw);
|
|
}
|
|
catch
|
|
{
|
|
//Eat the exception thrown
|
|
DrawingState |= DrawingStates.InvalidDraw;
|
|
}
|
|
finally
|
|
{
|
|
if (!restoredClipState)
|
|
e.Graphics.Clip = oldRegion;
|
|
|
|
if (DrawingState != DrawingStates.Valid)
|
|
ActivityDesignerPaint.DrawInvalidDesignerIndicator(e.Graphics, this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IWorkflowDesignerMessageSink.OnPaintWorkflowAdornments(PaintEventArgs e, Rectangle viewPort)
|
|
{
|
|
//Only used in message filters
|
|
return true;
|
|
}
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region Class SmartTag
|
|
internal sealed class SmartTag : DesignerGlyph
|
|
{
|
|
internal const int DefaultHeight = 2;
|
|
private static Image defaultImage = DR.GetImage(DR.SmartTag);
|
|
private ActivityDesigner activeDesigner;
|
|
|
|
public override Rectangle GetBounds(ActivityDesigner designer, bool activated)
|
|
{
|
|
Rectangle smartTagRectangle = Rectangle.Empty;
|
|
Rectangle rectangle = designer.SmartTagRectangle;
|
|
if (!rectangle.IsEmpty)
|
|
{
|
|
Size glyphSize = WorkflowTheme.CurrentTheme.AmbientTheme.GlyphSize;
|
|
Size imageSize = rectangle.Size;
|
|
|
|
Size margin = WorkflowTheme.CurrentTheme.AmbientTheme.Margin;
|
|
|
|
smartTagRectangle.X = rectangle.Left - margin.Width / 2;
|
|
smartTagRectangle.Y = rectangle.Top - margin.Height / 2;
|
|
smartTagRectangle.Width = imageSize.Width + glyphSize.Width / 2 + 3 * margin.Width;
|
|
smartTagRectangle.Height = imageSize.Height + margin.Height;
|
|
}
|
|
|
|
return smartTagRectangle;
|
|
}
|
|
|
|
public override bool CanBeActivated
|
|
{
|
|
get
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
protected override void OnPaint(Graphics graphics, bool activated, AmbientTheme ambientTheme, ActivityDesigner designer)
|
|
{
|
|
Rectangle activatedBounds = GetBounds(designer, true);
|
|
|
|
bool formShown = false; //if the drop down form is shown, draw the arrow up
|
|
if (Form.ActiveForm != null && Form.ActiveForm.GetType().FullName.Equals(typeof(ItemPalette).FullName + "+Palette", StringComparison.Ordinal))
|
|
formShown = (Form.ActiveForm.Location == designer.PointToScreen(new Point(activatedBounds.Left, activatedBounds.Bottom)));
|
|
|
|
//work around: This is in order to show the smarttag activated when the drop down is shown but cursor leaves the active area of glyph
|
|
if (!activated)
|
|
{
|
|
if (this.activeDesigner != null)
|
|
{
|
|
activated = true;
|
|
}
|
|
else if (Form.ActiveForm != null && Form.ActiveForm.GetType().FullName.Equals(typeof(ItemPalette).FullName + "+Palette", StringComparison.Ordinal))
|
|
{
|
|
activated = formShown;
|
|
}
|
|
}
|
|
|
|
graphics.FillRectangle(WorkflowTheme.CurrentTheme.AmbientTheme.BackgroundBrush, activatedBounds);
|
|
using (Brush transparentSelectionBrush = new SolidBrush(Color.FromArgb(50, WorkflowTheme.CurrentTheme.AmbientTheme.SelectionForeColor)))
|
|
graphics.FillRectangle(transparentSelectionBrush, activatedBounds);
|
|
graphics.DrawRectangle(SystemPens.ControlDarkDark, activatedBounds);
|
|
|
|
//Draw the image
|
|
Image image = designer.Image;
|
|
image = (designer.Image == null) ? SmartTag.defaultImage : image;
|
|
|
|
Size glyphSize = WorkflowTheme.CurrentTheme.AmbientTheme.GlyphSize;
|
|
Size imageSize = designer.SmartTagRectangle.Size;
|
|
|
|
Size margin = WorkflowTheme.CurrentTheme.AmbientTheme.Margin;
|
|
|
|
Rectangle imageRectangle = activatedBounds;
|
|
imageRectangle.X += margin.Width / 2;
|
|
imageRectangle.Y += margin.Height / 2;
|
|
imageRectangle.Size = imageSize;
|
|
ActivityDesignerPaint.DrawImage(graphics, image, imageRectangle, DesignerContentAlignment.Center);
|
|
|
|
//Draw the drop down indicator
|
|
Rectangle dropDownRectangle = activatedBounds;
|
|
dropDownRectangle.X += imageSize.Width + 3 * margin.Width / 2;
|
|
dropDownRectangle.Y += margin.Height / 2;
|
|
dropDownRectangle.Width = glyphSize.Width / 2;
|
|
dropDownRectangle.Height -= glyphSize.Height / 4;
|
|
using (GraphicsPath graphicsPath = ActivityDesignerPaint.GetScrollIndicatorPath(dropDownRectangle, ScrollButton.Down))
|
|
{
|
|
graphics.FillPath(Brushes.Black, graphicsPath);
|
|
graphics.DrawPath(Pens.Black, graphicsPath);
|
|
}
|
|
}
|
|
|
|
protected override void OnActivate(ActivityDesigner designer)
|
|
{
|
|
if (designer.SmartTagVerbs.Count > 0)
|
|
{
|
|
this.activeDesigner = designer;
|
|
Rectangle bounds = GetBounds(designer, true);
|
|
this.activeDesigner.OnShowSmartTagVerbs(new Point(bounds.Left, bounds.Bottom + 1));
|
|
this.activeDesigner = null;
|
|
}
|
|
}
|
|
|
|
internal ActivityDesigner ActiveDesigner
|
|
{
|
|
get
|
|
{
|
|
return this.activeDesigner;
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
#endregion
|
|
|
|
}
|