e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
342 lines
11 KiB
C#
342 lines
11 KiB
C#
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
|
|
}
|