cca39c9b46dcebafbbbc02f310efb650e4fb5cb3
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / View / DesignerView.Commands.cs
1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------
4
5 namespace System.Activities.Presentation.View
6 {
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;
19     using System.Linq;
20     using System.Runtime;
21     using System.Runtime.InteropServices;
22     using System.Windows;
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;
31
32     public partial class DesignerView
33     {
34         public const string CustomMenuItemsSeparatorCommand = "6F455692-EA19-4ac9-ABEE-57F6DF20A687";
35
36         public static readonly DependencyProperty CommandMenuModeProperty =
37             DependencyProperty.RegisterAttached("CommandMenuMode", typeof(CommandMenuMode), typeof(DesignerView), new UIPropertyMetadata(CommandMenuMode.FullCommandMenu));
38
39         static readonly DependencyProperty MenuItemOriginProperty =
40             DependencyProperty.RegisterAttached("MenuItemOrigin", typeof(FrameworkElement), typeof(DesignerView));
41
42         public static readonly DependencyProperty MenuItemStyleProperty =
43             DependencyProperty.Register("MenuItemStyle", typeof(Style), typeof(DesignerView), new UIPropertyMetadata(null));
44
45         public static readonly DependencyProperty MenuSeparatorStyleProperty =
46             DependencyProperty.Register("MenuSeparatorStyle", typeof(Style), typeof(DesignerView), new UIPropertyMetadata(null));
47
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));
129
130         WorkflowViewElement contextMenuTarget;
131         HashSet<CommandBinding> ignoreCommands = new HashSet<CommandBinding>();
132
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;
139
140         bool ContainsChordKeyGestures(InputGestureCollection collection)
141         {
142             if (collection == null)
143             {
144                 return false;
145             }
146             else
147             {
148                 foreach (KeyGesture gesture in collection)
149                 {
150                     if (gesture.GetType() == typeof(DefaultCommandExtensionCallback.ChordKeyGesture))
151                     {
152                         return true;
153                     }
154                 }
155                 return false;
156             }
157         }
158
159         // Set chordkey gestures owner to this class, so that the chordkey can clear other chord key's mode
160         // after executing.
161         void SetChordKeyGesturesOwner()
162         {
163             foreach (CommandBinding binding in this.CommandBindings)
164             {
165                 RoutedCommand cmd = binding.Command as RoutedCommand;
166                 foreach (KeyGesture gesture in cmd.InputGestures)
167                 {
168                     if (gesture.GetType() == typeof(DefaultCommandExtensionCallback.ChordKeyGesture))
169                     {
170                         ((DefaultCommandExtensionCallback.ChordKeyGesture)gesture).Owner = this;
171                     }
172                 }
173             }
174         }
175
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()
179         {
180             CommandBindingCollection chordCommandBindings = new CommandBindingCollection();
181             CommandBindingCollection basicCommandBindings = new CommandBindingCollection();
182             foreach (CommandBinding binding in this.CommandBindings)
183             {
184                 RoutedCommand cmd = binding.Command as RoutedCommand;
185                 if (ContainsChordKeyGestures(cmd.InputGestures))
186                 {
187                     chordCommandBindings.Add(binding);
188                 }
189                 else
190                 {
191                     basicCommandBindings.Add(binding);
192                 }
193             }
194             this.CommandBindings.Clear();
195             this.CommandBindings.AddRange(chordCommandBindings);
196             this.CommandBindings.AddRange(basicCommandBindings);
197         }
198
199         internal void ResetAllChordKeyGesturesMode()
200         {
201             foreach (CommandBinding binding in this.CommandBindings)
202             {
203                 RoutedCommand cmd = binding.Command as RoutedCommand;
204                 foreach (KeyGesture gesture in cmd.InputGestures)
205                 {
206                     if (gesture.GetType() == typeof(DefaultCommandExtensionCallback.ChordKeyGesture))
207                     {
208                         ((DefaultCommandExtensionCallback.ChordKeyGesture)gesture).ResetChordMode();
209                     }
210                 }
211             }
212         }
213
214         void InitializeMenuActions()
215         {
216             this.isCommandServiceEnabled = () =>
217                 {
218                     return null != this.Context.Services.GetService<ICommandService>();
219                 };
220
221             this.areBreakpointServicesEnabled = () =>
222                 {
223                     return null != this.Context.Services.GetService<IDesignerDebugView>() && this.isCommandServiceEnabled();
224                 };
225
226             this.isCommandSupported = commandId =>
227                 {
228                     return this.Context.Services.GetService<ICommandService>().IsCommandSupported(commandId);
229                 };
230
231
232             this.navigateToParentFunction = (selection, shouldExecute) =>
233                 {
234                     bool result = false;
235                     ModelItem target = null;
236                     if (null != selection && selection.Equals(this.RootDesigner))
237                     {
238                         if (null != selection.ModelItem.Parent)
239                         {
240                             WorkflowViewService viewService = (WorkflowViewService)this.Context.Services.GetService<ViewService>();
241                             target = selection.ModelItem;
242                             do
243                             {
244                                 target = target.Parent;
245                                 if (target == null)
246                                 {
247                                     break;
248                                 }
249                             }
250                             while (!viewService.ShouldAppearOnBreadCrumb(target, true));
251                             result = (null != target);
252                         }
253                     }
254                     if (shouldExecute && result)
255                     {
256                         this.MakeRootDesigner(target);
257                     }
258                     return result ? Visibility.Visible : Visibility.Collapsed;
259                 };
260
261             this.navigateToChildFunction = (selection, shouldExecute) =>
262                 {
263                     bool result = false;
264                     ModelItem target = null;
265                     if (null != selection && !selection.Equals(this.RootDesigner))
266                     {
267                         target = selection.ModelItem;
268                         WorkflowViewService viewService = (WorkflowViewService)this.Context.Services.GetService<ViewService>();
269                         result = viewService.ShouldAppearOnBreadCrumb(target, true);
270                     }
271                     if (shouldExecute && result)
272                     {
273                         this.MakeRootDesigner(target);
274                     }
275                     return result ? Visibility.Visible : Visibility.Collapsed;
276                 };
277
278             this.getBreakpointType = selection =>
279                 {
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)
284                     {
285                         breakpoints.TryGetValue(debugView.SelectedLocation, out result);
286                     }
287                     return result;
288                 };
289             this.ContextMenu.ClipToBounds = false;
290
291             //workflow command extension callback invoker
292             Action<WorkflowCommandExtensionItem> updateCommands = (item) =>
293                 {
294                     //if there are any commands which were ignored - add them back to bindings collections
295                     foreach (CommandBinding binding in this.ignoreCommands)
296                     {
297                         this.CommandBindings.Add(binding);
298                     }
299                     this.ignoreCommands.Clear();
300
301                     if (null != item.CommandExtensionCallback)
302                     {
303                         foreach (CommandBinding cb in this.CommandBindings)
304                         {
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)
309                             {
310                                 this.ignoreCommands.Add(cb);
311                             }
312
313                         }
314                         //remove all commands from ignore list from bindings - let the commands bubble up to the client
315                         foreach (CommandBinding cb in this.ignoreCommands)
316                         {
317                             this.CommandBindings.Remove(cb);
318                         }
319
320                         if (null != this.ContextMenu && this.ContextMenu.HasItems)
321                         {
322                             foreach (MenuItem menuItem in this.ContextMenu.Items.OfType<MenuItem>())
323                             {
324                                 this.RefreshContextMenu(menuItem);
325                             }
326                         }
327                     }
328                     if (item.CommandExtensionCallback.GetType() == typeof(DefaultCommandExtensionCallback))
329                     {
330                         this.ReorderCommandBindings();
331                         this.SetChordKeyGesturesOwner();
332                     }
333                 };
334
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>())
339             {
340                 updateCommands(this.context.Items.GetValue<WorkflowCommandExtensionItem>());
341             }
342         }
343
344         public Style MenuItemStyle
345         {
346             get { return (Style)GetValue(MenuItemStyleProperty); }
347             set { SetValue(MenuItemStyleProperty, value); }
348         }
349
350         public Style MenuSeparatorStyle
351         {
352             get { return (Style)GetValue(MenuSeparatorStyleProperty); }
353             set { SetValue(MenuSeparatorStyleProperty, value); }
354         }
355
356         void RefreshContextMenu(MenuItem menuItem)
357         {
358             if (null != menuItem.Command)
359             {
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;
364             }
365             if (menuItem.HasItems)
366             {
367                 foreach (MenuItem subItem in menuItem.Items.OfType<MenuItem>())
368                 {
369                     this.RefreshContextMenu(subItem);
370                 }
371             }
372         }
373
374         protected override void OnContextMenuOpening(ContextMenuEventArgs e)
375         {
376             bool shouldDisplayMenu = false;
377             DependencyObject target = null;
378             DependencyObject source = e.OriginalSource as DependencyObject;
379             if (source is Adorner)
380             {
381                 source = ((Adorner)source).AdornedElement;
382             }
383
384             DependencyObject designerPresenterSource = this.designerPresenter.FindCommonVisualAncestor(source);
385             DependencyObject extensionSurfaceSource = this.wfViewExtensionSurface.FindCommonVisualAncestor(source);
386
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)
390             {
391                 Selection currentSelection = this.Context.Items.GetValue<Selection>();
392                 if (null != currentSelection && currentSelection.SelectionCount >= 1)
393                 {
394                     if (currentSelection.SelectionCount == 1) // single selection
395                     {
396                         //check original source, to see if it prevents displaying context menu
397                         if (!CommandMenuMode.Equals(CommandMenuMode.NoCommandMenu, GetCommandMenuMode((DependencyObject)e.OriginalSource)))
398                         {
399                             if (null != currentSelection.PrimarySelection.View)
400                             {
401                                 target = currentSelection.PrimarySelection.View;
402                                 shouldDisplayMenu = true;
403                             }
404                         }
405                     }
406                     else // multi-selection
407                     {
408                         // If Multi-selection's context menu was not enabled, don't display menu.
409                         shouldDisplayMenu = Context.Services.GetService<DesignerConfigurationService>().MultipleItemsContextMenuEnabled;
410                     }
411                 }
412             }
413             e.Handled = true;
414             base.OnContextMenuOpening(e);
415
416             if (shouldDisplayMenu)
417             {
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));
421             }
422         }
423
424         void LoadContextMenu(UIElement sender, bool openedByKeyboard)
425         {
426             if (this.ContextMenu == null)
427             {
428                 return;
429             }
430
431             if (!Selection.MultipleObjectsSelected(this.Context) && sender != null && CommandMenuMode.Equals(CommandMenuMode.NoCommandMenu, GetCommandMenuMode(sender)))
432             {
433                 return;
434             }
435
436             //clear context menu state
437             this.UnloadContextMenu(this.ContextMenu);
438
439             this.contextMenuTarget = sender as WorkflowViewElement;
440
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())
446             {
447                 this.ContextMenu.Items.Remove(entry);
448                 entry.Visibility = Visibility.Visible;
449                 newMenu.Items.Insert(0, entry);
450             }
451             this.ContextMenu = newMenu;
452
453             if (!Selection.MultipleObjectsSelected(this.Context))
454             {
455                 if (null != this.contextMenuTarget && null != this.contextMenuTarget.ContextMenu)
456                 {
457                     var items = this.contextMenuTarget.ContextMenu.Items.OfType<Control>().Reverse();
458                     int insertIndex = this.ContextMenu.Items.Count;
459
460                     foreach (var item in items)
461                     {
462                         this.contextMenuTarget.ContextMenu.Items.Remove(item);
463                         DesignerView.SetMenuItemOrigin(item, this.contextMenuTarget);
464                         this.ContextMenu.Items.Insert(insertIndex, item);
465                     }
466                 }
467
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;
471             }
472             else
473             {
474                 this.ContextMenu.Placement = openedByKeyboard ? PlacementMode.Center : PlacementMode.MousePoint;
475                 this.ContextMenu.PlacementTarget = this;
476             }
477
478             this.ContextMenu.IsOpen = true;
479         }
480
481         void UnloadContextMenu(ContextMenu contextMenuToUnload)
482         {
483             if (null != contextMenuToUnload && null != this.contextMenuTarget)
484             {
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)
489                     .Reverse();
490
491                 foreach (Control item in items)
492                 {
493                     //remove item from designer menu's location
494                     contextMenuToUnload.Items.Remove(item);
495
496                     //and add it back to activity designer
497                     DesignerView.GetMenuItemOrigin(item).ContextMenu.Items.Insert(0, item);
498                     DesignerView.SetMenuItemOrigin(item, null);
499                 }
500                 this.contextMenuTarget = null;
501                 contextMenuToUnload.Loaded -= this.OnWorkflowViewContextMenuLoaded;
502                 contextMenuToUnload.Unloaded -= this.OnWorkflowViewContextMenuClosed;
503             }
504         }
505
506         void OnWorkflowViewContextMenuLoaded(object sender, RoutedEventArgs e)
507         {
508             this.ContextMenu.MinWidth = 0;
509             this.ContextMenu.MinWidth = this.ContextMenu.DesiredSize.Width;
510
511             Action<WorkflowViewElement, FrameworkElement> contextMenuLoaded =
512                 (designer, menuSource) =>
513                 {
514                     System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} DesignerView.OnWorkflowViewContextMenuLoaded()", DateTime.Now.ToLocalTime()));
515                     if (null != menuSource && null != menuSource.ContextMenu)
516                     {
517                         if (null != designer) // for single selection, designer is the current selected item, we set CommandTarget to current selection
518                         {
519                             foreach (var item in menuSource.ContextMenu.Items.OfType<MenuItem>())
520                             {
521                                 item.CommandTarget = designer;
522                             }
523                             designer.NotifyContextMenuLoaded(menuSource.ContextMenu);
524                         }
525                         else // for multiple selection, designer is null, we set the CommandTarget to DesignerView
526                         {
527                             foreach (var item in menuSource.ContextMenu.Items.OfType<MenuItem>())
528                             {
529                                 item.CommandTarget = this;
530                             }
531                         }
532                     }
533                 };
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);
536         }
537
538         void OnWorkflowViewContextMenuClosed(object sender, RoutedEventArgs e)
539         {
540             this.UnloadContextMenu((ContextMenu)sender);
541         }
542
543         void OnMenuItemSeparatorLoaded(object sender, RoutedEventArgs e)
544         {
545             //define a delegate which will handle separator load events
546             Action<Separator> action = (separator) =>
547             {
548                 if (null != separator && null != separator.Tag && null != this.ContextMenu)
549                 {
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]))
555                     {
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++)
560                         {
561                             object contextMenuItem = this.ContextMenu.Items[i];
562                             if (contextMenuItem is MenuItem)
563                             {
564                                 visible = ((MenuItem)contextMenuItem).Visibility == Visibility.Visible;
565                             }
566                             else
567                             {
568                                 // For safety sake, someone might put other things into the ContextMenu.Items other than MenuItem.
569                                 visible = true;
570                             }
571                         }
572                         separator.Visibility = visible ? Visibility.Visible : Visibility.Collapsed;
573                     }
574                     else if (commands.Length != 0)
575                     {
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
579                             .OfType<MenuItem>()
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;
583                     }
584                 }
585             };
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);
588         }
589
590         void OnGoToParentMenuLoaded(object sender, RoutedEventArgs e)
591         {
592             MenuItem item = sender as MenuItem;
593             if (null != item)
594             {
595                 if (Selection.MultipleObjectsSelected(this.Context))
596                 {
597                     item.Visibility = Visibility.Collapsed;
598                     e.Handled = true;
599                     return;
600                 }
601                 item.Visibility = this.navigateToParentFunction(this.contextMenuTarget, false);
602             }
603             e.Handled = true;
604         }
605
606         void OnGoToParentCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
607         {
608             e.CanExecute = true;
609             e.Handled = true;
610         }
611
612         void OnGoToParentCommandExecute(object sender, ExecutedRoutedEventArgs e)
613         {
614             this.navigateToParentFunction(this.contextMenuTarget ?? this.FocusedViewElement, true);
615             e.Handled = true;
616             FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.ViewParent);
617         }
618
619         void OnCollapseCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
620         {
621             if (this.FocusedViewElement != null)
622             {
623                 e.CanExecute = this.FocusedViewElement.ShowExpanded;
624             }
625             e.Handled = true;
626         }
627
628         void OnCollapseCommandExecute(object sender, ExecutedRoutedEventArgs e)
629         {
630             this.FocusedViewElement.ExpandState = false;
631             if (this.ShouldExpandAll)
632             {
633                 this.FocusedViewElement.PinState = true;
634             }
635             e.Handled = true;
636         }
637
638         void OnCollapseAllCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
639         {
640             e.CanExecute = !this.ShouldCollapseAll;
641             e.Handled = true;
642         }
643
644         void OnCollapseAllCommandExecute(object sender, ExecutedRoutedEventArgs e)
645         {
646             this.ShouldCollapseAll = true;
647             e.Handled = true;
648             FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.CollapseAll);
649         }
650
651         void OnRestoreCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
652         {
653             e.CanExecute = this.ShouldExpandAll || this.ShouldCollapseAll;
654             e.Handled = true;
655         }
656
657         void OnRestoreCommandExecute(object sender, ExecutedRoutedEventArgs e)
658         {
659             this.ShouldExpandAll = false;
660             this.ShouldCollapseAll = false;
661             e.Handled = true;
662             FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.Restore);
663         }
664
665         void OnExpandAllCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
666         {
667             e.CanExecute = !this.ShouldExpandAll;
668             e.Handled = true;
669         }
670
671         void OnExpandAllCommandExecute(object sender, ExecutedRoutedEventArgs e)
672         {
673             this.ShouldExpandAll = true;
674             e.Handled = true;
675             FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.ExpandAll);
676         }
677
678         void OnCollapseExpandInPlaceMenuLoaded(object sender, RoutedEventArgs e)
679         {
680             MenuItem item = sender as MenuItem;
681             if (null != item)
682             {
683                 if (Selection.MultipleObjectsSelected(this.Context))
684                 {
685                     item.Visibility = Visibility.Collapsed;
686                     e.Handled = true;
687                     return;
688                 }
689                 item.Visibility = ExpandButtonVisibilityConverter.GetExpandCollapseButtonVisibility(this.contextMenuTarget);
690             }
691             e.Handled = true;
692         }
693
694         void OnExpandInPlaceCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
695         {
696             if (this.FocusedViewElement != null)
697             {
698                 e.CanExecute = !this.FocusedViewElement.ShowExpanded;
699             }
700             e.Handled = true;
701         }
702
703         void OnExpandInPlaceCommandExecute(object sender, ExecutedRoutedEventArgs e)
704         {
705             this.FocusedViewElement.ExpandState = true;
706             if (this.ShouldCollapseAll)
707             {
708                 this.FocusedViewElement.PinState = true;
709             }
710             e.Handled = true;
711         }
712
713         void OnExpandMenuLoaded(object sender, RoutedEventArgs e)
714         {
715             MenuItem item = sender as MenuItem;
716             if (null != item)
717             {
718                 if (Selection.MultipleObjectsSelected(this.Context))
719                 {
720                     item.Visibility = Visibility.Collapsed;
721                     e.Handled = true;
722                     return;
723                 }
724                 item.Visibility = this.navigateToChildFunction(this.contextMenuTarget, false);
725             }
726             e.Handled = true;
727         }
728
729         void OnExpandCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
730         {
731             e.CanExecute = true;
732             e.Handled = true;
733         }
734
735         void OnExpandCommandExecute(object sender, ExecutedRoutedEventArgs e)
736         {
737             this.navigateToChildFunction(this.contextMenuTarget ?? this.FocusedViewElement, true);
738             e.Handled = true;
739             FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.OpenChild);
740         }
741
742         void OnCopyCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
743         {
744             e.CanExecute = !this.IsReadOnly && CutCopyPasteHelper.CanCopy(this.Context);
745             e.ContinueRouting = false;
746             e.Handled = true;
747         }
748
749         void OnCopyCommandExecute(object sender, ExecutedRoutedEventArgs e)
750         {
751             this.Context.Services.GetService<DesignerPerfEventProvider>().WorkflowDesignerCopyStart();
752             CutCopyPasteHelper.DoCopy(this.Context);
753             e.Handled = true;
754             this.Context.Services.GetService<DesignerPerfEventProvider>().WorkflowDesignerCopyEnd();
755         }
756
757         void OnPasteCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
758         {
759             e.CanExecute = !this.IsReadOnly && CutCopyPasteHelper.CanPaste(this.Context);
760             e.ContinueRouting = false;
761             e.Handled = true;
762         }
763
764         void OnPasteCommandExecute(object sender, ExecutedRoutedEventArgs e)
765         {
766             context.Services.GetService<DesignerPerfEventProvider>().WorkflowDesignerPasteStart();
767             WorkflowViewElement sourceElement = e.OriginalSource as WorkflowViewElement;
768             if (sourceElement != null)
769             {
770                 Point contextMenuTopLeft = this.ContextMenu.TranslatePoint(new Point(0, 0), sourceElement);
771                 CutCopyPasteHelper.DoPaste(this.Context, contextMenuTopLeft, sourceElement);
772             }
773             else
774             {
775                 CutCopyPasteHelper.DoPaste(this.Context);
776             }
777             e.Handled = true;
778             context.Services.GetService<DesignerPerfEventProvider>().WorkflowDesignerPasteEnd();
779         }
780
781         void OnCutCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
782         {
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;
786             e.Handled = true;
787         }
788
789         void OnCutCommandExecute(object sender, ExecutedRoutedEventArgs e)
790         {
791             CutCopyPasteHelper.DoCut(this.Context);
792             e.Handled = true;
793         }
794
795         void OnDeleteCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
796         {
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;
800             e.Handled = true;
801         }
802
803         void OnDeleteCommandExecute(object sender, ExecutedRoutedEventArgs e)
804         {
805             DeleteHelper.Delete(this.Context);
806             e.Handled = true;
807         }
808
809         void OnPropertiesMenuLoaded(object sender, RoutedEventArgs e)
810         {
811             MenuItem item = sender as MenuItem;
812             if (null != item)
813             {
814                 item.Visibility = this.isCommandServiceEnabled() && this.isCommandSupported(CommandValues.ShowProperties) ?
815                     Visibility.Visible : Visibility.Collapsed;
816             }
817             e.Handled = true;
818         }
819
820         void OnShowPropertiesCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
821         {
822             e.CanExecute = true;
823             e.Handled = true;
824         }
825
826         void OnShowPropertiesCommandExecute(object sender, ExecutedRoutedEventArgs e)
827         {
828             //execute ShowProperties command
829             ExecuteCommand(CommandValues.ShowProperties);
830             e.Handled = true;
831         }
832
833         void OnBreakpointMenuLoaded(object sender, RoutedEventArgs e)
834         {
835             MenuItem item = sender as MenuItem;
836             if (null != item)
837             {
838                 if (Selection.MultipleObjectsSelected(this.Context))
839                 {
840                     item.Visibility = Visibility.Collapsed;
841                     e.Handled = true;
842                     return;
843                 }
844                 item.Visibility =
845                     this.areBreakpointServicesEnabled() && (this.contextMenuTarget is ActivityDesigner) ?
846                     Visibility.Visible : Visibility.Collapsed;
847             }
848             e.Handled = true;
849         }
850
851         void OnInsertBreakpointMenuLoaded(object sender, RoutedEventArgs e)
852         {
853             MenuItem item = sender as MenuItem;
854             if (null != item)
855             {
856                 item.Visibility =
857                     this.areBreakpointServicesEnabled() &&
858                     this.isCommandSupported(CommandValues.InsertBreakpoint) &&
859                     this.getBreakpointType(this.FocusedViewElement) == BreakpointTypes.None ?
860                     Visibility.Visible : Visibility.Collapsed;
861             }
862             e.Handled = true;
863         }
864
865         void OnInsertBreakpointCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
866         {
867             e.CanExecute = this.FocusedViewElement != null && this.FocusedViewElement.ModelItem != null &&
868                 AllowBreakpointAttribute.IsBreakpointAllowed(this.FocusedViewElement.ModelItem.ItemType);
869             e.Handled = true;
870         }
871
872         void OnInsertBreakpointCommandExecute(object sender, ExecutedRoutedEventArgs e)
873         {
874             ExecuteCommand(CommandValues.InsertBreakpoint);
875             e.Handled = true;
876         }
877
878         void OnDeleteBreakpointMenuLoaded(object sender, RoutedEventArgs e)
879         {
880             MenuItem item = sender as MenuItem;
881             if (null != item)
882             {
883                 item.Visibility =
884                     this.areBreakpointServicesEnabled() &&
885                     this.isCommandSupported(CommandValues.DeleteBreakpoint) &&
886                     this.getBreakpointType(this.FocusedViewElement) != BreakpointTypes.None ?
887                     Visibility.Visible : Visibility.Collapsed;
888             }
889             e.Handled = true;
890         }
891
892         void OnDeleteBreakpointCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
893         {
894             e.CanExecute = this.FocusedViewElement != null && this.FocusedViewElement.ModelItem != null &&
895                 AllowBreakpointAttribute.IsBreakpointAllowed(this.FocusedViewElement.ModelItem.ItemType);
896             e.Handled = true;
897         }
898
899         void OnDeleteBreakpointCommandExecute(object sender, ExecutedRoutedEventArgs e)
900         {
901             ExecuteCommand(CommandValues.DeleteBreakpoint);
902             e.Handled = true;
903         }
904
905         void OnEnableBreakpointMenuLoaded(object sender, RoutedEventArgs e)
906         {
907             MenuItem item = sender as MenuItem;
908             if (null != item)
909             {
910                 Visibility visibility = Visibility.Collapsed;
911                 if (this.areBreakpointServicesEnabled() && this.isCommandSupported(CommandValues.EnableBreakpoint))
912                 {
913                     BreakpointTypes breakpoint = this.getBreakpointType(this.FocusedViewElement);
914                     visibility = ((breakpoint & BreakpointTypes.Bounded) != 0 && (breakpoint & BreakpointTypes.Enabled) == 0) ?
915                         Visibility.Visible : Visibility.Collapsed;
916                 }
917                 item.Visibility = visibility;
918             }
919             e.Handled = true;
920         }
921
922         void OnEnableBreakpointCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
923         {
924             e.CanExecute = true;
925             e.Handled = true;
926         }
927
928         void OnEnableBreakpointCommandExecute(object sender, ExecutedRoutedEventArgs e)
929         {
930             ExecuteCommand(CommandValues.EnableBreakpoint);
931             e.Handled = true;
932         }
933
934         void OnDisableBreakpointMenuLoaded(object sender, RoutedEventArgs e)
935         {
936             MenuItem item = sender as MenuItem;
937             if (null != item)
938             {
939                 Visibility visibility = Visibility.Collapsed;
940                 if (this.areBreakpointServicesEnabled() && this.isCommandSupported(CommandValues.DisableBreakpoint))
941                 {
942                     BreakpointTypes breakpoint = this.getBreakpointType(this.FocusedViewElement);
943                     visibility = ((breakpoint & BreakpointTypes.Bounded) != 0 && (breakpoint & BreakpointTypes.Enabled) != 0) ?
944                         Visibility.Visible : Visibility.Collapsed;
945                 }
946                 item.Visibility = visibility;
947             }
948             e.Handled = true;
949         }
950
951
952         void OnDisableBreakpointCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
953         {
954             e.CanExecute = true;
955             e.Handled = true;
956         }
957
958         void OnDisableBreakpointCommandExecute(object sender, ExecutedRoutedEventArgs e)
959         {
960             ExecuteCommand(CommandValues.DisableBreakpoint);
961             e.Handled = true;
962         }
963
964         void OnUndoCommandExecute(object sender, ExecutedRoutedEventArgs e)
965         {
966             this.Context.Services.GetService<UndoEngine>().Undo();
967             e.Handled = true;
968         }
969
970         void OnUndoCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
971         {
972             e.CanExecute = true;
973             e.Handled = true;
974         }
975
976         void OnRedoCommandExecute(object sender, ExecutedRoutedEventArgs e)
977         {
978             this.Context.Services.GetService<UndoEngine>().Redo();
979             e.Handled = true;
980         }
981
982         void OnRedoCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
983         {
984             e.CanExecute = true;
985             e.Handled = true;
986         }
987
988         void OnCommitCommandExecute(object sender, ExecutedRoutedEventArgs e)
989         {
990             TextBox textBox = e.OriginalSource as TextBox;
991             if (textBox != null)
992             {
993                 BindingExpression textBinding = textBox.GetBindingExpression(TextBox.TextProperty);
994                 if (textBinding != null)
995                 {
996                     textBinding.UpdateSource();
997                     e.Handled = true;
998                 }
999             }
1000         }
1001
1002         void OnCommitCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1003         {
1004             e.CanExecute = true;
1005             e.Handled = true;
1006         }
1007
1008         void OnSelectAllCommandExecute(object sender, ExecutedRoutedEventArgs e)
1009         {
1010             this.SelectAll();
1011             e.Handled = true;
1012         }
1013
1014         void OnCopyAsImageMenuLoaded(object sender, RoutedEventArgs e)
1015         {
1016             MenuItem item = sender as MenuItem;
1017             if (null != item)
1018             {
1019                 if (Selection.MultipleObjectsSelected(this.Context))
1020                 {
1021                     item.Visibility = Visibility.Collapsed;
1022                 }
1023                 else
1024                 {
1025                     item.Visibility = Visibility.Visible;
1026                 }
1027             }
1028             e.Handled = true;
1029         }
1030
1031         void OnCopyAsImageCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1032         {
1033             e.CanExecute = null != this.RootDesigner;
1034             e.Handled = true;
1035         }
1036
1037         void OnCopyAsImageCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1038         {
1039             VirtualizedContainerService virtualizingContainerService = this.Context.Services.GetService<VirtualizedContainerService>();
1040             virtualizingContainerService.BeginPopulateAll((Action)(() =>
1041             {
1042                 BitmapSource screenShot = this.CreateScreenShot();
1043                 try
1044                 {
1045                     RetriableClipboard.SetImage(screenShot);
1046                 }
1047                 catch (COMException err)
1048                 {
1049                     ErrorReporting.ShowErrorMessage(err.Message);
1050                 }
1051                 e.Handled = true;
1052                 FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.CopyAsImage);
1053             }));
1054         }
1055
1056         void OnSaveAsImageMenuLoaded(object sender, RoutedEventArgs e)
1057         {
1058             MenuItem item = sender as MenuItem;
1059             if (null != item)
1060             {
1061                 if (Selection.MultipleObjectsSelected(this.Context))
1062                 {
1063                     item.Visibility = Visibility.Collapsed;
1064                 }
1065                 else
1066                 {
1067                     item.Visibility = Visibility.Visible;
1068                 }
1069             }
1070             e.Handled = true;
1071         }
1072
1073         void OnSaveAsImageCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1074         {
1075             e.CanExecute = null != this.RootDesigner;
1076             e.Handled = true;
1077         }
1078
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)
1083         {
1084
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)))
1091             {
1092                 name = (string)displayNameProperty.GetValue(rootItem);
1093             }
1094             SaveFileDialog dlg = new SaveFileDialog()
1095             {
1096                 Filter = @"JPG|*.jpg|PNG|*.png|GIF|*.gif|XPS|*.xps",
1097                 FileName = name
1098             };
1099             bool? showDialogResult = false;
1100             try
1101             {
1102                 showDialogResult = dlg.ShowDialog();
1103             }
1104             catch (ArgumentException)
1105             {
1106                 dlg.FileName = null;
1107                 showDialogResult = dlg.ShowDialog();
1108             }
1109             if (true == showDialogResult && !string.IsNullOrEmpty(dlg.FileName))
1110             {
1111                 VirtualizedContainerService virtualizingContainerService = this.Context.Services.GetService<VirtualizedContainerService>();
1112                 virtualizingContainerService.BeginPopulateAll((Action)(() =>
1113                 {
1114                     try
1115                     {
1116                         switch (dlg.FilterIndex)
1117                         {
1118                             case 1:
1119                                 this.CreateImageFile(dlg.FileName, typeof(JpegBitmapEncoder));
1120                                 break;
1121
1122                             case 2:
1123                                 this.CreateImageFile(dlg.FileName, typeof(PngBitmapEncoder));
1124                                 break;
1125
1126                             case 3:
1127                                 this.CreateImageFile(dlg.FileName, typeof(GifBitmapEncoder));
1128                                 break;
1129
1130                             case 4:
1131                                 this.CreateXPSDocument(dlg.FileName);
1132                                 break;
1133
1134                             default:
1135                                 throw FxTrace.Exception.AsError(new InvalidOperationException("Not supported file type"));
1136                         }
1137                     }
1138                     catch (Exception err)
1139                     {
1140                         MessageBox.Show(err.Message, err.GetType().Name, MessageBoxButton.OK, MessageBoxImage.Error);
1141                     }
1142                 }));
1143             }
1144             e.Handled = true;
1145             FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.SaveAsImage);
1146         }
1147
1148         void OnZoomInCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1149         {
1150             e.CanExecute = this.zoomToTicksConverter.CanZoomIn();
1151             e.Handled = true;
1152         }
1153
1154         void OnZoomInCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1155         {
1156             this.zoomToTicksConverter.ZoomIn();
1157             e.Handled = true;
1158         }
1159
1160         void OnMoveFocusCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1161         {
1162             e.CanExecute = true;
1163             e.Handled = true;
1164         }
1165         void OnMoveFocusCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1166         {
1167             UIElement focusedElement = Keyboard.FocusedElement as UIElement;
1168             if (focusedElement != null)
1169             {
1170                 this.IsMultipleSelectionMode = true;
1171                 focusedElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
1172                 this.IsMultipleSelectionMode = false;
1173             }
1174             e.Handled = true;
1175         }
1176
1177         void OnToggleSelectionCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1178         {
1179             e.CanExecute = true;
1180             e.Handled = true;
1181         }
1182         void OnToggleSelectionCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1183         {
1184             WorkflowViewElement focusedElement = Keyboard.FocusedElement as WorkflowViewElement;
1185             if (focusedElement != null && focusedElement.ModelItem != null)
1186             {
1187                 Selection.Toggle(this.Context, focusedElement.ModelItem);
1188             }
1189             e.Handled = true;
1190         }
1191
1192         void OnZoomOutCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1193         {
1194             e.CanExecute = this.zoomToTicksConverter.CanZoomOut();
1195             e.Handled = true;
1196         }
1197
1198         void OnZoomOutCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1199         {
1200             this.zoomToTicksConverter.ZoomOut();
1201             e.Handled = true;
1202         }
1203
1204         void OnToggleArgumentDesignerCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1205         {
1206             e.CanExecute =
1207                 ((this.shellBarItemVisibility & ShellBarItemVisibility.Arguments) == ShellBarItemVisibility.Arguments) &&
1208                 null != this.ActivitySchema &&
1209                 typeof(ActivityBuilder).IsAssignableFrom(this.ActivitySchema.ItemType);
1210             e.Handled = true;
1211
1212         }
1213
1214         void OnToggleArgumentDesignerCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1215         {
1216             this.buttonArguments1.IsChecked = !this.buttonArguments1.IsChecked;
1217             this.FocusShellBarDesigner(this.arguments1);
1218             e.Handled = true;
1219         }
1220
1221         void OnToggleVariableDesignerCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1222         {
1223             e.CanExecute = ((this.shellBarItemVisibility & ShellBarItemVisibility.Variables) == ShellBarItemVisibility.Variables);
1224             e.Handled = true;
1225         }
1226
1227         void OnToggleVariableDesignerCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1228         {
1229             this.buttonVariables1.IsChecked = !this.buttonVariables1.IsChecked;
1230             this.FocusShellBarDesigner(this.variables1);
1231             e.Handled = true;
1232         }
1233
1234         void OnToggleImportsDesignerCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1235         {
1236             if ((this.shellBarItemVisibility & ShellBarItemVisibility.Imports) == ShellBarItemVisibility.Imports)
1237             {
1238                 e.CanExecute = true;
1239             }
1240             else
1241             {
1242                 e.CanExecute = false;
1243             }
1244             e.Handled = true;
1245         }
1246
1247         void OnToggleImportsDesignerCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1248         {
1249             this.buttonImports1.IsChecked = !this.buttonImports1.IsChecked;
1250             this.FocusShellBarDesigner(this.imports1);
1251             e.Handled = true;
1252         }
1253
1254         void FocusShellBarDesigner(UIElement designer)
1255         {
1256             // Focus the Argument/Variable/Imports designer when it is turn on.
1257             if (designer.IsEnabled)
1258             {
1259                 if (!designer.IsKeyboardFocusWithin)
1260                 {
1261                     Keyboard.Focus(designer);
1262                 }
1263             }
1264             // Focus an activity designer when the Argument/Variable/Imports designer is turned off and has keyboard focus within.
1265             else if (designer.IsKeyboardFocusWithin)
1266             {
1267                 Keyboard.Focus(this.GetDesignerToFocus());
1268             }
1269         }
1270
1271         void OnCreateVariableMenuLoaded(object sender, RoutedEventArgs e)
1272         {
1273             MenuItem item = sender as MenuItem;
1274             if (null != item)
1275             {
1276                 if (Selection.MultipleObjectsSelected(this.Context))
1277                 {
1278                     item.Visibility = Visibility.Collapsed;
1279                     return;
1280                 }
1281                 item.Visibility = variablesStatusBarItem.Visibility;
1282             }
1283         }
1284
1285         void OnCreateVariableCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1286         {
1287             e.CanExecute =
1288                 ((this.shellBarItemVisibility & ShellBarItemVisibility.Variables) == ShellBarItemVisibility.Variables) &&
1289                 !this.IsReadOnly && null != this.variables1.CurrentVariableScope;
1290             e.Handled = true;
1291         }
1292
1293         void OnCreateVariableCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1294         {
1295             this.buttonVariables1.IsChecked = true;
1296             this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => { this.variables1.CreateNewVariableWrapper(); }));
1297             e.Handled = true;
1298         }
1299
1300         void OnCreateArgumentCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1301         {
1302             e.CanExecute =
1303                 ((this.shellBarItemVisibility & ShellBarItemVisibility.Arguments) == ShellBarItemVisibility.Arguments) &&
1304                 !this.IsReadOnly && null != this.arguments1.ActivitySchema;
1305             e.Handled = true;
1306         }
1307
1308         void OnCreateArgumentCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1309         {
1310             this.buttonArguments1.IsChecked = true;
1311             this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => { this.arguments1.CreateNewArgumentWrapper(); }));
1312             e.Handled = true;
1313         }
1314
1315         void OnToggleMiniMapCommandExecute(object sender, CanExecuteRoutedEventArgs e)
1316         {
1317             e.Handled = e.CanExecute = true;
1318         }
1319
1320         void OnToggleMiniMapCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1321         {
1322             e.Handled = true;
1323             this.miniMap.IsEnabled = !this.miniMap.IsEnabled;
1324         }
1325
1326         void OnCycleThroughDesignerCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1327         {
1328             e.CanExecute = e.Handled = true;
1329         }
1330
1331         UIElement GetDesignerToFocus()
1332         {
1333             Selection selection = this.Context.Items.GetValue<Selection>();
1334             if (selection.SelectionCount != 0 && selection.PrimarySelection.View != null)
1335             {
1336                 return (UIElement)selection.PrimarySelection.View;
1337             }
1338             else
1339             {
1340                 return this.RootDesigner;
1341             }
1342         }
1343
1344         void OnCycleThroughDesignerCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1345         {
1346             UIElement toFocus = this.breadCrumbListBox;
1347
1348             if (this.BreadCrumbBarLayout.IsKeyboardFocusWithin)
1349             {
1350                 toFocus = this.GetDesignerToFocus();
1351             }
1352             else if (this.scrollViewer.IsKeyboardFocusWithin)
1353             {
1354                 if ((bool)this.buttonVariables1.IsChecked)
1355                 {
1356                     toFocus = this.variables1;
1357                 }
1358                 else if ((bool)this.buttonArguments1.IsChecked)
1359                 {
1360                     toFocus = this.arguments1;
1361                 }
1362                 else if ((bool)this.buttonImports1.IsChecked)
1363                 {
1364                     toFocus = this.imports1;
1365                 }
1366                 else
1367                 {
1368                     toFocus = this.buttonVariables1;
1369                 }
1370             }
1371             else if ((bool)this.buttonVariables1.IsChecked && this.variables1.IsKeyboardFocusWithin)
1372             {
1373                 toFocus = this.buttonVariables1;
1374             }
1375             else if ((bool)this.buttonArguments1.IsChecked && this.arguments1.IsKeyboardFocusWithin)
1376             {
1377                 toFocus = this.buttonVariables1;
1378             }
1379             else if ((bool)this.buttonImports1.IsChecked && this.imports1.IsKeyboardFocusWithin)
1380             {
1381                 toFocus = this.buttonVariables1;
1382             }
1383             this.Dispatcher.BeginInvoke(new Action<IInputElement>((target) =>
1384                 {
1385                     System.Diagnostics.Debug.WriteLine(target.GetType().Name + " " + target.GetHashCode());
1386                     Keyboard.Focus(target);
1387                 }), DispatcherPriority.ApplicationIdle, toFocus);
1388             e.Handled = true;
1389         }
1390
1391         void OnCreateWorkflowElementCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1392         {
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>)
1397             {
1398                 IDictionary<string, string> context = e.Parameter as IDictionary<string, string>;
1399                 context.TryGetValue("TypeName", out typeName);
1400             }
1401             else
1402             {
1403                 IDataObject context = e.Parameter as IDataObject;
1404                 if (context != null)
1405                 {
1406                     typeName = context.GetData(DragDropHelper.WorkflowItemTypeNameFormat) as string;
1407                 }
1408             }
1409
1410             bool precondition = !this.IsReadOnly && !string.IsNullOrWhiteSpace(typeName);
1411
1412             if (precondition)
1413             {
1414                 Type activityType = Type.GetType(typeName, false);
1415                 if (null != activityType)
1416                 {
1417                     Selection selection = this.Context.Items.GetValue<Selection>();
1418                     if (selection.SelectionCount == 1 && selection.PrimarySelection.View is WorkflowViewElement)
1419                     {
1420                         WorkflowViewElement viewElement = (WorkflowViewElement)selection.PrimarySelection.View;
1421                         ICompositeView container = viewElement.ActiveCompositeView;
1422                         if (null != container)
1423                         {
1424                             List<object> itemsToPaste = new List<object>(1);
1425                             Type factoryType;
1426                             if (activityType.TryGetActivityTemplateFactory(out factoryType))
1427                             {
1428                                 itemsToPaste.Add(factoryType);
1429                             }
1430                             else
1431                             {
1432                                 itemsToPaste.Add(activityType);
1433                             }
1434
1435                             e.CanExecute = container.CanPasteItems(itemsToPaste);
1436                         }
1437                     }
1438                 }
1439             }
1440             e.Handled = true;
1441         }
1442
1443         void OnCreateWorkflowElementCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1444         {
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.");
1448
1449             WorkflowViewElement viewElement = (WorkflowViewElement)selection.PrimarySelection.View;
1450
1451             Type activityType = null;
1452             IDataObject dataObject = null;
1453
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>)
1457             {
1458                 IDictionary<string, string> context = e.Parameter as IDictionary<string, string>;
1459                 activityType = Type.GetType(context["TypeName"]);
1460
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);
1465                 if (data is IntPtr)
1466                 {
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);
1471                 }
1472             }
1473             else
1474             {
1475                 dataObject = e.Parameter as IDataObject;
1476                 activityType = Type.GetType((string)dataObject.GetData(DragDropHelper.WorkflowItemTypeNameFormat));
1477             }
1478
1479             object instance = DragDropHelper.GetDroppedObjectInstance(viewElement, this.Context, activityType, dataObject);
1480             if (instance != null)
1481             {
1482                 List<object> itemsToPaste = new List<object>(1);
1483                 List<object> metaData = new List<object>(1);
1484                 if (instance is FlowNode)
1485                 {
1486                     List<FlowNode> flowchartMetaData = new List<FlowNode>(1);
1487                     flowchartMetaData.Add(instance as FlowNode);
1488                     metaData.Add(flowchartMetaData);
1489                 }
1490                 else
1491                 {
1492                     itemsToPaste.Add(instance);
1493                 }
1494
1495                 viewElement.ActiveCompositeView.OnItemsPasted(itemsToPaste, metaData, new Point(), null);
1496             }
1497             e.Handled = true;
1498         }
1499
1500         void OnFitToScreenCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1501         {
1502             e.CanExecute = (null != this.zoomToTicksConverter);
1503         }
1504
1505         void OnFitToScreenCommandExecute(object sender, ExecutedRoutedEventArgs e)
1506         {
1507             this.zoomToTicksConverter.FitToScreen();
1508             e.Handled = true;
1509             FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.FitToScreen);
1510         }
1511
1512         void OnResetZoomCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1513         {
1514             e.CanExecute = (null != this.zoomToTicksConverter);
1515         }
1516
1517         void OnResetZoomCommandExecute(object sender, ExecutedRoutedEventArgs e)
1518         {
1519             this.zoomToTicksConverter.ResetZoom();
1520             e.Handled = true;
1521             FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.ResetZoom);
1522         }
1523
1524         void OnZoomPickerUndoRedoCommandPreviewCanExecute(object sender, CanExecuteRoutedEventArgs e)
1525         {
1526             e.CanExecute = false;
1527             e.Handled = true;
1528         }
1529
1530         void OnAnnotationsMenuLoaded(object sender, RoutedEventArgs e)
1531         {
1532             MenuItem item = sender as MenuItem;
1533
1534             if (this.context.Services.GetService<DesignerConfigurationService>().AnnotationEnabled == true)
1535             {
1536                 if (!Selection.MultipleObjectsSelected(this.Context))
1537                 {
1538                     item.Visibility = Visibility.Visible;
1539                     e.Handled = true;
1540                     return;
1541                 }
1542             }
1543
1544             item.Visibility = Visibility.Collapsed;
1545             e.Handled = true;
1546         }
1547
1548         void OnAddAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1549         {
1550             ContextMenuUtilities.OnAddAnnotationCommandCanExecute(e, this.Context);
1551         }
1552
1553         void OnAddAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1554         {
1555             ContextMenuUtilities.OnAddAnnotationCommandExecuted(e, this.Context.Items.GetValue<Selection>().PrimarySelection);
1556         }
1557
1558         void OnEditAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1559         {
1560             // call the same method as delete annotation command
1561             ContextMenuUtilities.OnDeleteAnnotationCommandCanExecute(e, this.Context);
1562         }
1563
1564         void OnEditAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1565         {
1566             ContextMenuUtilities.OnEditAnnotationCommandExecuted(e, this.Context.Items.GetValue<Selection>().PrimarySelection);
1567         }
1568
1569         void OnDeleteAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1570         {
1571             ContextMenuUtilities.OnDeleteAnnotationCommandCanExecute(e, this.Context);
1572         }
1573
1574         void OnDeleteAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1575         {
1576             ContextMenuUtilities.OnDeleteAnnotationCommandExecuted(e, this.Context.Items.GetValue<Selection>().PrimarySelection);
1577         }
1578
1579         void OnShowAllAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1580         {
1581             if (this.context.Services.GetService<DesignerConfigurationService>().AnnotationEnabled != true)
1582             {
1583                 e.CanExecute = false;
1584                 return;
1585             }
1586
1587             e.CanExecute = true;
1588             e.Handled = true;
1589         }
1590
1591         void OnShowAllAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1592         {
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))
1597             {
1598                 viewStateService.StoreViewState(item, Annotation.IsAnnotationDockedViewStateName, true);
1599             }
1600             e.Handled = true;
1601         }
1602
1603         void OnHideAllAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1604         {
1605             if (this.context.Services.GetService<DesignerConfigurationService>().AnnotationEnabled != true)
1606             {
1607                 e.CanExecute = false;
1608                 return;
1609             }
1610
1611             e.CanExecute = true;
1612             e.Handled = true;
1613         }
1614
1615         void OnHideAllAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1616         {
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))
1621             {
1622                 viewStateService.StoreViewState(item, Annotation.IsAnnotationDockedViewStateName, false);
1623             }
1624             e.Handled = true;
1625         }
1626
1627         void OnDeleteAllAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
1628         {
1629             ContextMenuUtilities.OnDeleteAllAnnotationCommandCanExecute(e, this.Context);
1630         }
1631
1632         void OnDeleteAllAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e)
1633         {
1634             ModelTreeManager modelTreeManager = this.Context.Services.GetService<ModelTreeManager>();
1635             AnnotationAdornerService annotationService = this.Context.Services.GetService<AnnotationAdornerService>();
1636             ViewStateService viewStateService = this.Context.Services.GetService<ViewStateService>();
1637
1638             MessageBoxResult result = MessageBox.Show(SR.DeleteAllAnnotationMessage, SR.DeleteAnnotationTitle, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
1639
1640             if (result != MessageBoxResult.Yes)
1641             {
1642                 e.Handled = true;
1643                 return;
1644             }
1645
1646             ModelEditingScope editingScope = null;
1647             bool isModified = false;
1648             try
1649             {
1650                 foreach (ModelItem item in ModelTreeManager.Find(modelTreeManager.Root, new Predicate<ModelItem>(ModelItemExtensions.HasAnnotation), false))
1651                 {
1652                     isModified = true;
1653                     if (editingScope == null)
1654                     {
1655                         editingScope = item.BeginEdit(SR.DeleteAllAnnotationsDescription);
1656                     }
1657                     item.Properties[Annotation.AnnotationTextPropertyName].ClearValue();
1658                     viewStateService.StoreViewStateWithUndo(item, Annotation.IsAnnotationDockedViewStateName, null);
1659                 }
1660
1661                 if (isModified)
1662                 {
1663                     modelTreeManager.AddToCurrentEditingScope(new NotifyArgumentVariableAnnotationTextChanged()
1664                     {
1665                         ArgumentDesigner = this.arguments1,
1666                         VariableDesigner = this.variables1,
1667                     });
1668                 }
1669             }
1670             finally
1671             {
1672                 if (editingScope != null)
1673                 {
1674                     editingScope.Complete();
1675                 }
1676             }
1677
1678             e.Handled = true;
1679         }
1680
1681         void ExecuteCommand(int command)
1682         {
1683             IDesignerDebugView debuggerService = this.Context.Services.GetService<IDesignerDebugView>();
1684             ICommandService commandService = this.Context.Services.GetService<ICommandService>();
1685             if (null != commandService)
1686             {
1687                 //setup parameters
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))
1694                 {
1695                     commandParameters = new Dictionary<string, object>();
1696                     if (command == CommandValues.InsertBreakpoint)
1697                     {
1698                         commandParameters.Add(typeof(BreakpointTypes).Name, BreakpointTypes.Bounded);
1699                     }
1700
1701                     commandParameters.Add(typeof(SourceLocation).Name, debuggerService.SelectedLocation);
1702                 }
1703
1704                 //execute command
1705                 commandService.ExecuteCommand(command, commandParameters);
1706             }
1707         }
1708
1709         static FrameworkElement GetMenuItemOrigin(DependencyObject obj)
1710         {
1711             return (FrameworkElement)obj.GetValue(MenuItemOriginProperty);
1712         }
1713
1714         static void SetMenuItemOrigin(DependencyObject obj, FrameworkElement value)
1715         {
1716             obj.SetValue(MenuItemOriginProperty, value);
1717         }
1718
1719         public static CommandMenuMode GetCommandMenuMode(DependencyObject obj)
1720         {
1721             return (CommandMenuMode)obj.GetValue(CommandMenuModeProperty);
1722         }
1723
1724         public static void SetCommandMenuMode(DependencyObject obj, CommandMenuMode value)
1725         {
1726             obj.SetValue(CommandMenuModeProperty, value);
1727         }
1728
1729         sealed class ContextMenuItemStyleSelector : StyleSelector
1730         {
1731             DesignerView owner;
1732
1733             public ContextMenuItemStyleSelector(DesignerView owner)
1734             {
1735                 this.owner = owner;
1736             }
1737
1738             public override Style SelectStyle(object item, DependencyObject container)
1739             {
1740                 if (item is MenuItem && null != this.owner.MenuItemStyle)
1741                 {
1742                     ((MenuItem)item).ItemContainerStyleSelector = this;
1743                     return this.owner.MenuItemStyle;
1744                 }
1745                 else if (item is Separator && null != this.owner.MenuSeparatorStyle)
1746                 {
1747                     return this.owner.MenuSeparatorStyle;
1748                 }
1749                 return base.SelectStyle(item, container);
1750             }
1751         }
1752     }
1753
1754     [Fx.Tag.XamlVisible(false)]
1755     public sealed class CommandMenuMode
1756     {
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();
1762
1763         private CommandMenuMode()
1764         {
1765         }
1766     }
1767 }