File: Designers\SetStateDesigner.cs
Project: ndp\cdf\src\WF\Activities\System.Workflow.Activities.csproj (System.Workflow.Activities)
namespace System.Workflow.Activities
{
    using System;
    using System.Text;
    using System.Reflection;
    using System.Collections;
    using System.CodeDom;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Diagnostics;
    using System.Drawing;
    using System.Drawing.Design;
    using System.Drawing.Drawing2D;
    using System.Security;
    using System.Security.Permissions;
    using System.Workflow.Activities;
    using System.Workflow.ComponentModel;
    using System.Workflow.ComponentModel.Design;
    using System.Windows.Forms;
    using System.Windows.Forms.Design;
 
    #region Class SetStateDesigner
 
    [ActivityDesignerTheme(typeof(SetStateDesignerTheme))]
    [System.Runtime.InteropServices.ComVisible(false)]
    internal sealed class SetStateDesigner : ActivityDesigner
    {
        #region Fields
 
        private string previousTargetState = String.Empty;
        private Size targetStateSize = Size.Empty;
 
        #endregion Fields
 
        #region Properties
 
        #region Protected Properties
 
 
        protected override Rectangle TextRectangle
        {
            get
            {
                Size margin = WorkflowTheme.CurrentTheme.AmbientTheme.Margin;
                Rectangle textRectangle = base.TextRectangle;
                textRectangle.Offset(0, (-targetStateSize.Height - margin.Height) / 2);
                return textRectangle;
            }
        }
 
        protected override Rectangle ImageRectangle
        {
            get
            {
                Size margin = WorkflowTheme.CurrentTheme.AmbientTheme.Margin;
                Rectangle imageRectangle = base.ImageRectangle;
                imageRectangle.Offset(0, (-targetStateSize.Height - margin.Height) / 2);
                return imageRectangle;
            }
        }
 
        #endregion
 
        #region Private Properties
 
        private string TargetState
        {
            get
            {
                SetStateActivity setState = this.Activity as SetStateActivity;
                if (setState == null)
                    return String.Empty;
 
                string targetState = setState.TargetStateName;
                if (targetState == null)
                    return String.Empty;
 
                return targetState;
            }
        }
 
        /// <summary>
        /// Gets the value of text rectangle in logical coordinates.
        /// </summary>
        internal Rectangle TargetStateRectangle
        {
            get
            {
                Size margin = WorkflowTheme.CurrentTheme.AmbientTheme.Margin;
 
                Rectangle bounds = this.Bounds;
                Rectangle textRectangle = this.TextRectangle;
                Point location = new Point(
                    bounds.Left + margin.Width,
                    textRectangle.Bottom + (margin.Height / 2));
                Size size = new Size(
                    bounds.Width - margin.Width * 2,
                    targetStateSize.Height);
                return new Rectangle(location, size);
            }
        }
        #endregion Private Properties
 
        #endregion Properties
 
        #region Methods
 
        #region Public Methods
 
        public override bool CanBeParentedTo(CompositeActivityDesigner parentActivityDesigner)
        {
            if (parentActivityDesigner == null)
                throw new ArgumentNullException("parentActivityDesigner");
 
            CompositeActivity parentActivity = parentActivityDesigner.Activity as CompositeActivity;
            if (parentActivity == null)
                return false;
 
            bool result = ValidateParent(parentActivity);
            if (!result)
                return false;
 
            return base.CanBeParentedTo(parentActivityDesigner);
        }
 
        #endregion Public Methods
 
        #region Protected Methods
 
        protected override void OnActivityChanged(ActivityChangedEventArgs e)
        {
            base.OnActivityChanged(e);
 
            if (previousTargetState != this.TargetState)
                PerformLayout();
        }
 
        /// <summary>
        /// Called to set the size of the visual cues or designers contained within the designer.
        /// </summary>
        /// <param name="e">ActivityDesignerLayoutEventArgs holding layout arguments</param>
        protected override Size OnLayoutSize(ActivityDesignerLayoutEventArgs e)
        {
            Size size = base.OnLayoutSize(e);
 
            string targetState = this.TargetState;
            if (String.IsNullOrEmpty(targetState))
            {
                // We use a dummy string so we don't 
                // calculate an empty rectangle
                targetState = "M";
            }
 
            Font font = e.DesignerTheme.Font;
 
            this.targetStateSize = StateMachineDesignerPaint.MeasureString(e.Graphics,
                font,
                targetState,
                StringAlignment.Near,
                Size.Empty);
 
            size.Height += targetStateSize.Height;
            return size;
        }
 
        protected override void OnPaint(ActivityDesignerPaintEventArgs e)
        {
            base.OnPaint(e);
 
            string targetState = this.TargetState;
 
            ActivityDesignerPaint.DrawText(e.Graphics,
                e.DesignerTheme.Font,
                targetState,
                this.TargetStateRectangle,
                StringAlignment.Center,
                e.AmbientTheme.TextQuality,
                e.DesignerTheme.ForegroundBrush);
        }
 
