1 namespace System.Workflow.Activities
2 {
3     using System;
4     using System.Text;
5     using System.Reflection;
6     using System.Collections;
7     using System.CodeDom;
8     using System.ComponentModel;
9     using System.ComponentModel.Design;
10     using System.Diagnostics;
11     using System.Drawing;
12     using System.Drawing.Design;
13     using System.Drawing.Drawing2D;
14     using System.Security;
15     using System.Security.Permissions;
16     using System.Workflow.Activities;
17     using System.Workflow.ComponentModel;
18     using System.Workflow.ComponentModel.Design;
19     using System.Windows.Forms;
20     using System.Windows.Forms.Design;
21 
22     #region Class SetStateDesigner
23 
24     [ActivityDesignerTheme(typeof(SetStateDesignerTheme))]
25     [System.Runtime.InteropServices.ComVisible(false)]
26     internal sealed class SetStateDesigner : ActivityDesigner
27     {
28         #region Fields
29 
30         private string previousTargetState = String.Empty;
31         private Size targetStateSize = Size.Empty;
32 
33         #endregion Fields
34 
35         #region Properties
36 
37         #region Protected Properties
38 
39 
40         protected override Rectangle TextRectangle
41         {
42             get
43             {
44                 Size margin = WorkflowTheme.CurrentTheme.AmbientTheme.Margin;
45                 Rectangle textRectangle = base.TextRectangle;
46                 textRectangle.Offset(0, (-targetStateSize.Height - margin.Height) / 2);
47                 return textRectangle;
48             }
49         }
50 
51         protected override Rectangle ImageRectangle
52         {
53             get
54             {
55                 Size margin = WorkflowTheme.CurrentTheme.AmbientTheme.Margin;
56                 Rectangle imageRectangle = base.ImageRectangle;
57                 imageRectangle.Offset(0, (-targetStateSize.Height - margin.Height) / 2);
58                 return imageRectangle;
59             }
60         }
61 
62         #endregion
63 
64         #region Private Properties
65 
66         private string TargetState
67         {
68             get
69             {
70                 SetStateActivity setState = this.Activity as SetStateActivity;
71                 if (setState == null)
72                     return String.Empty;
73 
74                 string targetState = setState.TargetStateName;
75                 if (targetState == null)
76                     return String.Empty;
77 
78                 return targetState;
79             }
80         }
81 
82         /// <summary>
83         /// Gets the value of text rectangle in logical coordinates.
84         /// </summary>
85         internal Rectangle TargetStateRectangle
86         {
87             get
88             {
89                 Size margin = WorkflowTheme.CurrentTheme.AmbientTheme.Margin;
90 
91                 Rectangle bounds = this.Bounds;
92                 Rectangle textRectangle = this.TextRectangle;
93                 Point location = new Point(
94                     bounds.Left + margin.Width,
95                     textRectangle.Bottom + (margin.Height / 2));
96                 Size size = new Size(
97                     bounds.Width - margin.Width * 2,
98                     targetStateSize.Height);
99                 return new Rectangle(location, size);
100             }
101         }
102         #endregion Private Properties
103 
104         #endregion Properties
105 
106         #region Methods
107 
108         #region Public Methods
109 
CanBeParentedTo(CompositeActivityDesigner parentActivityDesigner)110         public override bool CanBeParentedTo(CompositeActivityDesigner parentActivityDesigner)
111         {
112             if (parentActivityDesigner == null)
113                 throw new ArgumentNullException("parentActivityDesigner");
114 
115             CompositeActivity parentActivity = parentActivityDesigner.Activity as CompositeActivity;
116             if (parentActivity == null)
117                 return false;
118 
119             bool result = ValidateParent(parentActivity);
120             if (!result)
121                 return false;
122 
123             return base.CanBeParentedTo(parentActivityDesigner);
124         }
125 
126         #endregion Public Methods
127 
128         #region Protected Methods
129 
OnActivityChanged(ActivityChangedEventArgs e)130         protected override void OnActivityChanged(ActivityChangedEventArgs e)
131         {
132             base.OnActivityChanged(e);
133 
134             if (previousTargetState != this.TargetState)
135                 PerformLayout();
136         }
137 
138         /// <summary>
139         /// Called to set the size of the visual cues or designers contained within the designer.
140         /// </summary>
141         /// <param name="e">ActivityDesignerLayoutEventArgs holding layout arguments</param>
OnLayoutSize(ActivityDesignerLayoutEventArgs e)142         protected override Size OnLayoutSize(ActivityDesignerLayoutEventArgs e)
143         {
144             Size size = base.OnLayoutSize(e);
145 
146             string targetState = this.TargetState;
147             if (String.IsNullOrEmpty(targetState))
148             {
149                 // We use a dummy string so we don't
150                 // calculate an empty rectangle
151                 targetState = "M";
152             }
153 
154             Font font = e.DesignerTheme.Font;
155 
156             this.targetStateSize = StateMachineDesignerPaint.MeasureString(e.Graphics,
157                 font,
158                 targetState,
159                 StringAlignment.Near,
160                 Size.Empty);
161 
162             size.Height += targetStateSize.Height;
163             return size;
164         }
165 
OnPaint(ActivityDesignerPaintEventArgs e)166         protected override void OnPaint(ActivityDesignerPaintEventArgs e)
167         {
168             base.OnPaint(e);
169 
170             string targetState = this.TargetState;
171 
172             ActivityDesignerPaint.DrawText(e.Graphics,
173                 e.DesignerTheme.Font,
174                 targetState,
175                 this.TargetStateRectangle,
176                 StringAlignment.Center,
177                 e.AmbientTheme.TextQuality,
178                 e.DesignerTheme.ForegroundBrush);
179         }
180 
181         #endregion Protected Methods
182 
183         #region Static Private Methods
184 
ValidateParent(CompositeActivity parentActivity)185         static private bool ValidateParent(CompositeActivity parentActivity)
186         {
187             if (parentActivity == null)
188                 return false;
189 
190             if (SetStateValidator.IsValidContainer(parentActivity))
191                 return true;
192 
193             return ValidateParent(parentActivity.Parent);
194         }
195 
196         #endregion Static Private Methods
197 
198         #endregion Methods
199 
200     }
201 
202     #endregion
203 
204     #region SetStateDesignerTheme
205     internal sealed class SetStateDesignerTheme : ActivityDesignerTheme
206     {
SetStateDesignerTheme(WorkflowTheme theme)207         public SetStateDesignerTheme(WorkflowTheme theme)
208             : base(theme)
209         {
210             this.ForeColor = Color.FromArgb(0xFF, 0x00, 0x00, 0x00);
211             this.BorderColor = Color.FromArgb(0xFF, 0x80, 0x80, 0x80);
212             this.BorderStyle = DashStyle.Solid;
213             this.BackColorStart = Color.FromArgb(0xFF, 0xF4, 0xF4, 0xF4);
214             this.BackColorEnd = Color.FromArgb(0xFF, 0xC0, 0xC0, 0xC0);
215             this.BackgroundStyle = LinearGradientMode.Horizontal;
216         }
217     }
218     #endregion
219 
220     #region Class StateDropDownEditor
221 
222     internal sealed class StateDropDownEditor : UITypeEditor
223     {
224         #region Fields
225         private IWindowsFormsEditorService _editorService;
226         private ITypeDescriptorContext _context;
227         private object _selectedObject;
228         #endregion Fields
229 
230         #region Constructors/Destructors
StateDropDownEditor()231         public StateDropDownEditor()
232         {
233         }
234         #endregion Constructors/Destructors
235 
236         #region Methods
237 
238         #region Public Methods
EditValue(ITypeDescriptorContext typeDescriptorContext, IServiceProvider serviceProvider, object value)239         public override object EditValue(ITypeDescriptorContext typeDescriptorContext, IServiceProvider serviceProvider, object value)
240         {
241             if (typeDescriptorContext == null)
242                 throw new ArgumentNullException("typeDescriptorContext");
243             if (serviceProvider == null)
244                 throw new ArgumentNullException("serviceProvider");
245             _editorService = (IWindowsFormsEditorService)serviceProvider.GetService(typeof(IWindowsFormsEditorService));
246             _context = typeDescriptorContext;
247 
248             // Initialize the dropdown control
249             ListBox dropDownList = new ListBox();
250             dropDownList.BorderStyle = BorderStyle.None;
251 
252             Activity activity = _context.Instance as Activity;
253             if (activity == null)
254             {
255                 // this could happen when there are multiple
256                 // SetState activities selected
257                 object[] activities = _context.Instance as object[];
258                 if (activities != null && activities.Length > 0)
259                     activity = (Activity)activities[0];
260             }
261             Debug.Assert(activity != null);
262 
263             // Add the items from the typeconverter, followed by the datasource choices
264             PopulateDropDownList(dropDownList, activity);
265 
266             dropDownList.SelectedIndexChanged += new EventHandler(dataSourceDropDown_SelectedIndexChanged);
267 
268             // Display the control
269             _editorService.DropDownControl(dropDownList);
270 
271             // If a value was selected, read the selected value from the control and return it
272             if (dropDownList.SelectedIndex != -1 && _selectedObject != null)
273                 return _selectedObject;
274 
275             return value;
276         }
277 
GetEditStyle(ITypeDescriptorContext typeDescriptorContext)278         public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext typeDescriptorContext)
279         {
280             return UITypeEditorEditStyle.DropDown;
281         }
282 
283         #endregion Public Methods
284 
285         #region Private Methods
286 
dataSourceDropDown_SelectedIndexChanged(object sender, EventArgs e)287         private void dataSourceDropDown_SelectedIndexChanged(object sender, EventArgs e)
288         {
289             _editorService.CloseDropDown();
290             _selectedObject = null;
291 
292             ListBox dropDownList = sender as ListBox;
293             if (dropDownList == null)
294                 throw new ArgumentNullException("sender");
295 
296             if (dropDownList.SelectedIndex < 0)
297                 return;
298 
299             _selectedObject = dropDownList.Items[dropDownList.SelectedIndex];
300         }
301 
PopulateDropDownList(ListBox dropDownList, Activity activity)302         private void PopulateDropDownList(ListBox dropDownList, Activity activity)
303         {
304             Debug.Assert(dropDownList != null);
305             Debug.Assert(activity != null);
306 
307             StateActivity enclosingState = StateMachineHelpers.FindEnclosingState(activity);
308             if (enclosingState == null)
309                 return;
310 
311             StateActivity rootState = StateMachineHelpers.GetRootState(enclosingState);
312 
313             FindStates(dropDownList, rootState);
314         }
315 
FindStates(ListBox dropDownList, StateActivity parent)316         private void FindStates(ListBox dropDownList, StateActivity parent)
317         {
318             foreach (Activity activity in parent.EnabledActivities)
319             {
320                 StateActivity state = activity as StateActivity;
321                 if (state != null)
322                 {
323                     if (StateMachineHelpers.IsLeafState(state))
324                     {
325                         dropDownList.Items.Add(state.QualifiedName);
326                     }
327                     else
328                     {
329                         FindStates(dropDownList, state);
330                     }
331                 }
332             }
333         }
334 
335         #endregion Private Methods
336 
337         #endregion Methods
338     }
339 
340     #endregion Class StateDropDownEditor
341 }
342