Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WF / Common / AuthoringOM / Design / ActivityDesigner.cs / 1305376 / ActivityDesigner.cs
#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 ////// 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. /// [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)] 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 ListdesignerActions; [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 /// /// Gets activity being designed by the designer. /// public Activity Activity { get { return this.activity; } } ////// Gets the parent designer of existing designer /// 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; } } ////// Gets value indicating if the activity associated with the designer is selected. /// public bool IsSelected { get { ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService; return (selectionService != null && selectionService.GetComponentSelected(Activity)); } } ////// Gets value indicating if the activity associated with the designer is primary selection. /// public bool IsPrimarySelection { get { ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService; return (selectionService != null && selectionService.PrimarySelection == Activity); } } ////// Gets the accessibility object associated with the designer /// public virtual AccessibleObject AccessibilityObject { get { if (this.accessibilityObject == null) this.accessibilityObject = new ActivityDesignerAccessibleObject(this); return this.accessibilityObject; } } ////// 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. /// public virtual bool IsVisible { get { return this.isVisible; } } ////// 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. /// 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; } } ////// Gets or Sets the location of the designer in logical coordinates. /// public virtual Point Location { get { return this.location; } set { if (ParentDesigner is FreeformActivityDesigner) value = DesignerHelpers.SnapToGrid(value); if (this.location != value) this.location = value; } } ////// Gets or Sets the size of the designer. /// 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; } } ////// Get the minimum size of the designer /// public virtual Size MinimumSize { get { return DesignerTheme.Size; } } ////// Get value for enclosing rectangle of the designer in logical coordinates. /// public Rectangle Bounds { get { //Bounds contain designer rectangle + the selection area return new Rectangle(Location, Size); } } ////// Gets the image associated with the designer. /// public virtual Image Image { get { return this.image; } protected set { this.image = value; PerformLayout(); } } ////// Gets the text associated with the designer. /// public virtual string Text { get { return this.text; } protected set { if (value == null || value.Length == 0 || this.text == value) return; this.text = value; PerformLayout(); } } ////// Gets the current theme to be used for the designer /// public ActivityDesignerTheme DesignerTheme { get { return WorkflowTheme.CurrentTheme.GetDesignerTheme(this); } } ////// Gets the value indicating if the designer is root designer. /// 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 ////// Returns the WorkflowView containing the designer /// protected internal WorkflowView ParentView { get { return GetService(typeof(WorkflowView)) as WorkflowView; } } ////// Gets the collection of verbs to be associated with the designer. /// The verbs are shown on context menu and the top level workflow menu. /// 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; } } ////// Gets or sets the value indicating if smarttag should be shown. /// protected virtual bool ShowSmartTag { get { return false; } } ////// Gets the array of actions which the designer wants to associated with the smarttag. /// protected virtual ReadOnlyCollectionSmartTagVerbs { get { return new List ().AsReadOnly(); } } /// /// Gets the Rectangle where the smarttag needs to be displayed /// protected virtual Rectangle SmartTagRectangle { get { Rectangle smartTagRectangle = Rectangle.Empty; Rectangle imageRectangle = ImageRectangle; if (!imageRectangle.Size.IsEmpty) { smartTagRectangle = imageRectangle; } return smartTagRectangle; } } ////// Gets the array of actions associated with the configuration errors. /// protected internal virtual ReadOnlyCollectionDesignerActions { get { if (this.designerActions == null) { this.designerActions = new List (); 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(); } } /// /// Gets the array of glyphs with which to adorn the designer. /// 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; } } ////// Gets the value of text rectangle in logical coordinates. /// 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; } } ////// Gets the value for enclosing bounds image associated with the designer in logical coordinates. /// 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 ReadOnlyCollectionMessageFilters { get { List stockFilters = new List (); 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(); } } /// /// Get if the designer is resizable using the rubberbanding when dropped in FreeformDesigner /// 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 { ListpropertyDescriptors = new List (); //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 propertyDescriptors = new List (); 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 rules = DesignerHelpers.GetDeclarativeRules(Activity); if (rules.Count > 0) { this.rulesText = DR.GetString(DR.Rules); int maxRulesLength = 3 * (MaximumIdentifierLength + MaximumDescriptionLength); foreach (KeyValuePair 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 activities = new List (); 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; } /// /// Returns if the Activity is commented or is inside commented activity /// /// ///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 /// /// 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. /// /// CompositeActivity which can be potentially set as parent. ///True if the CompositeActivity can be set as parent of activity associated with designer, false otherwise. public virtual bool CanBeParentedTo(CompositeActivityDesigner parentActivityDesigner) { if (parentActivityDesigner == null) throw new ArgumentNullException("parentActivityDesigner"); return true; } ////// Allows detection of the area hit on the designer. /// /// Point to test in logical coordinates. ///Information indicating where the hit happened 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 ReadOnlyCollectionconnectionPoints = 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; } /// /// Brings designer in viewable area /// public void EnsureVisible() { WorkflowView parentView = ParentView; if (parentView != null) parentView.EnsureVisible(Activity); } ////// Get the points used to connect the designer. Points are in logical coordinates. /// public virtual ReadOnlyCollectionGetConnectionPoints(DesignerEdges edges) { List connectionPoints = new List (); 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(); } /// /// Invalidates the entire workflow designer /// 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)); } } } ////// Invalidates specified rectangle on the designer /// /// Rectangle to invalidate public void Invalidate(Rectangle rectangle) { WorkflowView parentView = ParentView; if (parentView != null) { rectangle = Rectangle.Intersect(Bounds, rectangle); parentView.InvalidateLogicalRectangle(rectangle); } } ////// Get image of the activity designer on specified graphics /// /// Graphics objects to draw image ///Image which is drawn 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)); Queuedesigners = new Queue (); 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 /// /// Initializes the designer with associated activity. /// /// Activity with which the designer needs to be initialized. 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); } ////// Disposes the resources held by the designer. /// /// True if the designer is being disposed, false if the designer is being finalized. 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); } } } } ////// Get the points used to connect the designer. Points are in logical coordinates. /// protected internal virtual ReadOnlyCollectionGetConnections(DesignerEdges edges) { Rectangle bounds = Bounds; List connections = new List (); 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(); } /// /// Perform default UI action associated with the designer. /// Example: Emit method associated with default event in code beside file on double click. /// 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); } } } } } ////// When overridden in a derived class, allows a designer to add items to the set of attributes that it exposes through a TypeDescriptor. /// /// The Attribute objects for the class of the activity. The keys in the dictionary of attributes are the TypeID values of the attributes. protected virtual void PreFilterAttributes(IDictionary attributes) { if (attributes == null) throw new ArgumentNullException("attributes"); } ////// When overridden in a derived class, allows a designer to add items to the set of properties that it exposes through a TypeDescriptor. /// /// The PropertyDescriptor objects that represent the properties of the class of the activity. The keys in the dictionary of properties are property names. protected virtual void PreFilterProperties(IDictionary properties) { if (properties == null) throw new ArgumentNullException("properties"); } ////// When overridden in a derived class, allows a designer to add items to the set of events that it exposes through a TypeDescriptor. /// /// The EventDescriptor objects that represent the events of the class of the activity. The keys in the dictionary of events are event names. protected virtual void PreFilterEvents(IDictionary events) { if (events == null) throw new ArgumentNullException("events"); } ////// 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. /// /// The Attribute objects for the class of the activity. The keys in the dictionary of attributes are the TypeID values of the attributes. protected virtual void PostFilterAttributes(IDictionary attributes) { if (attributes == null) throw new ArgumentNullException("attributes"); } ////// 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. /// /// The PropertyDescriptor objects that represent the properties of the class of the activity. The keys in the dictionary of properties are property names. 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); } ////// 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. /// /// The EventDescriptor objects that represent the events of the class of the activity. The keys in the dictionary of events are event names. protected virtual void PostFilterEvents(IDictionary events) { if (events == null) throw new ArgumentNullException("events"); } ////// Attempts to retrieve the specified type of service from the designer's activity's design mode site. /// /// The type of service to request. ///An object implementing the requested service, or a null reference (Nothing in Visual Basic) if the service cannot be resolved. 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; } ////// Called when the users begins to drag mouse on the designer. /// /// Point where the drag started in logical coordinates /// MouseEventArgs containing event data. protected virtual void OnMouseDragBegin(Point initialDragPoint, MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the users drags mouse over the designer. /// /// MouseEventArgs containing event data. protected virtual void OnMouseDragMove(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the mouse drag ends. /// protected virtual void OnMouseDragEnd() { } ////// Called when the mouse cursor enters the designer bounds. /// /// MouseEventArgs containing event data. protected virtual void OnMouseEnter(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); if (IsVisible) { if (ShowSmartTag) SmartTagVisible = true; ShowInfoTip(InfoTipTitle, InfoTipText); } } ////// Called when the mouse button is clicked when mouse cursor is in designer bounds. /// /// MouseEventArgs containing event data. protected virtual void OnMouseDown(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the mouse cursor is moving in designer bounds. /// /// MouseEventArgs containing event data. protected virtual void OnMouseMove(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); if (IsVisible) ShowInfoTip(InfoTipTitle, InfoTipText); } ////// Called when the mouse cursor is in designer bounds. /// /// MouseEventArgs containing event data. protected virtual void OnMouseHover(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); if (IsVisible) ShowInfoTip(InfoTipTitle, InfoTipText); } ////// Called when the moused button is released when mouse cursor is in designer bounds. /// /// MouseEventArgs containing event data. protected virtual void OnMouseUp(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the mouse button is clicked multiple times on the designer /// /// MouseEventArgs containing event data. protected virtual void OnMouseDoubleClick(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the mouse cursor leaves designer bounds. /// protected virtual void OnMouseLeave() { if (ShowSmartTag) SmartTagVisible = false; ShowInfoTip(String.Empty); } ////// Called when the mouse capture changes /// protected virtual void OnMouseCaptureChanged() { } ////// Called when the drag drop operation is in progress and mouse cursor enters the designer bounds. /// /// Drag drop event arguments. protected virtual void OnDragEnter(ActivityDragEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the drag drop operation is in progress and mouse cursor is inside the designer bounds. /// /// Drag drop event arguments. protected virtual void OnDragOver(ActivityDragEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the drag drop operation is in progress and mouse cursor leaves the designer bounds. /// protected virtual void OnDragLeave() { } ////// Called when the drag drop operation is completed inside designer bounds. /// /// Drag drop event arguments. protected virtual void OnDragDrop(ActivityDragEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Updates the visual cues for feedback given to the user when performing drag drop operation. /// /// A GiveFeedbackEventArgs that contains the event data. protected virtual void OnGiveFeedback(GiveFeedbackEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Controls if the drag drop operation should continue. /// /// A QueryContinueDragEventArgs that contains the event data. protected virtual void OnQueryContinueDrag(QueryContinueDragEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when key is pressed when designer has keyboard focus. /// /// protected virtual void OnKeyDown(KeyEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when key is released when designer has keyboard focus. /// /// protected virtual void OnKeyUp(KeyEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when scroll position is changed /// /// Scrollbar sending the message /// New value of the scrolled position protected virtual void OnScroll(ScrollBar sender, int value) { } ////// Allows designer to process raw win32 message /// /// Message structure containing details of the message to be processed protected virtual void OnProcessMessage(Message message) { } ////// Called to refresh the configuration errors associated with designers. /// protected internal virtual void RefreshDesignerActions() { this.designerActions = null; } ////// Called when user clicks on configuration errors associated with the designer. /// /// Designer action associated with configuration error. 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); } } ////// Called to notify the designer if the SmartTag is being shown or hidden /// /// Indicates if the SmartTag is being shown or hidden 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); } ////// Shows the designer verbs associated with smarttag at specific point /// /// Point at which to show the actions protected virtual void OnShowSmartTagVerbs(Point smartTagPoint) { ActivityDesignerVerb[] verbs = null; SmartTagVerbs.CopyTo(verbs, 0); DesignerHelpers.ShowDesignerVerbs(this, PointToScreen(smartTagPoint), verbs); } ////// Notifies the designer that the associated theme has changed. /// protected virtual void OnThemeChange(ActivityDesignerTheme newTheme) { if (newTheme == null) throw new ArgumentNullException("newTheme"); this.Image = StockImage; } ////// Stores the UI state of the designer in binary stream. /// /// BinaryWriter used to store the state. protected virtual void SaveViewState(BinaryWriter writer) { if (writer == null) throw new ArgumentNullException("writer"); } ////// Restores the UI state of the designer from binary stream. /// /// BinaryReader used to restore the designer state. ///protected virtual void LoadViewState(BinaryReader reader) { if (reader == null) throw new ArgumentNullException("reader"); } /// /// 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 /// /// Type of the activity being queried ///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; } /// /// Refreshes the ActivityDesignerVerbs associted with the designer by calling status handler. /// 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; } } } } ////// Draws the visual representation of activity at design time. /// /// ActivityDesignerPaintEventArgs holding drawing arguments 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); } ////// Called to layout the position of contained visual cues or designers. /// /// ActivityDesignerLayoutEventArgs holding layout arguments protected virtual void OnLayoutPosition(ActivityDesignerLayoutEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called to set the size of the visual cues or designers contained within the designer. /// /// ActivityDesignerLayoutEventArgs holding layout arguments 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; } ////// Called when the user starts to visually resize the designer when designer is inside freeform designer /// /// protected virtual void OnBeginResizing(ActivityDesignerResizeEventArgs e) { } ////// Called when the user is visually resizing the designer when designer is inside freeform designer /// /// ActivityDesignerResizeEventArgs specifying the edge being used to resize and new bounds protected virtual void OnResizing(ActivityDesignerResizeEventArgs e) { FreeformActivityDesigner.SetDesignerBounds(this, e.Bounds); } ////// Called when user is done resizing the designer /// protected virtual void OnEndResizing() { PerformLayout(); } ////// Called to check if connection can be established between source and target designer /// /// Source connection point /// Target connection point ///True if connection can be established, false otherwise protected virtual bool CanConnect(ConnectionPoint source, ConnectionPoint target) { return true; } ////// Called when connection is established between two connection points /// /// Source connection point /// Target connection point protected virtual void OnConnected(ConnectionPoint source, ConnectionPoint target) { } ////// Called when the activity associated with the designer is changed. /// /// A ActivityChangedEventArgs containing information about what changed. 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; } ////// Shows specified tooltip /// /// String specifying the tooltip title /// String specifying the tooltip to display protected void ShowInfoTip(string title, string infoTip) { WorkflowView parentView = ParentView; if (parentView != null) parentView.ShowInfoTip(title, infoTip); } ////// Shows specified tooltip /// /// String specifying the tooltip to display protected void ShowInfoTip(string infoTip) { WorkflowView parentView = ParentView; if (parentView != null) parentView.ShowInfoTip(infoTip); } ////// Shows tooltip at specified location /// /// String specifying the tooltip to display /// Rectangle where to display tooltip protected void ShowInPlaceTip(string infoTip, Rectangle rectangle) { WorkflowView parentView = ParentView; if (parentView != null) parentView.ShowInPlaceToolTip(infoTip, parentView.LogicalRectangleToClient(rectangle)); } ////// Updates the layout of the designer /// protected void PerformLayout() { WorkflowView parentView = ParentView; if (parentView != null) parentView.PerformLayout(false); } ////// Transforms point from activity designer coordinate system to screen /// /// Point in activity designer coordinate system ///Point in screen coordinate system protected Point PointToScreen(Point point) { WorkflowView parentView = ParentView; if (parentView != null) return parentView.LogicalPointToScreen(point); else return point; } ////// Transforms point from screen coordinate system to activity designer coordinate system /// /// Point in screen coordinate system ///Point in activity designer coordinate system protected Point PointToLogical(Point point) { WorkflowView parentView = ParentView; if (parentView != null) return parentView.ScreenPointToLogical(point); else return point; } ////// Transforms rectangle from activity designer coordinate system to screen /// /// Rectangle in activity designer coordinate system ///Rectangle in screen coordinate system 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); } ////// Transforms rectangle from screen coordinate system to activity designer coordinate system /// /// Rectangle in screen coordinate system ///Rectangle in activity designer coordinate system 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); Listproperties = CustomActivityDesignerHelper.GetCustomProperties(serviceProvider); if (properties == null) return; // get all the members of the custom activity to ensure uniqueness Type customActivityType = CustomActivityDesignerHelper.GetCustomActivityType(serviceProvider); List customPropertyNames = new List (); 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 promotedProperties = new Dictionary (); 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 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 (activities).AsReadOnly())) return; try { activities = CompositeActivityDesigner.DeserializeActivitiesFromToolboxItem(Activity.Site, toolboxItem, true); if (activities.Length > 0) { CompositeActivityDesigner.InsertActivities(compositeActivityDesigner, hitInfo, new List (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 } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. #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 /// /// 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. /// [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)] 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 ListdesignerActions; [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 /// /// Gets activity being designed by the designer. /// public Activity Activity { get { return this.activity; } } ////// Gets the parent designer of existing designer /// 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; } } ////// Gets value indicating if the activity associated with the designer is selected. /// public bool IsSelected { get { ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService; return (selectionService != null && selectionService.GetComponentSelected(Activity)); } } ////// Gets value indicating if the activity associated with the designer is primary selection. /// public bool IsPrimarySelection { get { ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService; return (selectionService != null && selectionService.PrimarySelection == Activity); } } ////// Gets the accessibility object associated with the designer /// public virtual AccessibleObject AccessibilityObject { get { if (this.accessibilityObject == null) this.accessibilityObject = new ActivityDesignerAccessibleObject(this); return this.accessibilityObject; } } ////// 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. /// public virtual bool IsVisible { get { return this.isVisible; } } ////// 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. /// 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; } } ////// Gets or Sets the location of the designer in logical coordinates. /// public virtual Point Location { get { return this.location; } set { if (ParentDesigner is FreeformActivityDesigner) value = DesignerHelpers.SnapToGrid(value); if (this.location != value) this.location = value; } } ////// Gets or Sets the size of the designer. /// 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; } } ////// Get the minimum size of the designer /// public virtual Size MinimumSize { get { return DesignerTheme.Size; } } ////// Get value for enclosing rectangle of the designer in logical coordinates. /// public Rectangle Bounds { get { //Bounds contain designer rectangle + the selection area return new Rectangle(Location, Size); } } ////// Gets the image associated with the designer. /// public virtual Image Image { get { return this.image; } protected set { this.image = value; PerformLayout(); } } ////// Gets the text associated with the designer. /// public virtual string Text { get { return this.text; } protected set { if (value == null || value.Length == 0 || this.text == value) return; this.text = value; PerformLayout(); } } ////// Gets the current theme to be used for the designer /// public ActivityDesignerTheme DesignerTheme { get { return WorkflowTheme.CurrentTheme.GetDesignerTheme(this); } } ////// Gets the value indicating if the designer is root designer. /// 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 ////// Returns the WorkflowView containing the designer /// protected internal WorkflowView ParentView { get { return GetService(typeof(WorkflowView)) as WorkflowView; } } ////// Gets the collection of verbs to be associated with the designer. /// The verbs are shown on context menu and the top level workflow menu. /// 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; } } ////// Gets or sets the value indicating if smarttag should be shown. /// protected virtual bool ShowSmartTag { get { return false; } } ////// Gets the array of actions which the designer wants to associated with the smarttag. /// protected virtual ReadOnlyCollectionSmartTagVerbs { get { return new List ().AsReadOnly(); } } /// /// Gets the Rectangle where the smarttag needs to be displayed /// protected virtual Rectangle SmartTagRectangle { get { Rectangle smartTagRectangle = Rectangle.Empty; Rectangle imageRectangle = ImageRectangle; if (!imageRectangle.Size.IsEmpty) { smartTagRectangle = imageRectangle; } return smartTagRectangle; } } ////// Gets the array of actions associated with the configuration errors. /// protected internal virtual ReadOnlyCollectionDesignerActions { get { if (this.designerActions == null) { this.designerActions = new List (); 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(); } } /// /// Gets the array of glyphs with which to adorn the designer. /// 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; } } ////// Gets the value of text rectangle in logical coordinates. /// 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; } } ////// Gets the value for enclosing bounds image associated with the designer in logical coordinates. /// 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 ReadOnlyCollectionMessageFilters { get { List stockFilters = new List (); 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(); } } /// /// Get if the designer is resizable using the rubberbanding when dropped in FreeformDesigner /// 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 { ListpropertyDescriptors = new List (); //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 propertyDescriptors = new List (); 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 rules = DesignerHelpers.GetDeclarativeRules(Activity); if (rules.Count > 0) { this.rulesText = DR.GetString(DR.Rules); int maxRulesLength = 3 * (MaximumIdentifierLength + MaximumDescriptionLength); foreach (KeyValuePair 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 activities = new List (); 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; } /// /// Returns if the Activity is commented or is inside commented activity /// /// ///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 /// /// 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. /// /// CompositeActivity which can be potentially set as parent. ///True if the CompositeActivity can be set as parent of activity associated with designer, false otherwise. public virtual bool CanBeParentedTo(CompositeActivityDesigner parentActivityDesigner) { if (parentActivityDesigner == null) throw new ArgumentNullException("parentActivityDesigner"); return true; } ////// Allows detection of the area hit on the designer. /// /// Point to test in logical coordinates. ///Information indicating where the hit happened 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 ReadOnlyCollectionconnectionPoints = 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; } /// /// Brings designer in viewable area /// public void EnsureVisible() { WorkflowView parentView = ParentView; if (parentView != null) parentView.EnsureVisible(Activity); } ////// Get the points used to connect the designer. Points are in logical coordinates. /// public virtual ReadOnlyCollectionGetConnectionPoints(DesignerEdges edges) { List connectionPoints = new List (); 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(); } /// /// Invalidates the entire workflow designer /// 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)); } } } ////// Invalidates specified rectangle on the designer /// /// Rectangle to invalidate public void Invalidate(Rectangle rectangle) { WorkflowView parentView = ParentView; if (parentView != null) { rectangle = Rectangle.Intersect(Bounds, rectangle); parentView.InvalidateLogicalRectangle(rectangle); } } ////// Get image of the activity designer on specified graphics /// /// Graphics objects to draw image ///Image which is drawn 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)); Queuedesigners = new Queue (); 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 /// /// Initializes the designer with associated activity. /// /// Activity with which the designer needs to be initialized. 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); } ////// Disposes the resources held by the designer. /// /// True if the designer is being disposed, false if the designer is being finalized. 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); } } } } ////// Get the points used to connect the designer. Points are in logical coordinates. /// protected internal virtual ReadOnlyCollectionGetConnections(DesignerEdges edges) { Rectangle bounds = Bounds; List connections = new List (); 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(); } /// /// Perform default UI action associated with the designer. /// Example: Emit method associated with default event in code beside file on double click. /// 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); } } } } } ////// When overridden in a derived class, allows a designer to add items to the set of attributes that it exposes through a TypeDescriptor. /// /// The Attribute objects for the class of the activity. The keys in the dictionary of attributes are the TypeID values of the attributes. protected virtual void PreFilterAttributes(IDictionary attributes) { if (attributes == null) throw new ArgumentNullException("attributes"); } ////// When overridden in a derived class, allows a designer to add items to the set of properties that it exposes through a TypeDescriptor. /// /// The PropertyDescriptor objects that represent the properties of the class of the activity. The keys in the dictionary of properties are property names. protected virtual void PreFilterProperties(IDictionary properties) { if (properties == null) throw new ArgumentNullException("properties"); } ////// When overridden in a derived class, allows a designer to add items to the set of events that it exposes through a TypeDescriptor. /// /// The EventDescriptor objects that represent the events of the class of the activity. The keys in the dictionary of events are event names. protected virtual void PreFilterEvents(IDictionary events) { if (events == null) throw new ArgumentNullException("events"); } ////// 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. /// /// The Attribute objects for the class of the activity. The keys in the dictionary of attributes are the TypeID values of the attributes. protected virtual void PostFilterAttributes(IDictionary attributes) { if (attributes == null) throw new ArgumentNullException("attributes"); } ////// 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. /// /// The PropertyDescriptor objects that represent the properties of the class of the activity. The keys in the dictionary of properties are property names. 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); } ////// 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. /// /// The EventDescriptor objects that represent the events of the class of the activity. The keys in the dictionary of events are event names. protected virtual void PostFilterEvents(IDictionary events) { if (events == null) throw new ArgumentNullException("events"); } ////// Attempts to retrieve the specified type of service from the designer's activity's design mode site. /// /// The type of service to request. ///An object implementing the requested service, or a null reference (Nothing in Visual Basic) if the service cannot be resolved. 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; } ////// Called when the users begins to drag mouse on the designer. /// /// Point where the drag started in logical coordinates /// MouseEventArgs containing event data. protected virtual void OnMouseDragBegin(Point initialDragPoint, MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the users drags mouse over the designer. /// /// MouseEventArgs containing event data. protected virtual void OnMouseDragMove(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the mouse drag ends. /// protected virtual void OnMouseDragEnd() { } ////// Called when the mouse cursor enters the designer bounds. /// /// MouseEventArgs containing event data. protected virtual void OnMouseEnter(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); if (IsVisible) { if (ShowSmartTag) SmartTagVisible = true; ShowInfoTip(InfoTipTitle, InfoTipText); } } ////// Called when the mouse button is clicked when mouse cursor is in designer bounds. /// /// MouseEventArgs containing event data. protected virtual void OnMouseDown(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the mouse cursor is moving in designer bounds. /// /// MouseEventArgs containing event data. protected virtual void OnMouseMove(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); if (IsVisible) ShowInfoTip(InfoTipTitle, InfoTipText); } ////// Called when the mouse cursor is in designer bounds. /// /// MouseEventArgs containing event data. protected virtual void OnMouseHover(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); if (IsVisible) ShowInfoTip(InfoTipTitle, InfoTipText); } ////// Called when the moused button is released when mouse cursor is in designer bounds. /// /// MouseEventArgs containing event data. protected virtual void OnMouseUp(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the mouse button is clicked multiple times on the designer /// /// MouseEventArgs containing event data. protected virtual void OnMouseDoubleClick(MouseEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the mouse cursor leaves designer bounds. /// protected virtual void OnMouseLeave() { if (ShowSmartTag) SmartTagVisible = false; ShowInfoTip(String.Empty); } ////// Called when the mouse capture changes /// protected virtual void OnMouseCaptureChanged() { } ////// Called when the drag drop operation is in progress and mouse cursor enters the designer bounds. /// /// Drag drop event arguments. protected virtual void OnDragEnter(ActivityDragEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the drag drop operation is in progress and mouse cursor is inside the designer bounds. /// /// Drag drop event arguments. protected virtual void OnDragOver(ActivityDragEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when the drag drop operation is in progress and mouse cursor leaves the designer bounds. /// protected virtual void OnDragLeave() { } ////// Called when the drag drop operation is completed inside designer bounds. /// /// Drag drop event arguments. protected virtual void OnDragDrop(ActivityDragEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Updates the visual cues for feedback given to the user when performing drag drop operation. /// /// A GiveFeedbackEventArgs that contains the event data. protected virtual void OnGiveFeedback(GiveFeedbackEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Controls if the drag drop operation should continue. /// /// A QueryContinueDragEventArgs that contains the event data. protected virtual void OnQueryContinueDrag(QueryContinueDragEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when key is pressed when designer has keyboard focus. /// /// protected virtual void OnKeyDown(KeyEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when key is released when designer has keyboard focus. /// /// protected virtual void OnKeyUp(KeyEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called when scroll position is changed /// /// Scrollbar sending the message /// New value of the scrolled position protected virtual void OnScroll(ScrollBar sender, int value) { } ////// Allows designer to process raw win32 message /// /// Message structure containing details of the message to be processed protected virtual void OnProcessMessage(Message message) { } ////// Called to refresh the configuration errors associated with designers. /// protected internal virtual void RefreshDesignerActions() { this.designerActions = null; } ////// Called when user clicks on configuration errors associated with the designer. /// /// Designer action associated with configuration error. 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); } } ////// Called to notify the designer if the SmartTag is being shown or hidden /// /// Indicates if the SmartTag is being shown or hidden 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); } ////// Shows the designer verbs associated with smarttag at specific point /// /// Point at which to show the actions protected virtual void OnShowSmartTagVerbs(Point smartTagPoint) { ActivityDesignerVerb[] verbs = null; SmartTagVerbs.CopyTo(verbs, 0); DesignerHelpers.ShowDesignerVerbs(this, PointToScreen(smartTagPoint), verbs); } ////// Notifies the designer that the associated theme has changed. /// protected virtual void OnThemeChange(ActivityDesignerTheme newTheme) { if (newTheme == null) throw new ArgumentNullException("newTheme"); this.Image = StockImage; } ////// Stores the UI state of the designer in binary stream. /// /// BinaryWriter used to store the state. protected virtual void SaveViewState(BinaryWriter writer) { if (writer == null) throw new ArgumentNullException("writer"); } ////// Restores the UI state of the designer from binary stream. /// /// BinaryReader used to restore the designer state. ///protected virtual void LoadViewState(BinaryReader reader) { if (reader == null) throw new ArgumentNullException("reader"); } /// /// 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 /// /// Type of the activity being queried ///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; } /// /// Refreshes the ActivityDesignerVerbs associted with the designer by calling status handler. /// 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; } } } } ////// Draws the visual representation of activity at design time. /// /// ActivityDesignerPaintEventArgs holding drawing arguments 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); } ////// Called to layout the position of contained visual cues or designers. /// /// ActivityDesignerLayoutEventArgs holding layout arguments protected virtual void OnLayoutPosition(ActivityDesignerLayoutEventArgs e) { if (e == null) throw new ArgumentNullException("e"); } ////// Called to set the size of the visual cues or designers contained within the designer. /// /// ActivityDesignerLayoutEventArgs holding layout arguments 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; } ////// Called when the user starts to visually resize the designer when designer is inside freeform designer /// /// protected virtual void OnBeginResizing(ActivityDesignerResizeEventArgs e) { } ////// Called when the user is visually resizing the designer when designer is inside freeform designer /// /// ActivityDesignerResizeEventArgs specifying the edge being used to resize and new bounds protected virtual void OnResizing(ActivityDesignerResizeEventArgs e) { FreeformActivityDesigner.SetDesignerBounds(this, e.Bounds); } ////// Called when user is done resizing the designer /// protected virtual void OnEndResizing() { PerformLayout(); } ////// Called to check if connection can be established between source and target designer /// /// Source connection point /// Target connection point ///True if connection can be established, false otherwise protected virtual bool CanConnect(ConnectionPoint source, ConnectionPoint target) { return true; } ////// Called when connection is established between two connection points /// /// Source connection point /// Target connection point protected virtual void OnConnected(ConnectionPoint source, ConnectionPoint target) { } ////// Called when the activity associated with the designer is changed. /// /// A ActivityChangedEventArgs containing information about what changed. 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; } ////// Shows specified tooltip /// /// String specifying the tooltip title /// String specifying the tooltip to display protected void ShowInfoTip(string title, string infoTip) { WorkflowView parentView = ParentView; if (parentView != null) parentView.ShowInfoTip(title, infoTip); } ////// Shows specified tooltip /// /// String specifying the tooltip to display protected void ShowInfoTip(string infoTip) { WorkflowView parentView = ParentView; if (parentView != null) parentView.ShowInfoTip(infoTip); } ////// Shows tooltip at specified location /// /// String specifying the tooltip to display /// Rectangle where to display tooltip protected void ShowInPlaceTip(string infoTip, Rectangle rectangle) { WorkflowView parentView = ParentView; if (parentView != null) parentView.ShowInPlaceToolTip(infoTip, parentView.LogicalRectangleToClient(rectangle)); } ////// Updates the layout of the designer /// protected void PerformLayout() { WorkflowView parentView = ParentView; if (parentView != null) parentView.PerformLayout(false); } ////// Transforms point from activity designer coordinate system to screen /// /// Point in activity designer coordinate system ///Point in screen coordinate system protected Point PointToScreen(Point point) { WorkflowView parentView = ParentView; if (parentView != null) return parentView.LogicalPointToScreen(point); else return point; } ////// Transforms point from screen coordinate system to activity designer coordinate system /// /// Point in screen coordinate system ///Point in activity designer coordinate system protected Point PointToLogical(Point point) { WorkflowView parentView = ParentView; if (parentView != null) return parentView.ScreenPointToLogical(point); else return point; } ////// Transforms rectangle from activity designer coordinate system to screen /// /// Rectangle in activity designer coordinate system ///Rectangle in screen coordinate system 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); } ////// Transforms rectangle from screen coordinate system to activity designer coordinate system /// /// Rectangle in screen coordinate system ///Rectangle in activity designer coordinate system 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); Listproperties = CustomActivityDesignerHelper.GetCustomProperties(serviceProvider); if (properties == null) return; // get all the members of the custom activity to ensure uniqueness Type customActivityType = CustomActivityDesignerHelper.GetCustomActivityType(serviceProvider); List customPropertyNames = new List (); 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 promotedProperties = new Dictionary (); 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 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 (activities).AsReadOnly())) return; try { activities = CompositeActivityDesigner.DeserializeActivitiesFromToolboxItem(Activity.Site, toolboxItem, true); if (activities.Length > 0) { CompositeActivityDesigner.InsertActivities(compositeActivityDesigner, hitInfo, new List (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 } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- QuadraticBezierSegment.cs
- EditBehavior.cs
- SiteMapSection.cs
- XmlReaderSettings.cs
- AnnotationResourceChangedEventArgs.cs
- ListViewGroupItemCollection.cs
- UniqueEventHelper.cs
- DbConnectionStringCommon.cs
- GraphicsPathIterator.cs
- TdsValueSetter.cs
- AudioSignalProblemOccurredEventArgs.cs
- RepeaterCommandEventArgs.cs
- SimpleType.cs
- NetWebProxyFinder.cs
- DataGridRelationshipRow.cs
- ProviderSettingsCollection.cs
- PhysicalFontFamily.cs
- ComponentEvent.cs
- COAUTHIDENTITY.cs
- FormsAuthenticationUser.cs
- PointAnimationUsingPath.cs
- ConfigViewGenerator.cs
- ServiceHostingEnvironment.cs
- ProcessingInstructionAction.cs
- ProfileManager.cs
- InkCanvasSelection.cs
- connectionpool.cs
- CalendarDay.cs
- PagesSection.cs
- PathFigureCollectionConverter.cs
- CodeExpressionCollection.cs
- SortExpressionBuilder.cs
- RSAPKCS1KeyExchangeFormatter.cs
- HashCodeCombiner.cs
- RangeValuePattern.cs
- PrintDialog.cs
- CompilerGlobalScopeAttribute.cs
- StreamGeometry.cs
- NativeCompoundFileAPIs.cs
- ResourceReader.cs
- XmlJsonWriter.cs
- ConnectionConsumerAttribute.cs
- XamlReaderHelper.cs
- BindingManagerDataErrorEventArgs.cs
- TypeGeneratedEventArgs.cs
- ThreadStartException.cs
- LocalClientSecuritySettings.cs
- SqlDependency.cs
- CompletionCallbackWrapper.cs
- UserInitiatedRoutedEventPermissionAttribute.cs
- PaintEvent.cs
- DocumentEventArgs.cs
- DataGrid.cs
- DataGridRowDetailsEventArgs.cs
- ThemeDictionaryExtension.cs
- IBuiltInEvidence.cs
- VariableQuery.cs
- Operators.cs
- XsltException.cs
- MeshGeometry3D.cs
- ClientRoleProvider.cs
- ListControl.cs
- TreeNodeCollection.cs
- PolicyChain.cs
- FilteredDataSetHelper.cs
- DataSourceCacheDurationConverter.cs
- XmlElementElement.cs
- Utils.cs
- Triplet.cs
- WebMessageEncodingElement.cs
- SymmetricAlgorithm.cs
- RoleManagerEventArgs.cs
- AutomationPattern.cs
- SurrogateEncoder.cs
- ObjectDataProvider.cs
- ErrorStyle.cs
- ToolStripContentPanelRenderEventArgs.cs
- UpdateExpressionVisitor.cs
- MetadataItemCollectionFactory.cs
- SQLBytesStorage.cs
- HwndPanningFeedback.cs
- RecognizerInfo.cs
- Point3DValueSerializer.cs
- StickyNoteContentControl.cs
- Selector.cs
- BaseValidator.cs
- RoleGroup.cs
- IconBitmapDecoder.cs
- PagePropertiesChangingEventArgs.cs
- QilInvoke.cs
- AffineTransform3D.cs
- XPathNavigatorKeyComparer.cs
- TypeExtensionConverter.cs
- VectorKeyFrameCollection.cs
- LocalizedNameDescriptionPair.cs
- LinkedResourceCollection.cs
- XdrBuilder.cs
- Screen.cs
- TokenBasedSet.cs
- StorageRoot.cs