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