        #endregion Protected Methods
 
        #region Static Private Methods
 
        static private bool ValidateParent(CompositeActivity parentActivity)
        {
            if (parentActivity == null)
                return false;
 
            if (SetStateValidator.IsValidContainer(parentActivity))
                return true;
 
            return ValidateParent(parentActivity.Parent);
        }
 
        #endregion Static Private Methods
 
        #endregion Methods
 
    }
 
    #endregion
 
    #region SetStateDesignerTheme
    internal sealed class SetStateDesignerTheme : ActivityDesignerTheme
    {
        public SetStateDesignerTheme(WorkflowTheme theme)
            : base(theme)
        {
            this.ForeColor = Color.FromArgb(0xFF, 0x00, 0x00, 0x00);
            this.BorderColor = Color.FromArgb(0xFF, 0x80, 0x80, 0x80);
            this.BorderStyle = DashStyle.Solid;
            this.BackColorStart = Color.FromArgb(0xFF, 0xF4, 0xF4, 0xF4);
            this.BackColorEnd = Color.FromArgb(0xFF, 0xC0, 0xC0, 0xC0);
            this.BackgroundStyle = LinearGradientMode.Horizontal;
        }
    }
    #endregion
 
    #region Class StateDropDownEditor
 
    internal sealed class StateDropDownEditor : UITypeEditor
    {
        #region Fields
        private IWindowsFormsEditorService _editorService;
        private ITypeDescriptorContext _context;
        private object _selectedObject;
        #endregion Fields
 
        #region Constructors/Destructors
        public StateDropDownEditor()
        {
        }
        #endregion Constructors/Destructors
 
        #region Methods
 
        #region Public Methods
        public override object EditValue(ITypeDescriptorContext typeDescriptorContext, IServiceProvider serviceProvider, object value)
        {
            if (typeDescriptorContext == null)
                throw new ArgumentNullException("typeDescriptorContext");
            if (serviceProvider == null)
                throw new ArgumentNullException("serviceProvider");
            _editorService = (IWindowsFormsEditorService)serviceProvider.GetService(typeof(IWindowsFormsEditorService));
            _context = typeDescriptorContext;
 
            // Initialize the dropdown control
            ListBox dropDownList = new ListBox();
            dropDownList.BorderStyle = BorderStyle.None;
 
            Activity activity = _context.Instance as Activity;
            if (activity == null)
            {
                // this could happen when there are multiple 
                // SetState activities selected
                object[] activities = _context.Instance as object[];
                if (activities != null && activities.Length > 0)
                    activity = (Activity)activities[0];
            }
            Debug.Assert(activity != null);
 
            // Add the items from the typeconverter, followed by the datasource choices
            PopulateDropDownList(dropDownList, activity);
 
            dropDownList.SelectedIndexChanged += new EventHandler(dataSourceDropDown_SelectedIndexChanged);
 
            // Display the control
            _editorService.DropDownControl(dropDownList);
 
            // If a value was selected, read the selected value from the control and return it
            if (dropDownList.SelectedIndex != -1 && _selectedObject != null)
                return _selectedObject;
 
            return value;
        }
 
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext typeDescriptorContext)
        {
            return UITypeEditorEditStyle.DropDown;
        }
 
        #endregion Public Methods
 
        #region Private Methods
 
        private void dataSourceDropDown_SelectedIndexChanged(object sender, EventArgs e)
        {
            _editorService.CloseDropDown();
            _selectedObject = null;
 
            ListBox dropDownList = sender as ListBox;
            if (dropDownList == null)
                throw new ArgumentNullException("sender");
 
            if (dropDownList.SelectedIndex < 0)
                return;
 
            _selectedObject = dropDownList.Items[dropDownList.SelectedIndex];
        }
 
        private void PopulateDropDownList(ListBox dropDownList, Activity activity)
        {
            Debug.Assert(dropDownList != null);
            Debug.Assert(activity != null);
 
            StateActivity enclosingState = StateMachineHelpers.FindEnclosingState(activity);
            if (enclosingState == null)
                return;
 
            StateActivity rootState = StateMachineHelpers.GetRootState(enclosingState);
 
            FindStates(dropDownList, rootState);
        }
 
        private void FindStates(ListBox dropDownList, StateActivity parent)
        {
            foreach (Activity activity in parent.EnabledActivities)
            {
                StateActivity state = activity as StateActivity;
                if (state != null)
                {
                    if (StateMachineHelpers.IsLeafState(state))
                    {
                        dropDownList.Items.Add(state.QualifiedName);
                    }
                    else
                    {
                        FindStates(dropDownList, state);
                    }
                }
            }
        }
 
        #endregion Private Methods
 
        #endregion Methods
    }
 
    #endregion Class StateDropDownEditor
}