1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //----------------------------------------------------------------
5 namespace System.Activities.Presentation.View
7 using System.Activities.Debugger;
8 using System.Activities.Presentation.Annotations;
9 using System.Activities.Presentation.Debug;
10 using System.Activities.Presentation.Hosting;
11 using System.Activities.Presentation.Model;
12 using System.Activities.Presentation.Services;
13 using System.Activities.Presentation.Sqm;
14 using System.Activities.Statements;
15 using System.Collections.Generic;
16 using System.ComponentModel;
17 using System.Diagnostics.CodeAnalysis;
18 using System.Globalization;
21 using System.Runtime.InteropServices;
23 using System.Windows.Controls;
24 using System.Windows.Controls.Primitives;
25 using System.Windows.Data;
26 using System.Windows.Input;
27 using System.Windows.Media.Imaging;
28 using System.Windows.Threading;
29 using Microsoft.Win32;
30 using System.Windows.Documents;
32 public partial class DesignerView
34 public const string CustomMenuItemsSeparatorCommand = "6F455692-EA19-4ac9-ABEE-57F6DF20A687";
36 public static readonly DependencyProperty CommandMenuModeProperty =
37 DependencyProperty.RegisterAttached("CommandMenuMode", typeof(CommandMenuMode), typeof(DesignerView), new UIPropertyMetadata(CommandMenuMode.FullCommandMenu));
39 static readonly DependencyProperty MenuItemOriginProperty =
40 DependencyProperty.RegisterAttached("MenuItemOrigin", typeof(FrameworkElement), typeof(DesignerView));
42 public static readonly DependencyProperty MenuItemStyleProperty =
43 DependencyProperty.Register("MenuItemStyle", typeof(Style), typeof(DesignerView), new UIPropertyMetadata(null));
45 public static readonly DependencyProperty MenuSeparatorStyleProperty =
46 DependencyProperty.Register("MenuSeparatorStyle", typeof(Style), typeof(DesignerView), new UIPropertyMetadata(null));
48 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes,
49 Justification = "The class RoutedCommand just has readonly properties, hence the referencetype instance cannot be modified")]
50 public static readonly ICommand GoToParentCommand = new RoutedCommand("GoToParentCommand", typeof(DesignerView));
51 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
52 public static readonly ICommand ExpandCommand = new RoutedCommand("ExpandCommand", typeof(DesignerView));
53 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
54 public static readonly ICommand ExpandAllCommand = new RoutedCommand("ExpandAllCommand", typeof(DesignerView));
55 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
56 public static readonly ICommand CollapseCommand = new RoutedCommand("CollapseCommand", typeof(DesignerView));
57 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
58 public static readonly ICommand CollapseAllCommand = new RoutedCommand("CollapseAllCommand", typeof(DesignerView));
59 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
60 public static readonly ICommand RestoreCommand = new RoutedCommand("RestoreCommand", typeof(DesignerView));
61 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
62 public static readonly ICommand ExpandInPlaceCommand = new RoutedCommand("ExpandInPlaceCommand", typeof(DesignerView));
63 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
64 public static readonly ICommand InsertBreakpointCommand = new RoutedCommand("InsertBreakpointCommand", typeof(DesignerView));
65 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
66 public static readonly ICommand DeleteBreakpointCommand = new RoutedCommand("DeleteBreakpointParentCommand", typeof(DesignerView));
67 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
68 public static readonly ICommand EnableBreakpointCommand = new RoutedCommand("EnableBreakpointCommand", typeof(DesignerView));
69 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
70 public static readonly ICommand DisableBreakpointCommand = new RoutedCommand("DisableBreakpointCommand", typeof(DesignerView));
71 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
72 public static readonly ICommand SaveAsImageCommand = new RoutedCommand("SaveAsImageCommand", typeof(DesignerView));
73 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
74 public static readonly ICommand CopyAsImageCommand = new RoutedCommand("CopyAsImageCommand", typeof(DesignerView));
75 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
76 public static readonly ICommand ZoomInCommand = new RoutedCommand("ZoomInCommand", typeof(DesignerView));
77 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
78 public static readonly ICommand ZoomOutCommand = new RoutedCommand("ZoomOutCommand", typeof(DesignerView));
79 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
80 public static readonly ICommand ToggleArgumentDesignerCommand = new RoutedCommand("ToggleArgumentDesignerCommand", typeof(DesignerView));
81 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
82 public static readonly ICommand ToggleImportsDesignerCommand = new RoutedCommand("ToggleImportsDesignerCommand", typeof(DesignerView));
83 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
84 public static readonly ICommand ToggleVariableDesignerCommand = new RoutedCommand("ToggleVariableDesignerCommand", typeof(DesignerView));
85 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
86 public static readonly ICommand CreateVariableCommand = new RoutedCommand("CreateVariableCommand", typeof(DesignerView));
87 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
88 public static readonly ICommand ToggleMiniMapCommand = new RoutedCommand("ToggleMinimapCommand", typeof(DesignerView));
89 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
90 public static readonly ICommand CycleThroughDesignerCommand = new RoutedCommand("CycleThroughDesignerCommand", typeof(DesignerView));
91 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
92 public static readonly ICommand CreateWorkflowElementCommand = new RoutedCommand("CreateWorkflowElementCommand", typeof(DesignerView));
93 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
94 public static readonly ICommand CreateArgumentCommand = new RoutedCommand("CreateArgumentCommand", typeof(DesignerView));
95 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
96 public static readonly ICommand CommitCommand = new RoutedCommand("CommitCommand", typeof(DesignerView));
97 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
98 public static readonly ICommand FitToScreenCommand = new RoutedCommand("FitToScreenCommand", typeof(DesignerView));
99 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
100 public static readonly ICommand ResetZoomCommand = new RoutedCommand("ResetZoomCommand", typeof(DesignerView));
101 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
102 public static readonly ICommand MoveFocusCommand = new RoutedCommand("MoveFocusCommand", typeof(DesignerView));
103 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
104 public static readonly ICommand ToggleSelectionCommand = new RoutedCommand("ToggleSelectionCommand", typeof(DesignerView));
105 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
106 public static readonly ICommand CutCommand = new RoutedCommand("CutCommand", typeof(DesignerView));
107 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
108 public static readonly ICommand CopyCommand = new RoutedCommand("CopyCommand", typeof(DesignerView));
109 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
110 public static readonly ICommand PasteCommand = new RoutedCommand("PasteCommand", typeof(DesignerView));
111 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
112 public static readonly ICommand SelectAllCommand = new RoutedCommand("SelectAllCommand", typeof(DesignerView));
113 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
114 public static readonly ICommand UndoCommand = new RoutedCommand("UndoCommand", typeof(DesignerView));
115 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
116 public static readonly ICommand RedoCommand = new RoutedCommand("RedoCommand", typeof(DesignerView));
117 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
118 public static readonly ICommand AddAnnotationCommand = new RoutedCommand("AddAnnotationCommand", typeof(DesignerView));
119 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
120 public static readonly ICommand EditAnnotationCommand = new RoutedCommand("EditAnnotationCommand", typeof(DesignerView));
121 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
122 public static readonly ICommand DeleteAnnotationCommand = new RoutedCommand("DeleteAnnotationCommand", typeof(DesignerView));
123 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
124 public static readonly ICommand ShowAllAnnotationCommand = new RoutedCommand("ShowAllAnnotationCommand", typeof(DesignerView));
125 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
126 public static readonly ICommand HideAllAnnotationCommand = new RoutedCommand("HideAllAnnotationCommand", typeof(DesignerView));
127 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
128 public static readonly ICommand DeleteAllAnnotationCommand = new RoutedCommand("DeleteAllAnnotationCommand", typeof(DesignerView));
130 WorkflowViewElement contextMenuTarget;
131 HashSet<CommandBinding> ignoreCommands = new HashSet<CommandBinding>();
133 Func<WorkflowViewElement, bool, Visibility> navigateToParentFunction;
134 Func<WorkflowViewElement, bool, Visibility> navigateToChildFunction;
135 Func<WorkflowViewElement, BreakpointTypes> getBreakpointType;
136 Func<bool> isCommandServiceEnabled;
137 Func<bool> areBreakpointServicesEnabled;
138 Func<int, bool> isCommandSupported;
140 bool ContainsChordKeyGestures(InputGestureCollection collection)
142 if (collection == null)
148 foreach (KeyGesture gesture in collection)
150 if (gesture.GetType() == typeof(DefaultCommandExtensionCallback.ChordKeyGesture))
159 // Set chordkey gestures owner to this class, so that the chordkey can clear other chord key's mode
161 void SetChordKeyGesturesOwner()
163 foreach (CommandBinding binding in this.CommandBindings)
165 RoutedCommand cmd = binding.Command as RoutedCommand;
166 foreach (KeyGesture gesture in cmd.InputGestures)
168 if (gesture.GetType() == typeof(DefaultCommandExtensionCallback.ChordKeyGesture))
170 ((DefaultCommandExtensionCallback.ChordKeyGesture)gesture).Owner = this;
176 // Let the chord command in front, so that the chord command (e.g. Ctrl+E,Ctrl+V) will match
177 // before the (e.g. Ctrl+V).
178 void ReorderCommandBindings()
180 CommandBindingCollection chordCommandBindings = new CommandBindingCollection();
181 CommandBindingCollection basicCommandBindings = new CommandBindingCollection();
182 foreach (CommandBinding binding in this.CommandBindings)
184 RoutedCommand cmd = binding.Command as RoutedCommand;
185 if (ContainsChordKeyGestures(cmd.InputGestures))
187 chordCommandBindings.Add(binding);
191 basicCommandBindings.Add(binding);
194 this.CommandBindings.Clear();
195 this.CommandBindings.AddRange(chordCommandBindings);
196 this.CommandBindings.AddRange(basicCommandBindings);
199 internal void ResetAllChordKeyGesturesMode()
201 foreach (CommandBinding binding in this.CommandBindings)
203 RoutedCommand cmd = binding.Command as RoutedCommand;
204 foreach (KeyGesture gesture in cmd.InputGestures)
206 if (gesture.GetType() == typeof(DefaultCommandExtensionCallback.ChordKeyGesture))
208 ((DefaultCommandExtensionCallback.ChordKeyGesture)gesture).ResetChordMode();
214 void InitializeMenuActions()
216 this.isCommandServiceEnabled = () =>
218 return null != this.Context.Services.GetService<ICommandService>();
221 this.areBreakpointServicesEnabled = () =>
223 return null != this.Context.Services.GetService<IDesignerDebugView>() && this.isCommandServiceEnabled();
226 this.isCommandSupported = commandId =>
228 return this.Context.Services.GetService<ICommandService>().IsCommandSupported(commandId);
232 this.navigateToParentFunction = (selection, shouldExecute) =>
235 ModelItem target = null;
236 if (null != selection && selection.Equals(this.RootDesigner))
238 if (null != selection.ModelItem.Parent)
240 WorkflowViewService viewService = (WorkflowViewService)this.Context.Services.GetService<ViewService>();
241 target = selection.ModelItem;
244 target = target.Parent;
250 while (!viewService.ShouldAppearOnBreadCrumb(target, true));
251 result = (null != target);
254 if (shouldExecute && result)
256 this.MakeRootDesigner(target);
258 return result ? Visibility.Visible : Visibility.Collapsed;
261 this.navigateToChildFunction = (selection, shouldExecute) =>
264 ModelItem target = null;
265 if (null != selection && !selection.Equals(this.RootDesigner))
267 target = selection.ModelItem;
268 WorkflowViewService viewService = (WorkflowViewService)this.Context.Services.GetService<ViewService>();
269 result = viewService.ShouldAppearOnBreadCrumb(target, true);
271 if (shouldExecute && result)
273 this.MakeRootDesigner(target);
275 return result ? Visibility.Visible : Visibility.Collapsed;
278 this.getBreakpointType = selection =>
280 IDesignerDebugView debugView = this.Context.Services.GetService<IDesignerDebugView>();
281 var breakpoints = debugView.GetBreakpointLocations();
282 BreakpointTypes result = BreakpointTypes.None;
283 if (null != breakpoints && null != debugView.SelectedLocation)
285 breakpoints.TryGetValue(debugView.SelectedLocation, out result);
289 this.ContextMenu.ClipToBounds = false;
291 //workflow command extension callback invoker
292 Action<WorkflowCommandExtensionItem> updateCommands = (item) =>
294 //if there are any commands which were ignored - add them back to bindings collections
295 foreach (CommandBinding binding in this.ignoreCommands)
297 this.CommandBindings.Add(binding);
299 this.ignoreCommands.Clear();
301 if (null != item.CommandExtensionCallback)
303 foreach (CommandBinding cb in this.CommandBindings)
305 //if callback returns false, it means that user will handle the command, add it to ingore list
306 CommandInfo ci = new CommandInfo(cb.Command);
307 item.CommandExtensionCallback.OnWorkflowCommandLoaded(ci);
308 if (!ci.IsBindingEnabledInDesigner)
310 this.ignoreCommands.Add(cb);
314 //remove all commands from ignore list from bindings - let the commands bubble up to the client
315 foreach (CommandBinding cb in this.ignoreCommands)
317 this.CommandBindings.Remove(cb);
320 if (null != this.ContextMenu && this.ContextMenu.HasItems)
322 foreach (MenuItem menuItem in this.ContextMenu.Items.OfType<MenuItem>())
324 this.RefreshContextMenu(menuItem);
328 if (item.CommandExtensionCallback.GetType() == typeof(DefaultCommandExtensionCallback))
330 this.ReorderCommandBindings();
331 this.SetChordKeyGesturesOwner();
335 //subscribe for command extension callback changes;
336 this.context.Items.Subscribe<WorkflowCommandExtensionItem>(new SubscribeContextCallback<WorkflowCommandExtensionItem>(updateCommands));
337 //if entry already exists - invoke update; if entry doesn't exist - do nothing. perhaps it will be added later by the user
338 if (this.context.Items.Contains<WorkflowCommandExtensionItem>())
340 updateCommands(this.context.Items.GetValue<WorkflowCommandExtensionItem>());
344 public Style MenuItemStyle
346 get { return (Style)GetValue(MenuItemStyleProperty); }
347 set { SetValue(MenuItemStyleProperty, value); }
350 public Style MenuSeparatorStyle
352 get { return (Style)GetValue(MenuSeparatorStyleProperty); }
353 set { SetValue(MenuSeparatorStyleProperty, value); }
356 void RefreshContextMenu(MenuItem menuItem)
358 if (null != menuItem.Command)
360 //update MenuItem's Command property - if user did update any keyboard shortcuts, then it would be reflected by that change
361 ICommand cmd = menuItem.Command;
362 menuItem.Command = null;
363 menuItem.Command = cmd;
365 if (menuItem.HasItems)
367 foreach (MenuItem subItem in menuItem.Items.OfType<MenuItem>())
369 this.RefreshContextMenu(subItem);
374 protected override void OnContextMenuOpening(ContextMenuEventArgs e)
376 bool shouldDisplayMenu = false;
377 DependencyObject target = null;
378 DependencyObject source = e.OriginalSource as DependencyObject;
379 if (source is Adorner)
381 source = ((Adorner)source).AdornedElement;
384 DependencyObject designerPresenterSource = this.designerPresenter.FindCommonVisualAncestor(source);
385 DependencyObject extensionSurfaceSource = this.wfViewExtensionSurface.FindCommonVisualAncestor(source);
387 //check, who is trying to open context menu - i limit context menu to only elements which are visible inside
388 //core of the workflow designer - no breadcrumb or toolbox
389 if (designerPresenterSource == this.designerPresenter || extensionSurfaceSource == this.wfViewExtensionSurface)
391 Selection currentSelection = this.Context.Items.GetValue<Selection>();
392 if (null != currentSelection && currentSelection.SelectionCount >= 1)
394 if (currentSelection.SelectionCount == 1) // single selection
396 //check original source, to see if it prevents displaying context menu
397 if (!CommandMenuMode.Equals(CommandMenuMode.NoCommandMenu, GetCommandMenuMode((DependencyObject)e.OriginalSource)))
399 if (null != currentSelection.PrimarySelection.View)
401 target = currentSelection.PrimarySelection.View;
402 shouldDisplayMenu = true;
406 else // multi-selection
408 // If Multi-selection's context menu was not enabled, don't display menu.
409 shouldDisplayMenu = Context.Services.GetService<DesignerConfigurationService>().MultipleItemsContextMenuEnabled;
414 base.OnContextMenuOpening(e);
416 if (shouldDisplayMenu)
418 // if the context menu is triggered by a context menu key, open context menu at the center of the designer;
419 // else open the context menu at mouse point
420 this.LoadContextMenu((UIElement)target, (e.CursorLeft < 0 && e.CursorTop < 0));
424 void LoadContextMenu(UIElement sender, bool openedByKeyboard)
426 if (this.ContextMenu == null)
431 if (!Selection.MultipleObjectsSelected(this.Context) && sender != null && CommandMenuMode.Equals(CommandMenuMode.NoCommandMenu, GetCommandMenuMode(sender)))
436 //clear context menu state
437 this.UnloadContextMenu(this.ContextMenu);
439 this.contextMenuTarget = sender as WorkflowViewElement;
441 //because of WPF caching behaviour, i have to create new instance of context menu each time it is shown
442 ContextMenu newMenu = new ContextMenu() { ItemContainerStyleSelector = new ContextMenuItemStyleSelector(this) };
443 newMenu.Loaded += this.OnWorkflowViewContextMenuLoaded;
444 newMenu.Unloaded += this.OnWorkflowViewContextMenuClosed;
445 foreach (var entry in this.ContextMenu.Items.OfType<Control>().Reverse())
447 this.ContextMenu.Items.Remove(entry);
448 entry.Visibility = Visibility.Visible;
449 newMenu.Items.Insert(0, entry);
451 this.ContextMenu = newMenu;
453 if (!Selection.MultipleObjectsSelected(this.Context))
455 if (null != this.contextMenuTarget && null != this.contextMenuTarget.ContextMenu)
457 var items = this.contextMenuTarget.ContextMenu.Items.OfType<Control>().Reverse();
458 int insertIndex = this.ContextMenu.Items.Count;
460 foreach (var item in items)
462 this.contextMenuTarget.ContextMenu.Items.Remove(item);
463 DesignerView.SetMenuItemOrigin(item, this.contextMenuTarget);
464 this.ContextMenu.Items.Insert(insertIndex, item);
468 Fx.Assert(this.contextMenuTarget.IsVisible, string.Format(CultureInfo.InvariantCulture, "ContextMenuTarget {0} is not visible", this.contextMenuTarget.GetType()));
469 this.ContextMenu.Placement = openedByKeyboard ? PlacementMode.Relative : PlacementMode.MousePoint;
470 this.ContextMenu.PlacementTarget = this.contextMenuTarget;
474 this.ContextMenu.Placement = openedByKeyboard ? PlacementMode.Center : PlacementMode.MousePoint;
475 this.ContextMenu.PlacementTarget = this;
478 this.ContextMenu.IsOpen = true;
481 void UnloadContextMenu(ContextMenu contextMenuToUnload)
483 if (null != contextMenuToUnload && null != this.contextMenuTarget)
485 // this should happen only for single selection
486 //select all menu items which do not belong to DesignerView
487 var items = contextMenuToUnload.Items.OfType<Control>()
488 .Where(p => DesignerView.GetMenuItemOrigin(p) != null)
491 foreach (Control item in items)
493 //remove item from designer menu's location
494 contextMenuToUnload.Items.Remove(item);
496 //and add it back to activity designer
497 DesignerView.GetMenuItemOrigin(item).ContextMenu.Items.Insert(0, item);
498 DesignerView.SetMenuItemOrigin(item, null);
500 this.contextMenuTarget = null;
501 contextMenuToUnload.Loaded -= this.OnWorkflowViewContextMenuLoaded;
502 contextMenuToUnload.Unloaded -= this.OnWorkflowViewContextMenuClosed;
506 void OnWorkflowViewContextMenuLoaded(object sender, RoutedEventArgs e)
508 this.ContextMenu.MinWidth = 0;
509 this.ContextMenu.MinWidth = this.ContextMenu.DesiredSize.Width;
511 Action<WorkflowViewElement, FrameworkElement> contextMenuLoaded =
512 (designer, menuSource) =>
514 System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} DesignerView.OnWorkflowViewContextMenuLoaded()", DateTime.Now.ToLocalTime()));
515 if (null != menuSource && null != menuSource.ContextMenu)
517 if (null != designer) // for single selection, designer is the current selected item, we set CommandTarget to current selection
519 foreach (var item in menuSource.ContextMenu.Items.OfType<MenuItem>())
521 item.CommandTarget = designer;
523 designer.NotifyContextMenuLoaded(menuSource.ContextMenu);
525 else // for multiple selection, designer is null, we set the CommandTarget to DesignerView
527 foreach (var item in menuSource.ContextMenu.Items.OfType<MenuItem>())
529 item.CommandTarget = this;
534 //if context menu is loaded, deffer notification untill its all menu items have been loaded
535 this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, contextMenuLoaded, this.contextMenuTarget, this);
538 void OnWorkflowViewContextMenuClosed(object sender, RoutedEventArgs e)
540 this.UnloadContextMenu((ContextMenu)sender);
543 void OnMenuItemSeparatorLoaded(object sender, RoutedEventArgs e)
545 //define a delegate which will handle separator load events
546 Action<Separator> action = (separator) =>
548 if (null != separator && null != separator.Tag && null != this.ContextMenu)
550 //check the separator tags - it should contain command names in a tag property
551 string[] commands = separator.Tag.ToString().Split(';');
552 //check if this separator has a special tag value - CustomMenuItemsSeparatorCommand
553 //it means, it has to be displayed only, when there are custom menu items added to the menu
554 if (commands.Length == 1 && string.Equals(CustomMenuItemsSeparatorCommand, commands[0]))
556 // The CustomMenuItemsSeparator should be visible only if it has visible child.
557 int index = this.ContextMenu.Items.IndexOf(separator);
558 bool visible = false;
559 for (int i = index + 1; i < this.ContextMenu.Items.Count && !visible; i++)
561 object contextMenuItem = this.ContextMenu.Items[i];
562 if (contextMenuItem is MenuItem)
564 visible = ((MenuItem)contextMenuItem).Visibility == Visibility.Visible;
568 // For safety sake, someone might put other things into the ContextMenu.Items other than MenuItem.
572 separator.Visibility = visible ? Visibility.Visible : Visibility.Collapsed;
574 else if (commands.Length != 0)
576 //set this separator visibility, if associated menu items have either a name or command.name property set to a passed
577 //value, and at least one of the menu item is visible
578 separator.Visibility = this.ContextMenu.Items
580 .Where(item => commands.Any(
581 cmd => string.Equals(cmd, null != item.Command && item.Command is RoutedCommand ? ((RoutedCommand)item.Command).Name : item.Name)))
582 .Any(item => item.Visibility == Visibility.Visible) ? Visibility.Visible : Visibility.Collapsed;
586 //postpone separator show/hide logic until all menu items are loaded and their visibility is calculated
587 this.Dispatcher.BeginInvoke(DispatcherPriority.DataBind, action, sender);
590 void OnGoToParentMenuLoaded(object sender, RoutedEventArgs e)
592 MenuItem item = sender as MenuItem;
595 if (Selection.MultipleObjectsSelected(this.Context))
597 item.Visibility = Visibility.Collapsed;
601 item.Visibility = this.navigateToParentFunction(this.contextMenuTarget, false);
606 void OnGoToParentCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
612 void OnGoToParentCommandExecute(object sender, ExecutedRoutedEventArgs e)
614 this.navigateToParentFunction(this.contextMenuTarget ?? this.FocusedViewElement, true);
616 FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.ViewParent);
619 void OnCollapseCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
621 if (this.FocusedViewElement != null)
623 e.CanExecute = this.FocusedViewElement.ShowExpanded;
628 void OnCollapseCommandExecute(object sender, ExecutedRoutedEventArgs e)
630 this.FocusedViewElement.ExpandState = false;
631 if (this.ShouldExpandAll)
633 this.FocusedViewElement.PinState = true;
638 void OnCollapseAllCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
640 e.CanExecute = !this.ShouldCollapseAll;
644 void OnCollapseAllCommandExecute(object sender, ExecutedRoutedEventArgs e)
646 this.ShouldCollapseAll = true;
648 FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.CollapseAll);
651 void OnRestoreCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
653 e.CanExecute = this.ShouldExpandAll || this.ShouldCollapseAll;
657 void OnRestoreCommandExecute(object sender, ExecutedRoutedEventArgs e)
659 this.ShouldExpandAll = false;
660 this.ShouldCollapseAll = false;
662 FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.Restore);
665 void OnExpandAllCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
667 e.CanExecute = !this.ShouldExpandAll;
671 void OnExpandAllCommandExecute(object sender, ExecutedRoutedEventArgs e)
673 this.ShouldExpandAll = true;
675 FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.ExpandAll);
678 void OnCollapseExpandInPlaceMenuLoaded(object sender, RoutedEventArgs e)
680 MenuItem item = sender as MenuItem;
683 if (Selection.MultipleObjectsSelected(this.Context))
685 item.Visibility = Visibility.Collapsed;
689 item.Visibility = ExpandButtonVisibilityConverter.GetExpandCollapseButtonVisibility(this.contextMenuTarget);
694 void OnExpandInPlaceCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
696 if (this.FocusedViewElement != null)
698 e.CanExecute = !this.FocusedViewElement.ShowExpanded;
703 void OnExpandInPlaceCommandExecute(object sender, ExecutedRoutedEventArgs e)
705 this.FocusedViewElement.ExpandState = true;
706 if (this.ShouldCollapseAll)
708 this.FocusedViewElement.PinState = true;
713 void OnExpandMenuLoaded(object sender, RoutedEventArgs e)
715 MenuItem item = sender as MenuItem;
718 if (Selection.MultipleObjectsSelected(this.Context))
720 item.Visibility = Visibility.Collapsed;
724 item.Visibility = this.navigateToChildFunction(this.contextMenuTarget, false);
729 void OnExpandCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
735 void OnExpandCommandExecute(object sender, ExecutedRoutedEventArgs e)
737 this.navigateToChildFunction(this.contextMenuTarget ?? this.FocusedViewElement, true);
739 FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.OpenChild);
742 void OnCopyCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
744 e.CanExecute = !this.IsReadOnly && CutCopyPasteHelper.CanCopy(this.Context);
745 e.ContinueRouting = false;
749 void OnCopyCommandExecute(object sender, ExecutedRoutedEventArgs e)
751 this.Context.Services.GetService<DesignerPerfEventProvider>().WorkflowDesignerCopyStart();
752 CutCopyPasteHelper.DoCopy(this.Context);
754 this.Context.Services.GetService<DesignerPerfEventProvider>().WorkflowDesignerCopyEnd();
757 void OnPasteCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
759 e.CanExecute = !this.IsReadOnly && CutCopyPasteHelper.CanPaste(this.Context);
760 e.ContinueRouting = false;
764 void OnPasteCommandExecute(object sender, ExecutedRoutedEventArgs e)
766 context.Services.GetService<DesignerPerfEventProvider>().WorkflowDesignerPasteStart();
767 WorkflowViewElement sourceElement = e.OriginalSource as WorkflowViewElement;
768 if (sourceElement != null)
770 Point contextMenuTopLeft = this.ContextMenu.TranslatePoint(new Point(0, 0), sourceElement);
771 CutCopyPasteHelper.DoPaste(this.Context, contextMenuTopLeft, sourceElement);
775 CutCopyPasteHelper.DoPaste(this.Context);
778 context.Services.GetService<DesignerPerfEventProvider>().WorkflowDesignerPasteEnd();
781 void OnCutCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
783 //handle CutCommand only if Cut reffers to WF designer context menu, otherwise - let target element handle it
784 e.CanExecute = !this.IsReadOnly && CutCopyPasteHelper.CanCut(this.Context);
785 e.ContinueRouting = false;
789 void OnCutCommandExecute(object sender, ExecutedRoutedEventArgs e)
791 CutCopyPasteHelper.DoCut(this.Context);
795 void OnDeleteCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
797 //query DeleteHelper if delete can occur - i.e. there is no root element selected
798 e.CanExecute = !this.IsReadOnly && DeleteHelper.CanDelete(this.Context);
799 e.ContinueRouting = false;
803 void OnDeleteCommandExecute(object sender, ExecutedRoutedEventArgs e)
805 DeleteHelper.Delete(this.Context);
809 void OnPropertiesMenuLoaded(object sender, RoutedEventArgs e)
811 MenuItem item = sender as MenuItem;
814 item.Visibility = this.isCommandServiceEnabled() && this.isCommandSupported(CommandValues.ShowProperties) ?
815 Visibility.Visible : Visibility.Collapsed;
820 void OnShowPropertiesCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
826 void OnShowPropertiesCommandExecute(object sender, ExecutedRoutedEventArgs e)
828 //execute ShowProperties command
829 ExecuteCommand(CommandValues.ShowProperties);
833 void OnBreakpointMenuLoaded(object sender, RoutedEventArgs e)
835 MenuItem item = sender as MenuItem;
838 if (Selection.MultipleObjectsSelected(this.Context))
840 item.Visibility = Visibility.Collapsed;
845 this.areBreakpointServicesEnabled() && (this.contextMenuTarget is ActivityDesigner) ?
846 Visibility.Visible : Visibility.Collapsed;
851 void OnInsertBreakpointMenuLoaded(object sender, RoutedEventArgs e)
853 MenuItem item = sender as MenuItem;
857 this.areBreakpointServicesEnabled() &&
858 this.isCommandSupported(CommandValues.InsertBreakpoint) &&
859 this.getBreakpointType(this.FocusedViewElement) == BreakpointTypes.None ?
860 Visibility.Visible : Visibility.Collapsed;
865 void OnInsertBreakpointCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
867 e.CanExecute = this.FocusedViewElement != null && this.FocusedViewElement.ModelItem != null &&
868 AllowBreakpointAttribute.IsBreakpointAllowed(this.FocusedViewElement.ModelItem.ItemType);
872 void OnInsertBreakpointCommandExecute(object sender, ExecutedRoutedEventArgs e)
874 ExecuteCommand(CommandValues.InsertBreakpoint);
878 void OnDeleteBreakpointMenuLoaded(object sender, RoutedEventArgs e)
880 MenuItem item = sender as MenuItem;
884 this.areBreakpointServicesEnabled() &&
885 this.isCommandSupported(CommandValues.DeleteBreakpoint) &&
886 this.getBreakpointType(this.FocusedViewElement) != BreakpointTypes.None ?
887 Visibility.Visible : Visibility.Collapsed;
892 void OnDeleteBreakpointCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
894 e.CanExecute = this.FocusedViewElement != null && this.FocusedViewElement.ModelItem != null &&
895 AllowBreakpointAttribute.IsBreakpointAllowed(this.FocusedViewElement.ModelItem.ItemType);
899 void OnDeleteBreakpointCommandExecute(object sender, ExecutedRoutedEventArgs e)
901 ExecuteCommand(CommandValues.DeleteBreakpoint);
905 void OnEnableBreakpointMenuLoaded(object sender, RoutedEventArgs e)
907 MenuItem item = sender as MenuItem;
910 Visibility visibility = Visibility.Collapsed;
911 if (this.areBreakpointServicesEnabled() && this.isCommandSupported(CommandValues.EnableBreakpoint))
913 BreakpointTypes breakpoint = this.getBreakpointType(this.FocusedViewElement);
914 visibility = ((breakpoint & BreakpointTypes.Bounded) != 0 && (breakpoint & BreakpointTypes.Enabled) == 0) ?
915 Visibility.Visible : Visibility.Collapsed;
917 item.Visibility = visibility;
922 void OnEnableBreakpointCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
928 void OnEnableBreakpointCommandExecute(object sender, ExecutedRoutedEventArgs e)
930 ExecuteCommand(CommandValues.EnableBreakpoint);
934 void OnDisableBreakpointMenuLoaded(object sender, RoutedEventArgs e)
936 MenuItem item = sender as MenuItem;
939 Visibility visibility = Visibility.Collapsed;
940 if (this.areBreakpointServicesEnabled() && this.isCommandSupported(CommandValues.DisableBreakpoint))
942 BreakpointTypes breakpoint = this.getBreakpointType(this.FocusedViewElement);
943 visibility = ((breakpoint & BreakpointTypes.Bounded) != 0 && (breakpoint & BreakpointTypes.Enabled) != 0) ?
944 Visibility.Visible : Visibility.Collapsed;
946 item.Visibility = visibility;
952 void OnDisableBreakpointCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
958 void OnDisableBreakpointCommandExecute(object sender, ExecutedRoutedEventArgs e)
960 ExecuteCommand(CommandValues.DisableBreakpoint);
964 void OnUndoCommandExecute(object sender, ExecutedRoutedEventArgs e)
966 this.Context.Services.GetService<UndoEngine>().Undo();
970 void OnUndoCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
976 void OnRedoCommandExecute(object sender, ExecutedRoutedEventArgs e)
978 this.Context.Services.GetService<UndoEngine>().Redo();
982 void OnRedoCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
988 void OnCommitCommandExecute(object sender, ExecutedRoutedEventArgs e)
990 TextBox textBox = e.OriginalSource as TextBox;
993 BindingExpression textBinding = textBox.GetBindingExpression(TextBox.TextProperty);
994 if (textBinding != null)
996 textBinding.UpdateSource();
1002 void OnCommitCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1004 e.CanExecute = true;
1008 void OnSelectAllCommandExecute(object sender, ExecutedRoutedEventArgs e)
1014 void OnCopyAsImageMenuLoaded(object sender, RoutedEventArgs e)
1016 MenuItem item = sender as MenuItem;
1019 if (Selection.MultipleObjectsSelected(this.Context))
1021 item.Visibility = Visibility.Collapsed;
1025 item.Visibility = Visibility.Visible;
1031 void OnCopyAsImageCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1033 e.CanExecute = null != this.RootDesigner;
1037 void OnCopyAsImageCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1039 VirtualizedContainerService virtualizingContainerService = this.Context.Services.GetService<VirtualizedContainerService>();
1040 virtualizingContainerService.BeginPopulateAll((Action)(() =>
1042 BitmapSource screenShot = this.CreateScreenShot();
1045 RetriableClipboard.SetImage(screenShot);
1047 catch (COMException err)
1049 ErrorReporting.ShowErrorMessage(err.Message);
1052 FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.CopyAsImage);
1056 void OnSaveAsImageMenuLoaded(object sender, RoutedEventArgs e)
1058 MenuItem item = sender as MenuItem;
1061 if (Selection.MultipleObjectsSelected(this.Context))
1063 item.Visibility = Visibility.Collapsed;
1067 item.Visibility = Visibility.Visible;
1073 void OnSaveAsImageCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1075 e.CanExecute = null != this.RootDesigner;
1079 [SuppressMessage(FxCop.Category.Design, FxCop.Rule.DoNotCatchGeneralExceptionTypes,
1080 Justification = "Catching all exceptions to avoid VS Crash")]
1081 [SuppressMessage("Reliability", "Reliability108", Justification = "Catching all exceptions to avoid VS Crash")]
1082 void OnSaveAsImageCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1085 ModelItem rootItem = ((WorkflowViewElement)this.RootDesigner).ModelItem;
1086 PropertyDescriptor displayNameProperty = TypeDescriptor.GetProperties(rootItem)["DisplayName"];
1087 // default to root item's typename
1088 string name = rootItem.ItemType.Name;
1089 // if there is a display name property on root use that as the file name.
1090 if (displayNameProperty != null && displayNameProperty.PropertyType.Equals(typeof(string)))
1092 name = (string)displayNameProperty.GetValue(rootItem);
1094 SaveFileDialog dlg = new SaveFileDialog()
1096 Filter = @"JPG|*.jpg|PNG|*.png|GIF|*.gif|XPS|*.xps",
1099 bool? showDialogResult = false;
1102 showDialogResult = dlg.ShowDialog();
1104 catch (ArgumentException)
1106 dlg.FileName = null;
1107 showDialogResult = dlg.ShowDialog();
1109 if (true == showDialogResult && !string.IsNullOrEmpty(dlg.FileName))
1111 VirtualizedContainerService virtualizingContainerService = this.Context.Services.GetService<VirtualizedContainerService>();
1112 virtualizingContainerService.BeginPopulateAll((Action)(() =>
1116 switch (dlg.FilterIndex)
1119 this.CreateImageFile(dlg.FileName, typeof(JpegBitmapEncoder));
1123 this.CreateImageFile(dlg.FileName, typeof(PngBitmapEncoder));
1127 this.CreateImageFile(dlg.FileName, typeof(GifBitmapEncoder));
1131 this.CreateXPSDocument(dlg.FileName);
1135 throw FxTrace.Exception.AsError(new InvalidOperationException("Not supported file type"));
1138 catch (Exception err)
1140 MessageBox.Show(err.Message, err.GetType().Name, MessageBoxButton.OK, MessageBoxImage.Error);
1145 FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.SaveAsImage);
1148 void OnZoomInCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1150 e.CanExecute = this.zoomToTicksConverter.CanZoomIn();
1154 void OnZoomInCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1156 this.zoomToTicksConverter.ZoomIn();
1160 void OnMoveFocusCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1162 e.CanExecute = true;
1165 void OnMoveFocusCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1167 UIElement focusedElement = Keyboard.FocusedElement as UIElement;
1168 if (focusedElement != null)
1170 this.IsMultipleSelectionMode = true;
1171 focusedElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
1172 this.IsMultipleSelectionMode = false;
1177 void OnToggleSelectionCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1179 e.CanExecute = true;
1182 void OnToggleSelectionCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1184 WorkflowViewElement focusedElement = Keyboard.FocusedElement as WorkflowViewElement;
1185 if (focusedElement != null && focusedElement.ModelItem != null)
1187 Selection.Toggle(this.Context, focusedElement.ModelItem);
1192 void OnZoomOutCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1194 e.CanExecute = this.zoomToTicksConverter.CanZoomOut();
1198 void OnZoomOutCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1200 this.zoomToTicksConverter.ZoomOut();
1204 void OnToggleArgumentDesignerCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1207 ((this.shellBarItemVisibility & ShellBarItemVisibility.Arguments) == ShellBarItemVisibility.Arguments) &&
1208 null != this.ActivitySchema &&
1209 typeof(ActivityBuilder).IsAssignableFrom(this.ActivitySchema.ItemType);
1214 void OnToggleArgumentDesignerCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1216 this.buttonArguments1.IsChecked = !this.buttonArguments1.IsChecked;
1217 this.FocusShellBarDesigner(this.arguments1);
1221 void OnToggleVariableDesignerCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1223 e.CanExecute = ((this.shellBarItemVisibility & ShellBarItemVisibility.Variables) == ShellBarItemVisibility.Variables);
1227 void OnToggleVariableDesignerCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1229 this.buttonVariables1.IsChecked = !this.buttonVariables1.IsChecked;
1230 this.FocusShellBarDesigner(this.variables1);
1234 void OnToggleImportsDesignerCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1236 if ((this.shellBarItemVisibility & ShellBarItemVisibility.Imports) == ShellBarItemVisibility.Imports)
1238 e.CanExecute = true;
1242 e.CanExecute = false;
1247 void OnToggleImportsDesignerCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1249 this.buttonImports1.IsChecked = !this.buttonImports1.IsChecked;
1250 this.FocusShellBarDesigner(this.imports1);
1254 void FocusShellBarDesigner(UIElement designer)
1256 // Focus the Argument/Variable/Imports designer when it is turn on.
1257 if (designer.IsEnabled)
1259 if (!designer.IsKeyboardFocusWithin)
1261 Keyboard.Focus(designer);
1264 // Focus an activity designer when the Argument/Variable/Imports designer is turned off and has keyboard focus within.
1265 else if (designer.IsKeyboardFocusWithin)
1267 Keyboard.Focus(this.GetDesignerToFocus());
1271 void OnCreateVariableMenuLoaded(object sender, RoutedEventArgs e)
1273 MenuItem item = sender as MenuItem;
1276 if (Selection.MultipleObjectsSelected(this.Context))
1278 item.Visibility = Visibility.Collapsed;
1281 item.Visibility = variablesStatusBarItem.Visibility;
1285 void OnCreateVariableCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1288 ((this.shellBarItemVisibility & ShellBarItemVisibility.Variables) == ShellBarItemVisibility.Variables) &&
1289 !this.IsReadOnly && null != this.variables1.CurrentVariableScope;
1293 void OnCreateVariableCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1295 this.buttonVariables1.IsChecked = true;
1296 this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => { this.variables1.CreateNewVariableWrapper(); }));
1300 void OnCreateArgumentCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1303 ((this.shellBarItemVisibility & ShellBarItemVisibility.Arguments) == ShellBarItemVisibility.Arguments) &&
1304 !this.IsReadOnly && null != this.arguments1.ActivitySchema;
1308 void OnCreateArgumentCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1310 this.buttonArguments1.IsChecked = true;
1311 this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => { this.arguments1.CreateNewArgumentWrapper(); }));
1315 void OnToggleMiniMapCommandExecute(object sender, CanExecuteRoutedEventArgs e)
1317 e.Handled = e.CanExecute = true;
1320 void OnToggleMiniMapCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1323 this.miniMap.IsEnabled = !this.miniMap.IsEnabled;
1326 void OnCycleThroughDesignerCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1328 e.CanExecute = e.Handled = true;
1331 UIElement GetDesignerToFocus()
1333 Selection selection = this.Context.Items.GetValue<Selection>();
1334 if (selection.SelectionCount != 0 && selection.PrimarySelection.View != null)
1336 return (UIElement)selection.PrimarySelection.View;
1340 return this.RootDesigner;
1344 void OnCycleThroughDesignerCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1346 UIElement toFocus = this.breadCrumbListBox;
1348 if (this.BreadCrumbBarLayout.IsKeyboardFocusWithin)
1350 toFocus = this.GetDesignerToFocus();
1352 else if (this.scrollViewer.IsKeyboardFocusWithin)
1354 if ((bool)this.buttonVariables1.IsChecked)
1356 toFocus = this.variables1;
1358 else if ((bool)this.buttonArguments1.IsChecked)
1360 toFocus = this.arguments1;
1362 else if ((bool)this.buttonImports1.IsChecked)
1364 toFocus = this.imports1;
1368 toFocus = this.buttonVariables1;
1371 else if ((bool)this.buttonVariables1.IsChecked && this.variables1.IsKeyboardFocusWithin)
1373 toFocus = this.buttonVariables1;
1375 else if ((bool)this.buttonArguments1.IsChecked && this.arguments1.IsKeyboardFocusWithin)
1377 toFocus = this.buttonVariables1;
1379 else if ((bool)this.buttonImports1.IsChecked && this.imports1.IsKeyboardFocusWithin)
1381 toFocus = this.buttonVariables1;
1383 this.Dispatcher.BeginInvoke(new Action<IInputElement>((target) =>
1385 System.Diagnostics.Debug.WriteLine(target.GetType().Name + " " + target.GetHashCode());
1386 Keyboard.Focus(target);
1387 }), DispatcherPriority.ApplicationIdle, toFocus);
1391 void OnCreateWorkflowElementCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1393 string typeName = null;
1394 // e.Parameter is IDictionary<string, string> when the designer is hosted
1395 // inside Visual Studio. It is IDataObject otherwise.
1396 if (e.Parameter is IDictionary<string, string>)
1398 IDictionary<string, string> context = e.Parameter as IDictionary<string, string>;
1399 context.TryGetValue("TypeName", out typeName);
1403 IDataObject context = e.Parameter as IDataObject;
1404 if (context != null)
1406 typeName = context.GetData(DragDropHelper.WorkflowItemTypeNameFormat) as string;
1410 bool precondition = !this.IsReadOnly && !string.IsNullOrWhiteSpace(typeName);
1414 Type activityType = Type.GetType(typeName, false);
1415 if (null != activityType)
1417 Selection selection = this.Context.Items.GetValue<Selection>();
1418 if (selection.SelectionCount == 1 && selection.PrimarySelection.View is WorkflowViewElement)
1420 WorkflowViewElement viewElement = (WorkflowViewElement)selection.PrimarySelection.View;
1421 ICompositeView container = viewElement.ActiveCompositeView;
1422 if (null != container)
1424 List<object> itemsToPaste = new List<object>(1);
1426 if (activityType.TryGetActivityTemplateFactory(out factoryType))
1428 itemsToPaste.Add(factoryType);
1432 itemsToPaste.Add(activityType);
1435 e.CanExecute = container.CanPasteItems(itemsToPaste);
1443 void OnCreateWorkflowElementCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1445 Selection selection = this.Context.Items.GetValue<Selection>();
1446 Fx.Assert(selection.SelectionCount == 1, "selection.SelectionCount should be 1.");
1447 Fx.Assert(selection.PrimarySelection.View is WorkflowViewElement, "selection.PrimarySelection.View should be WorkflowViewElement type.");
1449 WorkflowViewElement viewElement = (WorkflowViewElement)selection.PrimarySelection.View;
1451 Type activityType = null;
1452 IDataObject dataObject = null;
1454 // e.Parameter is IDictionary<string, string> when the designer is hosted
1455 // inside Visual Studio. It is IDataObject otherwise.
1456 if (e.Parameter is IDictionary<string, string>)
1458 IDictionary<string, string> context = e.Parameter as IDictionary<string, string>;
1459 activityType = Type.GetType(context["TypeName"]);
1461 // For the VisualStudio 11 hosted designer case data object corresponding to the toolbox item is passed in
1462 // through AppDomain level data by EditorPane.IToolboxUser.ItemPicked method.
1463 string dataObjectKey = typeof(System.Runtime.InteropServices.ComTypes.IDataObject).FullName;
1464 object data = AppDomain.CurrentDomain.GetData(dataObjectKey);
1467 IntPtr dataObjectPointer = (IntPtr)data;
1468 dataObject = new DataObject((System.Runtime.InteropServices.ComTypes.IDataObject)Marshal.GetObjectForIUnknown(dataObjectPointer));
1469 Marshal.Release(dataObjectPointer);
1470 AppDomain.CurrentDomain.SetData(dataObjectKey, null);
1475 dataObject = e.Parameter as IDataObject;
1476 activityType = Type.GetType((string)dataObject.GetData(DragDropHelper.WorkflowItemTypeNameFormat));
1479 object instance = DragDropHelper.GetDroppedObjectInstance(viewElement, this.Context, activityType, dataObject);
1480 if (instance != null)
1482 List<object> itemsToPaste = new List<object>(1);
1483 List<object> metaData = new List<object>(1);
1484 if (instance is FlowNode)
1486 List<FlowNode> flowchartMetaData = new List<FlowNode>(1);
1487 flowchartMetaData.Add(instance as FlowNode);
1488 metaData.Add(flowchartMetaData);
1492 itemsToPaste.Add(instance);
1495 viewElement.ActiveCompositeView.OnItemsPasted(itemsToPaste, metaData, new Point(), null);
1500 void OnFitToScreenCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1502 e.CanExecute = (null != this.zoomToTicksConverter);
1505 void OnFitToScreenCommandExecute(object sender, ExecutedRoutedEventArgs e)
1507 this.zoomToTicksConverter.FitToScreen();
1509 FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.FitToScreen);
1512 void OnResetZoomCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1514 e.CanExecute = (null != this.zoomToTicksConverter);
1517 void OnResetZoomCommandExecute(object sender, ExecutedRoutedEventArgs e)
1519 this.zoomToTicksConverter.ResetZoom();
1521 FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.ResetZoom);
1524 void OnZoomPickerUndoRedoCommandPreviewCanExecute(object sender, CanExecuteRoutedEventArgs e)
1526 e.CanExecute = false;
1530 void OnAnnotationsMenuLoaded(object sender, RoutedEventArgs e)
1532 MenuItem item = sender as MenuItem;
1534 if (this.context.Services.GetService<DesignerConfigurationService>().AnnotationEnabled == true)
1536 if (!Selection.MultipleObjectsSelected(this.Context))
1538 item.Visibility = Visibility.Visible;
1544 item.Visibility = Visibility.Collapsed;
1548 void OnAddAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1550 ContextMenuUtilities.OnAddAnnotationCommandCanExecute(e, this.Context);
1553 void OnAddAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1555 ContextMenuUtilities.OnAddAnnotationCommandExecuted(e, this.Context.Items.GetValue<Selection>().PrimarySelection);
1558 void OnEditAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1560 // call the same method as delete annotation command
1561 ContextMenuUtilities.OnDeleteAnnotationCommandCanExecute(e, this.Context);
1564 void OnEditAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1566 ContextMenuUtilities.OnEditAnnotationCommandExecuted(e, this.Context.Items.GetValue<Selection>().PrimarySelection);
1569 void OnDeleteAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1571 ContextMenuUtilities.OnDeleteAnnotationCommandCanExecute(e, this.Context);
1574 void OnDeleteAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1576 ContextMenuUtilities.OnDeleteAnnotationCommandExecuted(e, this.Context.Items.GetValue<Selection>().PrimarySelection);
1579 void OnShowAllAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1581 if (this.context.Services.GetService<DesignerConfigurationService>().AnnotationEnabled != true)
1583 e.CanExecute = false;
1587 e.CanExecute = true;
1591 void OnShowAllAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1593 ModelTreeManager modelTreeManager = this.Context.Services.GetService<ModelTreeManager>();
1594 AnnotationAdornerService annotationService = this.Context.Services.GetService<AnnotationAdornerService>();
1595 ViewStateService viewStateService = this.Context.Services.GetService<ViewStateService>();
1596 foreach (ModelItem item in ModelTreeManager.Find(modelTreeManager.Root, new Predicate<ModelItem>(ModelItemExtensions.HasAnnotation), false))
1598 viewStateService.StoreViewState(item, Annotation.IsAnnotationDockedViewStateName, true);
1603 void OnHideAllAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1605 if (this.context.Services.GetService<DesignerConfigurationService>().AnnotationEnabled != true)
1607 e.CanExecute = false;
1611 e.CanExecute = true;
1615 void OnHideAllAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1617 ModelTreeManager modelTreeManager = this.Context.Services.GetService<ModelTreeManager>();
1618 AnnotationAdornerService annotationService = this.Context.Services.GetService<AnnotationAdornerService>();
1619 ViewStateService viewStateService = this.Context.Services.GetService<ViewStateService>();
1620 foreach (ModelItem item in ModelTreeManager.Find(modelTreeManager.Root, new Predicate<ModelItem>(ModelItemExtensions.HasAnnotation), false))
1622 viewStateService.StoreViewState(item, Annotation.IsAnnotationDockedViewStateName, false);
1627 void OnDeleteAllAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1629 ContextMenuUtilities.OnDeleteAllAnnotationCommandCanExecute(e, this.Context);
1632 void OnDeleteAllAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1634 ModelTreeManager modelTreeManager = this.Context.Services.GetService<ModelTreeManager>();
1635 AnnotationAdornerService annotationService = this.Context.Services.GetService<AnnotationAdornerService>();
1636 ViewStateService viewStateService = this.Context.Services.GetService<ViewStateService>();
1638 MessageBoxResult result = MessageBox.Show(SR.DeleteAllAnnotationMessage, SR.DeleteAnnotationTitle, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
1640 if (result != MessageBoxResult.Yes)
1646 ModelEditingScope editingScope = null;
1647 bool isModified = false;
1650 foreach (ModelItem item in ModelTreeManager.Find(modelTreeManager.Root, new Predicate<ModelItem>(ModelItemExtensions.HasAnnotation), false))
1653 if (editingScope == null)
1655 editingScope = item.BeginEdit(SR.DeleteAllAnnotationsDescription);
1657 item.Properties[Annotation.AnnotationTextPropertyName].ClearValue();
1658 viewStateService.StoreViewStateWithUndo(item, Annotation.IsAnnotationDockedViewStateName, null);
1663 modelTreeManager.AddToCurrentEditingScope(new NotifyArgumentVariableAnnotationTextChanged()
1665 ArgumentDesigner = this.arguments1,
1666 VariableDesigner = this.variables1,
1672 if (editingScope != null)
1674 editingScope.Complete();
1681 void ExecuteCommand(int command)
1683 IDesignerDebugView debuggerService = this.Context.Services.GetService<IDesignerDebugView>();
1684 ICommandService commandService = this.Context.Services.GetService<ICommandService>();
1685 if (null != commandService)
1688 var commandParameters = (Dictionary<string, object>)null;
1689 if (null != debuggerService &&
1690 (command == CommandValues.InsertBreakpoint ||
1691 command == CommandValues.DeleteBreakpoint ||
1692 command == CommandValues.EnableBreakpoint ||
1693 command == CommandValues.DisableBreakpoint))
1695 commandParameters = new Dictionary<string, object>();
1696 if (command == CommandValues.InsertBreakpoint)
1698 commandParameters.Add(typeof(BreakpointTypes).Name, BreakpointTypes.Bounded);
1701 commandParameters.Add(typeof(SourceLocation).Name, debuggerService.SelectedLocation);
1705 commandService.ExecuteCommand(command, commandParameters);
1709 static FrameworkElement GetMenuItemOrigin(DependencyObject obj)
1711 return (FrameworkElement)obj.GetValue(MenuItemOriginProperty);
1714 static void SetMenuItemOrigin(DependencyObject obj, FrameworkElement value)
1716 obj.SetValue(MenuItemOriginProperty, value);
1719 public static CommandMenuMode GetCommandMenuMode(DependencyObject obj)
1721 return (CommandMenuMode)obj.GetValue(CommandMenuModeProperty);
1724 public static void SetCommandMenuMode(DependencyObject obj, CommandMenuMode value)
1726 obj.SetValue(CommandMenuModeProperty, value);
1729 sealed class ContextMenuItemStyleSelector : StyleSelector
1733 public ContextMenuItemStyleSelector(DesignerView owner)
1738 public override Style SelectStyle(object item, DependencyObject container)
1740 if (item is MenuItem && null != this.owner.MenuItemStyle)
1742 ((MenuItem)item).ItemContainerStyleSelector = this;
1743 return this.owner.MenuItemStyle;
1745 else if (item is Separator && null != this.owner.MenuSeparatorStyle)
1747 return this.owner.MenuSeparatorStyle;
1749 return base.SelectStyle(item, container);
1754 [Fx.Tag.XamlVisible(false)]
1755 public sealed class CommandMenuMode
1757 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes,
1758 Justification = "The class being an empty class, the readonly mutable referencetypes cannot be modified")]
1759 public static readonly CommandMenuMode NoCommandMenu = new CommandMenuMode();
1760 [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)]
1761 public static readonly CommandMenuMode FullCommandMenu = new CommandMenuMode();
1763 private CommandMenuMode()