1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //----------------------------------------------------------------
5 namespace System.Activities.Presentation
7 using System.Activities.Presentation.Annotations;
8 using System.Activities.Presentation.Model;
9 using System.Activities.Presentation.View;
10 using System.Collections.Generic;
11 using System.Collections.ObjectModel;
12 using System.ComponentModel;
13 using System.Diagnostics.CodeAnalysis;
17 using System.Windows.Controls;
18 using System.Windows.Data;
19 using System.Windows.Input;
20 using System.Windows.Media;
21 using System.Windows.Threading;
23 public class ActivityDesigner : WorkflowViewElement
25 UserControl defaultDisplayNameReadOnlyControl;
26 TextBox defaultDisplayNameBox;
27 bool defaultDisplayNameReadOnlyControlMouseDown;
29 private AnnotationManager annotationManager;
31 [Fx.Tag.KnownXamlExternal]
32 public DrawingBrush Icon
34 get { return (DrawingBrush)GetValue(IconProperty); }
35 set { SetValue(IconProperty, value); }
38 public static readonly DependencyProperty IconProperty =
39 DependencyProperty.Register("Icon", typeof(DrawingBrush), typeof(ActivityDesigner), new UIPropertyMetadata(null));
41 internal static readonly DependencyProperty ActivityDelegatesProperty = DependencyProperty.Register("ActivityDelegates", typeof(ObservableCollection<ActivityDelegateInfo>), typeof(ActivityDesigner));
43 internal static readonly DependencyProperty HasActivityDelegatesProperty = DependencyProperty.Register("HasActivityDelegates", typeof(bool), typeof(ActivityDesigner));
45 [SuppressMessage(FxCop.Category.Performance, FxCop.Rule.InitializeReferenceTypeStaticFieldsInline,
46 Justification = "Calls to OverrideMetadata for a dependency property should be done in the static constructor.")]
47 static ActivityDesigner()
49 DefaultStyleKeyProperty.OverrideMetadata(typeof(ActivityDesigner), new FrameworkPropertyMetadata(typeof(ActivityDesigner)));
52 public ActivityDesigner()
54 this.Loaded += (sender, args) =>
56 this.SetupDefaultIcon();
57 this.annotationManager.Initialize();
60 this.Unloaded += (sender, args) =>
62 this.annotationManager.Uninitialize();
65 this.annotationManager = new AnnotationManager(this);
68 internal ObservableCollection<ActivityDelegateInfo> ActivityDelegates
70 get { return (ObservableCollection<ActivityDelegateInfo>)GetValue(ActivityDelegatesProperty); }
71 set { SetValue(ActivityDelegatesProperty, value); }
74 internal bool HasActivityDelegates
76 get { return (bool)GetValue(HasActivityDelegatesProperty); }
77 set { SetValue(HasActivityDelegatesProperty, value); }
80 protected override void OnModelItemChanged(object newItem)
82 base.OnModelItemChanged(newItem);
84 this.PopulateActivityDelegates((ModelItem)newItem);
87 private void PopulateActivityDelegates(ModelItem modelItem)
89 if (this.ActivityDelegates == null)
91 this.ActivityDelegates = new ObservableCollection<ActivityDelegateInfo>();
95 this.ActivityDelegates.Clear();
98 List<ActivityDelegateInfo> list = ActivityDelegateUtilities.CreateActivityDelegateInfo(modelItem);
102 foreach (ActivityDelegateInfo entry in list)
104 this.ActivityDelegates.Add(entry);
107 this.HasActivityDelegates = true;
111 this.HasActivityDelegates = false;
115 protected override string GetAutomationIdMemberName()
117 return "DisplayName";
120 protected internal override string GetAutomationItemStatus()
122 StringBuilder descriptiveText = new StringBuilder();
124 EmitPropertyValuePair(descriptiveText, "IsPrimarySelection");
125 EmitPropertyValuePair(descriptiveText, "IsSelection");
126 EmitPropertyValuePair(descriptiveText, "IsCurrentLocation");
127 EmitPropertyValuePair(descriptiveText, "IsCurrentContext");
128 EmitPropertyValuePair(descriptiveText, "IsBreakpointEnabled");
129 EmitPropertyValuePair(descriptiveText, "IsBreakpointBounded");
130 EmitPropertyValuePair(descriptiveText, "ValidationState");
131 descriptiveText.Append(base.GetAutomationItemStatus());
133 return descriptiveText.ToString();
136 void EmitPropertyValuePair(StringBuilder description, string propertyName)
138 PropertyDescriptor property = TypeDescriptor.GetProperties(this.ModelItem)[propertyName];
139 object propertyValue = (property == null) ? null : property.GetValue(this.ModelItem);
140 string propertyValueString = propertyValue == null ? "null" : propertyValue.ToString();
141 description.AppendFormat("{0}={1} ", propertyName, propertyValueString);
144 public override void OnApplyTemplate()
146 base.OnApplyTemplate();
148 if (this.defaultDisplayNameBox != null)
150 this.defaultDisplayNameBox.LostFocus -= new RoutedEventHandler(OnDefaultDisplayNameBoxLostFocus);
151 this.defaultDisplayNameBox.ContextMenuOpening -= new ContextMenuEventHandler(OnDefaultDisplayNameBoxContextMenuOpening);
153 if (this.defaultDisplayNameReadOnlyControl != null)
155 this.defaultDisplayNameReadOnlyControl.MouseLeftButtonDown -= new MouseButtonEventHandler(OnDefaultDisplayNameReadOnlyControlMouseLeftButtonDown);
156 this.defaultDisplayNameReadOnlyControl.GotKeyboardFocus -= new KeyboardFocusChangedEventHandler(OnDefaultDisplayNameReadOnlyControlGotKeyboardFocus);
159 this.defaultDisplayNameReadOnlyControl = this.Template.FindName("DisplayNameReadOnlyControl_6E8E4954_F6B2_4c6c_9E28_33A7A78F1E81", this) as UserControl;
160 this.defaultDisplayNameBox = this.Template.FindName("DisplayNameBox_570C5205_7195_4d4e_953A_8E4B57EF7E7F", this) as TextBox;
162 UIElement defaultAnnotationIndicator = this.Template.FindName("AnnotationIndicator_570C5205_7195_4d4e_953A_8E4B57EF7E7F", this) as UIElement;
163 DockedAnnotationDecorator defaultDockedAnnotationDecorator = this.Template.FindName("DockedAnnotationDecorator_570C5205_7195_4d4e_953A_8E4B57EF7E7F", this) as DockedAnnotationDecorator;
165 if (defaultAnnotationIndicator != null && defaultDockedAnnotationDecorator != null)
167 this.annotationManager.AnnotationVisualProvider = new ActivityDesignerAnnotationVisualProvider(new UIElementToAnnotationIndicatorAdapter(defaultAnnotationIndicator), defaultDockedAnnotationDecorator);
170 if (this.defaultDisplayNameBox != null && this.defaultDisplayNameReadOnlyControl != null)
172 this.defaultDisplayNameBox.LostFocus += new RoutedEventHandler(OnDefaultDisplayNameBoxLostFocus);
173 this.defaultDisplayNameBox.ContextMenuOpening += new ContextMenuEventHandler(OnDefaultDisplayNameBoxContextMenuOpening);
174 this.defaultDisplayNameReadOnlyControl.MouseLeftButtonDown += new MouseButtonEventHandler(OnDefaultDisplayNameReadOnlyControlMouseLeftButtonDown);
175 this.defaultDisplayNameReadOnlyControl.GotKeyboardFocus += new KeyboardFocusChangedEventHandler(OnDefaultDisplayNameReadOnlyControlGotKeyboardFocus);
178 Border titleBar = this.Template.FindName("TitleBar_C36A1CF2_4B36_4F0D_B427_9825C2E110DE", this) as Border;
179 if (titleBar != null)
181 this.DragHandle = titleBar;
185 void OnDefaultDisplayNameReadOnlyControlGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
187 if (this.defaultDisplayNameBox != null && this.defaultDisplayNameReadOnlyControl != null)
189 DesignerView designerView = this.Context.Services.GetService<DesignerView>();
190 if (!designerView.IsReadOnly && !designerView.IsMultipleSelectionMode)
192 this.EnterDisplayNameEditMode();
197 void OnDefaultDisplayNameReadOnlyControlMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
199 this.defaultDisplayNameReadOnlyControlMouseDown = true;
202 void OnDefaultDisplayNameBoxLostFocus(object sender, RoutedEventArgs e)
204 if (this.defaultDisplayNameBox != null && this.defaultDisplayNameReadOnlyControl != null)
206 this.ExitDisplayNameEditMode();
210 void OnDefaultDisplayNameBoxContextMenuOpening(object sender, ContextMenuEventArgs e)
212 // to disable the context menu
216 protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
218 this.defaultDisplayNameReadOnlyControlMouseDown = false;
219 base.OnPreviewMouseDown(e);
222 protected override void OnMouseUp(MouseButtonEventArgs e)
224 // We have to check the defaultDisplayNameReadOnlyControlMouseDown flag to determine whether the mouse is clicked on
225 // the defaultDisplayNameReadOnlyControl. This is because the mouse capture is set on the WorkflowViewElement in
226 // OnMouseDown, and as a result MouseUp event is not fired on the defaultDisplayNameReadOnlyControl.
227 if (this.defaultDisplayNameBox != null && this.defaultDisplayNameReadOnlyControl != null &&
228 this.defaultDisplayNameReadOnlyControlMouseDown)
230 this.defaultDisplayNameReadOnlyControlMouseDown = false;
231 DesignerView designerView = this.Context.Services.GetService<DesignerView>();
232 if (!designerView.IsReadOnly)
234 this.EnterDisplayNameEditMode();
240 void EnterDisplayNameEditMode()
242 this.defaultDisplayNameBox.Visibility = Visibility.Visible;
243 this.defaultDisplayNameReadOnlyControl.Visibility = Visibility.Collapsed;
244 this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action)(() =>
246 Keyboard.Focus(this.defaultDisplayNameBox);
247 this.defaultDisplayNameBox.ScrollToHome();
251 void ExitDisplayNameEditMode()
253 this.defaultDisplayNameReadOnlyControl.Visibility = Visibility.Visible;
254 this.defaultDisplayNameBox.Visibility = Visibility.Collapsed;
257 private void SetupDefaultIcon()
259 if (this.Icon == null)
261 this.Icon = GetDefaultIcon();
265 internal DrawingBrush GetDefaultIcon()
267 DrawingBrush icon = null;
269 // Look for a named icon if this property is not set
271 if (this.ModelItem != null)
273 string iconKey = this.ModelItem.ItemType.IsGenericType ? this.ModelItem.ItemType.GetGenericTypeDefinition().Name : this.ModelItem.ItemType.Name;
274 int genericParamsIndex = iconKey.IndexOf('`');
275 if (genericParamsIndex > 0)
277 iconKey = iconKey.Remove(genericParamsIndex);
279 iconKey = iconKey + "Icon";
282 if (WorkflowDesignerIcons.IconResourceDictionary.Contains(iconKey))
284 object resourceItem = WorkflowDesignerIcons.IconResourceDictionary[iconKey];
285 if (resourceItem is DrawingBrush)
287 icon = (DrawingBrush)resourceItem;
291 catch (ResourceReferenceKeyNotFoundException) { }
292 catch (InvalidCastException) { }
296 // as a last resort fall back to the default generic leaf activity icon.
297 icon = WorkflowDesignerIcons.Activities.DefaultCustomActivity;
303 protected internal override void OnEditAnnotation()
305 this.annotationManager.OnEditAnnotation();
308 private class ActivityDesignerAnnotationVisualProvider : IAnnotationVisualProvider
310 private DockedAnnotationDecorator decorator;
311 private IAnnotationIndicator indicator;
312 private IFloatingAnnotation floatingAnnotation;
313 private IDockedAnnotation dockedAnnotation;
315 public ActivityDesignerAnnotationVisualProvider(IAnnotationIndicator indicator, DockedAnnotationDecorator decorator)
317 this.indicator = indicator;
318 this.decorator = decorator;
321 public IAnnotationIndicator GetAnnotationIndicator()
323 return this.indicator;
326 public IFloatingAnnotation GetFloatingAnnotation()
328 if (this.floatingAnnotation == null)
330 this.floatingAnnotation = new FloatingAnnotationView();
333 return this.floatingAnnotation;
336 public IDockedAnnotation GetDockedAnnotation()
338 if (this.dockedAnnotation == null)
340 DockedAnnotationView view = new DockedAnnotationView();
342 Binding annotationTextbinding = new Binding("ModelItem.AnnotationText");
343 view.SetBinding(DockedAnnotationView.AnnotationTextProperty, annotationTextbinding);
345 Binding maxWidthBinding = new Binding("ActualWidth");
346 maxWidthBinding.ElementName = "annotationWidthSetter";
347 view.SetBinding(DockedAnnotationView.MaxWidthProperty, maxWidthBinding);
349 this.dockedAnnotation = view;
350 this.decorator.Child = view;
353 return this.dockedAnnotation;