//---------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------- namespace System.Activities.Presentation.View { using System.Activities.Debugger; using System.Activities.Presentation.Annotations; using System.Activities.Presentation.Debug; using System.Activities.Presentation.Hosting; using System.Activities.Presentation.Model; using System.Activities.Presentation.Services; using System.Activities.Presentation.Sqm; using System.Activities.Statements; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Runtime; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media.Imaging; using System.Windows.Threading; using Microsoft.Win32; using System.Windows.Documents; public partial class DesignerView { public const string CustomMenuItemsSeparatorCommand = "6F455692-EA19-4ac9-ABEE-57F6DF20A687"; public static readonly DependencyProperty CommandMenuModeProperty = DependencyProperty.RegisterAttached("CommandMenuMode", typeof(CommandMenuMode), typeof(DesignerView), new UIPropertyMetadata(CommandMenuMode.FullCommandMenu)); static readonly DependencyProperty MenuItemOriginProperty = DependencyProperty.RegisterAttached("MenuItemOrigin", typeof(FrameworkElement), typeof(DesignerView)); public static readonly DependencyProperty MenuItemStyleProperty = DependencyProperty.Register("MenuItemStyle", typeof(Style), typeof(DesignerView), new UIPropertyMetadata(null)); public static readonly DependencyProperty MenuSeparatorStyleProperty = DependencyProperty.Register("MenuSeparatorStyle", typeof(Style), typeof(DesignerView), new UIPropertyMetadata(null)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes, Justification = "The class RoutedCommand just has readonly properties, hence the referencetype instance cannot be modified")] public static readonly ICommand GoToParentCommand = new RoutedCommand("GoToParentCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand ExpandCommand = new RoutedCommand("ExpandCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand ExpandAllCommand = new RoutedCommand("ExpandAllCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand CollapseCommand = new RoutedCommand("CollapseCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand CollapseAllCommand = new RoutedCommand("CollapseAllCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand RestoreCommand = new RoutedCommand("RestoreCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand ExpandInPlaceCommand = new RoutedCommand("ExpandInPlaceCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand InsertBreakpointCommand = new RoutedCommand("InsertBreakpointCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand DeleteBreakpointCommand = new RoutedCommand("DeleteBreakpointParentCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand EnableBreakpointCommand = new RoutedCommand("EnableBreakpointCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand DisableBreakpointCommand = new RoutedCommand("DisableBreakpointCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand SaveAsImageCommand = new RoutedCommand("SaveAsImageCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand CopyAsImageCommand = new RoutedCommand("CopyAsImageCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand ZoomInCommand = new RoutedCommand("ZoomInCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand ZoomOutCommand = new RoutedCommand("ZoomOutCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand ToggleArgumentDesignerCommand = new RoutedCommand("ToggleArgumentDesignerCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand ToggleImportsDesignerCommand = new RoutedCommand("ToggleImportsDesignerCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand ToggleVariableDesignerCommand = new RoutedCommand("ToggleVariableDesignerCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand CreateVariableCommand = new RoutedCommand("CreateVariableCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand ToggleMiniMapCommand = new RoutedCommand("ToggleMinimapCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand CycleThroughDesignerCommand = new RoutedCommand("CycleThroughDesignerCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand CreateWorkflowElementCommand = new RoutedCommand("CreateWorkflowElementCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand CreateArgumentCommand = new RoutedCommand("CreateArgumentCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand CommitCommand = new RoutedCommand("CommitCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand FitToScreenCommand = new RoutedCommand("FitToScreenCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand ResetZoomCommand = new RoutedCommand("ResetZoomCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand MoveFocusCommand = new RoutedCommand("MoveFocusCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand ToggleSelectionCommand = new RoutedCommand("ToggleSelectionCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand CutCommand = new RoutedCommand("CutCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand CopyCommand = new RoutedCommand("CopyCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand PasteCommand = new RoutedCommand("PasteCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand SelectAllCommand = new RoutedCommand("SelectAllCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand UndoCommand = new RoutedCommand("UndoCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand RedoCommand = new RoutedCommand("RedoCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand AddAnnotationCommand = new RoutedCommand("AddAnnotationCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand EditAnnotationCommand = new RoutedCommand("EditAnnotationCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand DeleteAnnotationCommand = new RoutedCommand("DeleteAnnotationCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand ShowAllAnnotationCommand = new RoutedCommand("ShowAllAnnotationCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand HideAllAnnotationCommand = new RoutedCommand("HideAllAnnotationCommand", typeof(DesignerView)); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly ICommand DeleteAllAnnotationCommand = new RoutedCommand("DeleteAllAnnotationCommand", typeof(DesignerView)); WorkflowViewElement contextMenuTarget; HashSet ignoreCommands = new HashSet(); Func navigateToParentFunction; Func navigateToChildFunction; Func getBreakpointType; Func isCommandServiceEnabled; Func areBreakpointServicesEnabled; Func isCommandSupported; bool ContainsChordKeyGestures(InputGestureCollection collection) { if (collection == null) { return false; } else { foreach (KeyGesture gesture in collection) { if (gesture.GetType() == typeof(DefaultCommandExtensionCallback.ChordKeyGesture)) { return true; } } return false; } } // Set chordkey gestures owner to this class, so that the chordkey can clear other chord key's mode // after executing. void SetChordKeyGesturesOwner() { foreach (CommandBinding binding in this.CommandBindings) { RoutedCommand cmd = binding.Command as RoutedCommand; foreach (KeyGesture gesture in cmd.InputGestures) { if (gesture.GetType() == typeof(DefaultCommandExtensionCallback.ChordKeyGesture)) { ((DefaultCommandExtensionCallback.ChordKeyGesture)gesture).Owner = this; } } } } // Let the chord command in front, so that the chord command (e.g. Ctrl+E,Ctrl+V) will match // before the (e.g. Ctrl+V). void ReorderCommandBindings() { CommandBindingCollection chordCommandBindings = new CommandBindingCollection(); CommandBindingCollection basicCommandBindings = new CommandBindingCollection(); foreach (CommandBinding binding in this.CommandBindings) { RoutedCommand cmd = binding.Command as RoutedCommand; if (ContainsChordKeyGestures(cmd.InputGestures)) { chordCommandBindings.Add(binding); } else { basicCommandBindings.Add(binding); } } this.CommandBindings.Clear(); this.CommandBindings.AddRange(chordCommandBindings); this.CommandBindings.AddRange(basicCommandBindings); } internal void ResetAllChordKeyGesturesMode() { foreach (CommandBinding binding in this.CommandBindings) { RoutedCommand cmd = binding.Command as RoutedCommand; foreach (KeyGesture gesture in cmd.InputGestures) { if (gesture.GetType() == typeof(DefaultCommandExtensionCallback.ChordKeyGesture)) { ((DefaultCommandExtensionCallback.ChordKeyGesture)gesture).ResetChordMode(); } } } } void InitializeMenuActions() { this.isCommandServiceEnabled = () => { return null != this.Context.Services.GetService(); }; this.areBreakpointServicesEnabled = () => { return null != this.Context.Services.GetService() && this.isCommandServiceEnabled(); }; this.isCommandSupported = commandId => { return this.Context.Services.GetService().IsCommandSupported(commandId); }; this.navigateToParentFunction = (selection, shouldExecute) => { bool result = false; ModelItem target = null; if (null != selection && selection.Equals(this.RootDesigner)) { if (null != selection.ModelItem.Parent) { WorkflowViewService viewService = (WorkflowViewService)this.Context.Services.GetService(); target = selection.ModelItem; do { target = target.Parent; if (target == null) { break; } } while (!viewService.ShouldAppearOnBreadCrumb(target, true)); result = (null != target); } } if (shouldExecute && result) { this.MakeRootDesigner(target); } return result ? Visibility.Visible : Visibility.Collapsed; }; this.navigateToChildFunction = (selection, shouldExecute) => { bool result = false; ModelItem target = null; if (null != selection && !selection.Equals(this.RootDesigner)) { target = selection.ModelItem; WorkflowViewService viewService = (WorkflowViewService)this.Context.Services.GetService(); result = viewService.ShouldAppearOnBreadCrumb(target, true); } if (shouldExecute && result) { this.MakeRootDesigner(target); } return result ? Visibility.Visible : Visibility.Collapsed; }; this.getBreakpointType = selection => { IDesignerDebugView debugView = this.Context.Services.GetService(); var breakpoints = debugView.GetBreakpointLocations(); BreakpointTypes result = BreakpointTypes.None; if (null != breakpoints && null != debugView.SelectedLocation) { breakpoints.TryGetValue(debugView.SelectedLocation, out result); } return result; }; this.ContextMenu.ClipToBounds = false; //workflow command extension callback invoker Action updateCommands = (item) => { //if there are any commands which were ignored - add them back to bindings collections foreach (CommandBinding binding in this.ignoreCommands) { this.CommandBindings.Add(binding); } this.ignoreCommands.Clear(); if (null != item.CommandExtensionCallback) { foreach (CommandBinding cb in this.CommandBindings) { //if callback returns false, it means that user will handle the command, add it to ingore list CommandInfo ci = new CommandInfo(cb.Command); item.CommandExtensionCallback.OnWorkflowCommandLoaded(ci); if (!ci.IsBindingEnabledInDesigner) { this.ignoreCommands.Add(cb); } } //remove all commands from ignore list from bindings - let the commands bubble up to the client foreach (CommandBinding cb in this.ignoreCommands) { this.CommandBindings.Remove(cb); } if (null != this.ContextMenu && this.ContextMenu.HasItems) { foreach (MenuItem menuItem in this.ContextMenu.Items.OfType()) { this.RefreshContextMenu(menuItem); } } } if (item.CommandExtensionCallback.GetType() == typeof(DefaultCommandExtensionCallback)) { this.ReorderCommandBindings(); this.SetChordKeyGesturesOwner(); } }; //subscribe for command extension callback changes; this.context.Items.Subscribe(new SubscribeContextCallback(updateCommands)); //if entry already exists - invoke update; if entry doesn't exist - do nothing. perhaps it will be added later by the user if (this.context.Items.Contains()) { updateCommands(this.context.Items.GetValue()); } } public Style MenuItemStyle { get { return (Style)GetValue(MenuItemStyleProperty); } set { SetValue(MenuItemStyleProperty, value); } } public Style MenuSeparatorStyle { get { return (Style)GetValue(MenuSeparatorStyleProperty); } set { SetValue(MenuSeparatorStyleProperty, value); } } void RefreshContextMenu(MenuItem menuItem) { if (null != menuItem.Command) { //update MenuItem's Command property - if user did update any keyboard shortcuts, then it would be reflected by that change ICommand cmd = menuItem.Command; menuItem.Command = null; menuItem.Command = cmd; } if (menuItem.HasItems) { foreach (MenuItem subItem in menuItem.Items.OfType()) { this.RefreshContextMenu(subItem); } } } protected override void OnContextMenuOpening(ContextMenuEventArgs e) { bool shouldDisplayMenu = false; DependencyObject target = null; DependencyObject source = e.OriginalSource as DependencyObject; if (source is Adorner) { source = ((Adorner)source).AdornedElement; } DependencyObject designerPresenterSource = this.designerPresenter.FindCommonVisualAncestor(source); DependencyObject extensionSurfaceSource = this.wfViewExtensionSurface.FindCommonVisualAncestor(source); //check, who is trying to open context menu - i limit context menu to only elements which are visible inside //core of the workflow designer - no breadcrumb or toolbox if (designerPresenterSource == this.designerPresenter || extensionSurfaceSource == this.wfViewExtensionSurface) { Selection currentSelection = this.Context.Items.GetValue(); if (null != currentSelection && currentSelection.SelectionCount >= 1) { if (currentSelection.SelectionCount == 1) // single selection { //check original source, to see if it prevents displaying context menu if (!CommandMenuMode.Equals(CommandMenuMode.NoCommandMenu, GetCommandMenuMode((DependencyObject)e.OriginalSource))) { if (null != currentSelection.PrimarySelection.View) { target = currentSelection.PrimarySelection.View; shouldDisplayMenu = true; } } } else // multi-selection { // If Multi-selection's context menu was not enabled, don't display menu. shouldDisplayMenu = Context.Services.GetService().MultipleItemsContextMenuEnabled; } } } e.Handled = true; base.OnContextMenuOpening(e); if (shouldDisplayMenu) { // if the context menu is triggered by a context menu key, open context menu at the center of the designer; // else open the context menu at mouse point this.LoadContextMenu((UIElement)target, (e.CursorLeft < 0 && e.CursorTop < 0)); } } void LoadContextMenu(UIElement sender, bool openedByKeyboard) { if (this.ContextMenu == null) { return; } if (!Selection.MultipleObjectsSelected(this.Context) && sender != null && CommandMenuMode.Equals(CommandMenuMode.NoCommandMenu, GetCommandMenuMode(sender))) { return; } //clear context menu state this.UnloadContextMenu(this.ContextMenu); this.contextMenuTarget = sender as WorkflowViewElement; //because of WPF caching behaviour, i have to create new instance of context menu each time it is shown ContextMenu newMenu = new ContextMenu() { ItemContainerStyleSelector = new ContextMenuItemStyleSelector(this) }; newMenu.Loaded += this.OnWorkflowViewContextMenuLoaded; newMenu.Unloaded += this.OnWorkflowViewContextMenuClosed; foreach (var entry in this.ContextMenu.Items.OfType().Reverse()) { this.ContextMenu.Items.Remove(entry); entry.Visibility = Visibility.Visible; newMenu.Items.Insert(0, entry); } this.ContextMenu = newMenu; if (!Selection.MultipleObjectsSelected(this.Context)) { if (null != this.contextMenuTarget && null != this.contextMenuTarget.ContextMenu) { var items = this.contextMenuTarget.ContextMenu.Items.OfType().Reverse(); int insertIndex = this.ContextMenu.Items.Count; foreach (var item in items) { this.contextMenuTarget.ContextMenu.Items.Remove(item); DesignerView.SetMenuItemOrigin(item, this.contextMenuTarget); this.ContextMenu.Items.Insert(insertIndex, item); } } Fx.Assert(this.contextMenuTarget.IsVisible, string.Format(CultureInfo.InvariantCulture, "ContextMenuTarget {0} is not visible", this.contextMenuTarget.GetType())); this.ContextMenu.Placement = openedByKeyboard ? PlacementMode.Relative : PlacementMode.MousePoint; this.ContextMenu.PlacementTarget = this.contextMenuTarget; } else { this.ContextMenu.Placement = openedByKeyboard ? PlacementMode.Center : PlacementMode.MousePoint; this.ContextMenu.PlacementTarget = this; } this.ContextMenu.IsOpen = true; } void UnloadContextMenu(ContextMenu contextMenuToUnload) { if (null != contextMenuToUnload && null != this.contextMenuTarget) { // this should happen only for single selection //select all menu items which do not belong to DesignerView var items = contextMenuToUnload.Items.OfType() .Where(p => DesignerView.GetMenuItemOrigin(p) != null) .Reverse(); foreach (Control item in items) { //remove item from designer menu's location contextMenuToUnload.Items.Remove(item); //and add it back to activity designer DesignerView.GetMenuItemOrigin(item).ContextMenu.Items.Insert(0, item); DesignerView.SetMenuItemOrigin(item, null); } this.contextMenuTarget = null; contextMenuToUnload.Loaded -= this.OnWorkflowViewContextMenuLoaded; contextMenuToUnload.Unloaded -= this.OnWorkflowViewContextMenuClosed; } } void OnWorkflowViewContextMenuLoaded(object sender, RoutedEventArgs e) { this.ContextMenu.MinWidth = 0; this.ContextMenu.MinWidth = this.ContextMenu.DesiredSize.Width; Action contextMenuLoaded = (designer, menuSource) => { System.Diagnostics.Debug.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0} DesignerView.OnWorkflowViewContextMenuLoaded()", DateTime.Now.ToLocalTime())); if (null != menuSource && null != menuSource.ContextMenu) { if (null != designer) // for single selection, designer is the current selected item, we set CommandTarget to current selection { foreach (var item in menuSource.ContextMenu.Items.OfType()) { item.CommandTarget = designer; } designer.NotifyContextMenuLoaded(menuSource.ContextMenu); } else // for multiple selection, designer is null, we set the CommandTarget to DesignerView { foreach (var item in menuSource.ContextMenu.Items.OfType()) { item.CommandTarget = this; } } } }; //if context menu is loaded, deffer notification untill its all menu items have been loaded this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, contextMenuLoaded, this.contextMenuTarget, this); } void OnWorkflowViewContextMenuClosed(object sender, RoutedEventArgs e) { this.UnloadContextMenu((ContextMenu)sender); } void OnMenuItemSeparatorLoaded(object sender, RoutedEventArgs e) { //define a delegate which will handle separator load events Action action = (separator) => { if (null != separator && null != separator.Tag && null != this.ContextMenu) { //check the separator tags - it should contain command names in a tag property string[] commands = separator.Tag.ToString().Split(';'); //check if this separator has a special tag value - CustomMenuItemsSeparatorCommand //it means, it has to be displayed only, when there are custom menu items added to the menu if (commands.Length == 1 && string.Equals(CustomMenuItemsSeparatorCommand, commands[0])) { // The CustomMenuItemsSeparator should be visible only if it has visible child. int index = this.ContextMenu.Items.IndexOf(separator); bool visible = false; for (int i = index + 1; i < this.ContextMenu.Items.Count && !visible; i++) { object contextMenuItem = this.ContextMenu.Items[i]; if (contextMenuItem is MenuItem) { visible = ((MenuItem)contextMenuItem).Visibility == Visibility.Visible; } else { // For safety sake, someone might put other things into the ContextMenu.Items other than MenuItem. visible = true; } } separator.Visibility = visible ? Visibility.Visible : Visibility.Collapsed; } else if (commands.Length != 0) { //set this separator visibility, if associated menu items have either a name or command.name property set to a passed //value, and at least one of the menu item is visible separator.Visibility = this.ContextMenu.Items .OfType() .Where(item => commands.Any( cmd => string.Equals(cmd, null != item.Command && item.Command is RoutedCommand ? ((RoutedCommand)item.Command).Name : item.Name))) .Any(item => item.Visibility == Visibility.Visible) ? Visibility.Visible : Visibility.Collapsed; } } }; //postpone separator show/hide logic until all menu items are loaded and their visibility is calculated this.Dispatcher.BeginInvoke(DispatcherPriority.DataBind, action, sender); } void OnGoToParentMenuLoaded(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; if (null != item) { if (Selection.MultipleObjectsSelected(this.Context)) { item.Visibility = Visibility.Collapsed; e.Handled = true; return; } item.Visibility = this.navigateToParentFunction(this.contextMenuTarget, false); } e.Handled = true; } void OnGoToParentCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } void OnGoToParentCommandExecute(object sender, ExecutedRoutedEventArgs e) { this.navigateToParentFunction(this.contextMenuTarget ?? this.FocusedViewElement, true); e.Handled = true; FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.ViewParent); } void OnCollapseCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { if (this.FocusedViewElement != null) { e.CanExecute = this.FocusedViewElement.ShowExpanded; } e.Handled = true; } void OnCollapseCommandExecute(object sender, ExecutedRoutedEventArgs e) { this.FocusedViewElement.ExpandState = false; if (this.ShouldExpandAll) { this.FocusedViewElement.PinState = true; } e.Handled = true; } void OnCollapseAllCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = !this.ShouldCollapseAll; e.Handled = true; } void OnCollapseAllCommandExecute(object sender, ExecutedRoutedEventArgs e) { this.ShouldCollapseAll = true; e.Handled = true; FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.CollapseAll); } void OnRestoreCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = this.ShouldExpandAll || this.ShouldCollapseAll; e.Handled = true; } void OnRestoreCommandExecute(object sender, ExecutedRoutedEventArgs e) { this.ShouldExpandAll = false; this.ShouldCollapseAll = false; e.Handled = true; FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.Restore); } void OnExpandAllCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = !this.ShouldExpandAll; e.Handled = true; } void OnExpandAllCommandExecute(object sender, ExecutedRoutedEventArgs e) { this.ShouldExpandAll = true; e.Handled = true; FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.ExpandAll); } void OnCollapseExpandInPlaceMenuLoaded(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; if (null != item) { if (Selection.MultipleObjectsSelected(this.Context)) { item.Visibility = Visibility.Collapsed; e.Handled = true; return; } item.Visibility = ExpandButtonVisibilityConverter.GetExpandCollapseButtonVisibility(this.contextMenuTarget); } e.Handled = true; } void OnExpandInPlaceCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { if (this.FocusedViewElement != null) { e.CanExecute = !this.FocusedViewElement.ShowExpanded; } e.Handled = true; } void OnExpandInPlaceCommandExecute(object sender, ExecutedRoutedEventArgs e) { this.FocusedViewElement.ExpandState = true; if (this.ShouldCollapseAll) { this.FocusedViewElement.PinState = true; } e.Handled = true; } void OnExpandMenuLoaded(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; if (null != item) { if (Selection.MultipleObjectsSelected(this.Context)) { item.Visibility = Visibility.Collapsed; e.Handled = true; return; } item.Visibility = this.navigateToChildFunction(this.contextMenuTarget, false); } e.Handled = true; } void OnExpandCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } void OnExpandCommandExecute(object sender, ExecutedRoutedEventArgs e) { this.navigateToChildFunction(this.contextMenuTarget ?? this.FocusedViewElement, true); e.Handled = true; FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.OpenChild); } void OnCopyCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = !this.IsReadOnly && CutCopyPasteHelper.CanCopy(this.Context); e.ContinueRouting = false; e.Handled = true; } void OnCopyCommandExecute(object sender, ExecutedRoutedEventArgs e) { this.Context.Services.GetService().WorkflowDesignerCopyStart(); CutCopyPasteHelper.DoCopy(this.Context); e.Handled = true; this.Context.Services.GetService().WorkflowDesignerCopyEnd(); } void OnPasteCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = !this.IsReadOnly && CutCopyPasteHelper.CanPaste(this.Context); e.ContinueRouting = false; e.Handled = true; } void OnPasteCommandExecute(object sender, ExecutedRoutedEventArgs e) { context.Services.GetService().WorkflowDesignerPasteStart(); WorkflowViewElement sourceElement = e.OriginalSource as WorkflowViewElement; if (sourceElement != null) { Point contextMenuTopLeft = this.ContextMenu.TranslatePoint(new Point(0, 0), sourceElement); CutCopyPasteHelper.DoPaste(this.Context, contextMenuTopLeft, sourceElement); } else { CutCopyPasteHelper.DoPaste(this.Context); } e.Handled = true; context.Services.GetService().WorkflowDesignerPasteEnd(); } void OnCutCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { //handle CutCommand only if Cut reffers to WF designer context menu, otherwise - let target element handle it e.CanExecute = !this.IsReadOnly && CutCopyPasteHelper.CanCut(this.Context); e.ContinueRouting = false; e.Handled = true; } void OnCutCommandExecute(object sender, ExecutedRoutedEventArgs e) { CutCopyPasteHelper.DoCut(this.Context); e.Handled = true; } void OnDeleteCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { //query DeleteHelper if delete can occur - i.e. there is no root element selected e.CanExecute = !this.IsReadOnly && DeleteHelper.CanDelete(this.Context); e.ContinueRouting = false; e.Handled = true; } void OnDeleteCommandExecute(object sender, ExecutedRoutedEventArgs e) { DeleteHelper.Delete(this.Context); e.Handled = true; } void OnPropertiesMenuLoaded(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; if (null != item) { item.Visibility = this.isCommandServiceEnabled() && this.isCommandSupported(CommandValues.ShowProperties) ? Visibility.Visible : Visibility.Collapsed; } e.Handled = true; } void OnShowPropertiesCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } void OnShowPropertiesCommandExecute(object sender, ExecutedRoutedEventArgs e) { //execute ShowProperties command ExecuteCommand(CommandValues.ShowProperties); e.Handled = true; } void OnBreakpointMenuLoaded(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; if (null != item) { if (Selection.MultipleObjectsSelected(this.Context)) { item.Visibility = Visibility.Collapsed; e.Handled = true; return; } item.Visibility = this.areBreakpointServicesEnabled() && (this.contextMenuTarget is ActivityDesigner) ? Visibility.Visible : Visibility.Collapsed; } e.Handled = true; } void OnInsertBreakpointMenuLoaded(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; if (null != item) { item.Visibility = this.areBreakpointServicesEnabled() && this.isCommandSupported(CommandValues.InsertBreakpoint) && this.getBreakpointType(this.FocusedViewElement) == BreakpointTypes.None ? Visibility.Visible : Visibility.Collapsed; } e.Handled = true; } void OnInsertBreakpointCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = this.FocusedViewElement != null && this.FocusedViewElement.ModelItem != null && AllowBreakpointAttribute.IsBreakpointAllowed(this.FocusedViewElement.ModelItem.ItemType); e.Handled = true; } void OnInsertBreakpointCommandExecute(object sender, ExecutedRoutedEventArgs e) { ExecuteCommand(CommandValues.InsertBreakpoint); e.Handled = true; } void OnDeleteBreakpointMenuLoaded(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; if (null != item) { item.Visibility = this.areBreakpointServicesEnabled() && this.isCommandSupported(CommandValues.DeleteBreakpoint) && this.getBreakpointType(this.FocusedViewElement) != BreakpointTypes.None ? Visibility.Visible : Visibility.Collapsed; } e.Handled = true; } void OnDeleteBreakpointCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = this.FocusedViewElement != null && this.FocusedViewElement.ModelItem != null && AllowBreakpointAttribute.IsBreakpointAllowed(this.FocusedViewElement.ModelItem.ItemType); e.Handled = true; } void OnDeleteBreakpointCommandExecute(object sender, ExecutedRoutedEventArgs e) { ExecuteCommand(CommandValues.DeleteBreakpoint); e.Handled = true; } void OnEnableBreakpointMenuLoaded(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; if (null != item) { Visibility visibility = Visibility.Collapsed; if (this.areBreakpointServicesEnabled() && this.isCommandSupported(CommandValues.EnableBreakpoint)) { BreakpointTypes breakpoint = this.getBreakpointType(this.FocusedViewElement); visibility = ((breakpoint & BreakpointTypes.Bounded) != 0 && (breakpoint & BreakpointTypes.Enabled) == 0) ? Visibility.Visible : Visibility.Collapsed; } item.Visibility = visibility; } e.Handled = true; } void OnEnableBreakpointCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } void OnEnableBreakpointCommandExecute(object sender, ExecutedRoutedEventArgs e) { ExecuteCommand(CommandValues.EnableBreakpoint); e.Handled = true; } void OnDisableBreakpointMenuLoaded(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; if (null != item) { Visibility visibility = Visibility.Collapsed; if (this.areBreakpointServicesEnabled() && this.isCommandSupported(CommandValues.DisableBreakpoint)) { BreakpointTypes breakpoint = this.getBreakpointType(this.FocusedViewElement); visibility = ((breakpoint & BreakpointTypes.Bounded) != 0 && (breakpoint & BreakpointTypes.Enabled) != 0) ? Visibility.Visible : Visibility.Collapsed; } item.Visibility = visibility; } e.Handled = true; } void OnDisableBreakpointCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } void OnDisableBreakpointCommandExecute(object sender, ExecutedRoutedEventArgs e) { ExecuteCommand(CommandValues.DisableBreakpoint); e.Handled = true; } void OnUndoCommandExecute(object sender, ExecutedRoutedEventArgs e) { this.Context.Services.GetService().Undo(); e.Handled = true; } void OnUndoCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } void OnRedoCommandExecute(object sender, ExecutedRoutedEventArgs e) { this.Context.Services.GetService().Redo(); e.Handled = true; } void OnRedoCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } void OnCommitCommandExecute(object sender, ExecutedRoutedEventArgs e) { TextBox textBox = e.OriginalSource as TextBox; if (textBox != null) { BindingExpression textBinding = textBox.GetBindingExpression(TextBox.TextProperty); if (textBinding != null) { textBinding.UpdateSource(); e.Handled = true; } } } void OnCommitCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } void OnSelectAllCommandExecute(object sender, ExecutedRoutedEventArgs e) { this.SelectAll(); e.Handled = true; } void OnCopyAsImageMenuLoaded(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; if (null != item) { if (Selection.MultipleObjectsSelected(this.Context)) { item.Visibility = Visibility.Collapsed; } else { item.Visibility = Visibility.Visible; } } e.Handled = true; } void OnCopyAsImageCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = null != this.RootDesigner; e.Handled = true; } void OnCopyAsImageCommandExecuted(object sender, ExecutedRoutedEventArgs e) { VirtualizedContainerService virtualizingContainerService = this.Context.Services.GetService(); virtualizingContainerService.BeginPopulateAll((Action)(() => { BitmapSource screenShot = this.CreateScreenShot(); try { RetriableClipboard.SetImage(screenShot); } catch (COMException err) { ErrorReporting.ShowErrorMessage(err.Message); } e.Handled = true; FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.CopyAsImage); })); } void OnSaveAsImageMenuLoaded(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; if (null != item) { if (Selection.MultipleObjectsSelected(this.Context)) { item.Visibility = Visibility.Collapsed; } else { item.Visibility = Visibility.Visible; } } e.Handled = true; } void OnSaveAsImageCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = null != this.RootDesigner; e.Handled = true; } [SuppressMessage(FxCop.Category.Design, FxCop.Rule.DoNotCatchGeneralExceptionTypes, Justification = "Catching all exceptions to avoid VS Crash")] [SuppressMessage("Reliability", "Reliability108", Justification = "Catching all exceptions to avoid VS Crash")] void OnSaveAsImageCommandExecuted(object sender, ExecutedRoutedEventArgs e) { ModelItem rootItem = ((WorkflowViewElement)this.RootDesigner).ModelItem; PropertyDescriptor displayNameProperty = TypeDescriptor.GetProperties(rootItem)["DisplayName"]; // default to root item's typename string name = rootItem.ItemType.Name; // if there is a display name property on root use that as the file name. if (displayNameProperty != null && displayNameProperty.PropertyType.Equals(typeof(string))) { name = (string)displayNameProperty.GetValue(rootItem); } SaveFileDialog dlg = new SaveFileDialog() { Filter = @"JPG|*.jpg|PNG|*.png|GIF|*.gif|XPS|*.xps", FileName = name }; bool? showDialogResult = false; try { showDialogResult = dlg.ShowDialog(); } catch (ArgumentException) { dlg.FileName = null; showDialogResult = dlg.ShowDialog(); } if (true == showDialogResult && !string.IsNullOrEmpty(dlg.FileName)) { VirtualizedContainerService virtualizingContainerService = this.Context.Services.GetService(); virtualizingContainerService.BeginPopulateAll((Action)(() => { try { switch (dlg.FilterIndex) { case 1: this.CreateImageFile(dlg.FileName, typeof(JpegBitmapEncoder)); break; case 2: this.CreateImageFile(dlg.FileName, typeof(PngBitmapEncoder)); break; case 3: this.CreateImageFile(dlg.FileName, typeof(GifBitmapEncoder)); break; case 4: this.CreateXPSDocument(dlg.FileName); break; default: throw FxTrace.Exception.AsError(new InvalidOperationException("Not supported file type")); } } catch (Exception err) { MessageBox.Show(err.Message, err.GetType().Name, MessageBoxButton.OK, MessageBoxImage.Error); } })); } e.Handled = true; FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.SaveAsImage); } void OnZoomInCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = this.zoomToTicksConverter.CanZoomIn(); e.Handled = true; } void OnZoomInCommandExecuted(object sender, ExecutedRoutedEventArgs e) { this.zoomToTicksConverter.ZoomIn(); e.Handled = true; } void OnMoveFocusCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } void OnMoveFocusCommandExecuted(object sender, ExecutedRoutedEventArgs e) { UIElement focusedElement = Keyboard.FocusedElement as UIElement; if (focusedElement != null) { this.IsMultipleSelectionMode = true; focusedElement.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next)); this.IsMultipleSelectionMode = false; } e.Handled = true; } void OnToggleSelectionCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } void OnToggleSelectionCommandExecuted(object sender, ExecutedRoutedEventArgs e) { WorkflowViewElement focusedElement = Keyboard.FocusedElement as WorkflowViewElement; if (focusedElement != null && focusedElement.ModelItem != null) { Selection.Toggle(this.Context, focusedElement.ModelItem); } e.Handled = true; } void OnZoomOutCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = this.zoomToTicksConverter.CanZoomOut(); e.Handled = true; } void OnZoomOutCommandExecuted(object sender, ExecutedRoutedEventArgs e) { this.zoomToTicksConverter.ZoomOut(); e.Handled = true; } void OnToggleArgumentDesignerCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = ((this.shellBarItemVisibility & ShellBarItemVisibility.Arguments) == ShellBarItemVisibility.Arguments) && null != this.ActivitySchema && typeof(ActivityBuilder).IsAssignableFrom(this.ActivitySchema.ItemType); e.Handled = true; } void OnToggleArgumentDesignerCommandExecuted(object sender, ExecutedRoutedEventArgs e) { this.buttonArguments1.IsChecked = !this.buttonArguments1.IsChecked; this.FocusShellBarDesigner(this.arguments1); e.Handled = true; } void OnToggleVariableDesignerCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = ((this.shellBarItemVisibility & ShellBarItemVisibility.Variables) == ShellBarItemVisibility.Variables); e.Handled = true; } void OnToggleVariableDesignerCommandExecuted(object sender, ExecutedRoutedEventArgs e) { this.buttonVariables1.IsChecked = !this.buttonVariables1.IsChecked; this.FocusShellBarDesigner(this.variables1); e.Handled = true; } void OnToggleImportsDesignerCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { if ((this.shellBarItemVisibility & ShellBarItemVisibility.Imports) == ShellBarItemVisibility.Imports) { e.CanExecute = true; } else { e.CanExecute = false; } e.Handled = true; } void OnToggleImportsDesignerCommandExecuted(object sender, ExecutedRoutedEventArgs e) { this.buttonImports1.IsChecked = !this.buttonImports1.IsChecked; this.FocusShellBarDesigner(this.imports1); e.Handled = true; } void FocusShellBarDesigner(UIElement designer) { // Focus the Argument/Variable/Imports designer when it is turn on. if (designer.IsEnabled) { if (!designer.IsKeyboardFocusWithin) { Keyboard.Focus(designer); } } // Focus an activity designer when the Argument/Variable/Imports designer is turned off and has keyboard focus within. else if (designer.IsKeyboardFocusWithin) { Keyboard.Focus(this.GetDesignerToFocus()); } } void OnCreateVariableMenuLoaded(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; if (null != item) { if (Selection.MultipleObjectsSelected(this.Context)) { item.Visibility = Visibility.Collapsed; return; } item.Visibility = variablesStatusBarItem.Visibility; } } void OnCreateVariableCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = ((this.shellBarItemVisibility & ShellBarItemVisibility.Variables) == ShellBarItemVisibility.Variables) && !this.IsReadOnly && null != this.variables1.CurrentVariableScope; e.Handled = true; } void OnCreateVariableCommandExecuted(object sender, ExecutedRoutedEventArgs e) { this.buttonVariables1.IsChecked = true; this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => { this.variables1.CreateNewVariableWrapper(); })); e.Handled = true; } void OnCreateArgumentCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = ((this.shellBarItemVisibility & ShellBarItemVisibility.Arguments) == ShellBarItemVisibility.Arguments) && !this.IsReadOnly && null != this.arguments1.ActivitySchema; e.Handled = true; } void OnCreateArgumentCommandExecuted(object sender, ExecutedRoutedEventArgs e) { this.buttonArguments1.IsChecked = true; this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => { this.arguments1.CreateNewArgumentWrapper(); })); e.Handled = true; } void OnToggleMiniMapCommandExecute(object sender, CanExecuteRoutedEventArgs e) { e.Handled = e.CanExecute = true; } void OnToggleMiniMapCommandExecuted(object sender, ExecutedRoutedEventArgs e) { e.Handled = true; this.miniMap.IsEnabled = !this.miniMap.IsEnabled; } void OnCycleThroughDesignerCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = e.Handled = true; } UIElement GetDesignerToFocus() { Selection selection = this.Context.Items.GetValue(); if (selection.SelectionCount != 0 && selection.PrimarySelection.View != null) { return (UIElement)selection.PrimarySelection.View; } else { return this.RootDesigner; } } void OnCycleThroughDesignerCommandExecuted(object sender, ExecutedRoutedEventArgs e) { UIElement toFocus = this.breadCrumbListBox; if (this.BreadCrumbBarLayout.IsKeyboardFocusWithin) { toFocus = this.GetDesignerToFocus(); } else if (this.scrollViewer.IsKeyboardFocusWithin) { if ((bool)this.buttonVariables1.IsChecked) { toFocus = this.variables1; } else if ((bool)this.buttonArguments1.IsChecked) { toFocus = this.arguments1; } else if ((bool)this.buttonImports1.IsChecked) { toFocus = this.imports1; } else { toFocus = this.buttonVariables1; } } else if ((bool)this.buttonVariables1.IsChecked && this.variables1.IsKeyboardFocusWithin) { toFocus = this.buttonVariables1; } else if ((bool)this.buttonArguments1.IsChecked && this.arguments1.IsKeyboardFocusWithin) { toFocus = this.buttonVariables1; } else if ((bool)this.buttonImports1.IsChecked && this.imports1.IsKeyboardFocusWithin) { toFocus = this.buttonVariables1; } this.Dispatcher.BeginInvoke(new Action((target) => { System.Diagnostics.Debug.WriteLine(target.GetType().Name + " " + target.GetHashCode()); Keyboard.Focus(target); }), DispatcherPriority.ApplicationIdle, toFocus); e.Handled = true; } void OnCreateWorkflowElementCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { string typeName = null; // e.Parameter is IDictionary when the designer is hosted // inside Visual Studio. It is IDataObject otherwise. if (e.Parameter is IDictionary) { IDictionary context = e.Parameter as IDictionary; context.TryGetValue("TypeName", out typeName); } else { IDataObject context = e.Parameter as IDataObject; if (context != null) { typeName = context.GetData(DragDropHelper.WorkflowItemTypeNameFormat) as string; } } bool precondition = !this.IsReadOnly && !string.IsNullOrWhiteSpace(typeName); if (precondition) { Type activityType = Type.GetType(typeName, false); if (null != activityType) { Selection selection = this.Context.Items.GetValue(); if (selection.SelectionCount == 1 && selection.PrimarySelection.View is WorkflowViewElement) { WorkflowViewElement viewElement = (WorkflowViewElement)selection.PrimarySelection.View; ICompositeView container = viewElement.ActiveCompositeView; if (null != container) { List itemsToPaste = new List(1); Type factoryType; if (activityType.TryGetActivityTemplateFactory(out factoryType)) { itemsToPaste.Add(factoryType); } else { itemsToPaste.Add(activityType); } e.CanExecute = container.CanPasteItems(itemsToPaste); } } } } e.Handled = true; } void OnCreateWorkflowElementCommandExecuted(object sender, ExecutedRoutedEventArgs e) { Selection selection = this.Context.Items.GetValue(); Fx.Assert(selection.SelectionCount == 1, "selection.SelectionCount should be 1."); Fx.Assert(selection.PrimarySelection.View is WorkflowViewElement, "selection.PrimarySelection.View should be WorkflowViewElement type."); WorkflowViewElement viewElement = (WorkflowViewElement)selection.PrimarySelection.View; Type activityType = null; IDataObject dataObject = null; // e.Parameter is IDictionary when the designer is hosted // inside Visual Studio. It is IDataObject otherwise. if (e.Parameter is IDictionary) { IDictionary context = e.Parameter as IDictionary; activityType = Type.GetType(context["TypeName"]); // For the VisualStudio 11 hosted designer case data object corresponding to the toolbox item is passed in // through AppDomain level data by EditorPane.IToolboxUser.ItemPicked method. string dataObjectKey = typeof(System.Runtime.InteropServices.ComTypes.IDataObject).FullName; object data = AppDomain.CurrentDomain.GetData(dataObjectKey); if (data is IntPtr) { IntPtr dataObjectPointer = (IntPtr)data; dataObject = new DataObject((System.Runtime.InteropServices.ComTypes.IDataObject)Marshal.GetObjectForIUnknown(dataObjectPointer)); Marshal.Release(dataObjectPointer); AppDomain.CurrentDomain.SetData(dataObjectKey, null); } } else { dataObject = e.Parameter as IDataObject; activityType = Type.GetType((string)dataObject.GetData(DragDropHelper.WorkflowItemTypeNameFormat)); } object instance = DragDropHelper.GetDroppedObjectInstance(viewElement, this.Context, activityType, dataObject); if (instance != null) { List itemsToPaste = new List(1); List metaData = new List(1); if (instance is FlowNode) { List flowchartMetaData = new List(1); flowchartMetaData.Add(instance as FlowNode); metaData.Add(flowchartMetaData); } else { itemsToPaste.Add(instance); } viewElement.ActiveCompositeView.OnItemsPasted(itemsToPaste, metaData, new Point(), null); } e.Handled = true; } void OnFitToScreenCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = (null != this.zoomToTicksConverter); } void OnFitToScreenCommandExecute(object sender, ExecutedRoutedEventArgs e) { this.zoomToTicksConverter.FitToScreen(); e.Handled = true; FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.FitToScreen); } void OnResetZoomCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = (null != this.zoomToTicksConverter); } void OnResetZoomCommandExecute(object sender, ExecutedRoutedEventArgs e) { this.zoomToTicksConverter.ResetZoom(); e.Handled = true; FeatureUsageCounter.ReportUsage(sqmService, WorkflowDesignerFeatureId.ResetZoom); } void OnZoomPickerUndoRedoCommandPreviewCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = false; e.Handled = true; } void OnAnnotationsMenuLoaded(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; if (this.context.Services.GetService().AnnotationEnabled == true) { if (!Selection.MultipleObjectsSelected(this.Context)) { item.Visibility = Visibility.Visible; e.Handled = true; return; } } item.Visibility = Visibility.Collapsed; e.Handled = true; } void OnAddAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { ContextMenuUtilities.OnAddAnnotationCommandCanExecute(e, this.Context); } void OnAddAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e) { ContextMenuUtilities.OnAddAnnotationCommandExecuted(e, this.Context.Items.GetValue().PrimarySelection); } void OnEditAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { // call the same method as delete annotation command ContextMenuUtilities.OnDeleteAnnotationCommandCanExecute(e, this.Context); } void OnEditAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e) { ContextMenuUtilities.OnEditAnnotationCommandExecuted(e, this.Context.Items.GetValue().PrimarySelection); } void OnDeleteAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { ContextMenuUtilities.OnDeleteAnnotationCommandCanExecute(e, this.Context); } void OnDeleteAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e) { ContextMenuUtilities.OnDeleteAnnotationCommandExecuted(e, this.Context.Items.GetValue().PrimarySelection); } void OnShowAllAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { if (this.context.Services.GetService().AnnotationEnabled != true) { e.CanExecute = false; return; } e.CanExecute = true; e.Handled = true; } void OnShowAllAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e) { ModelTreeManager modelTreeManager = this.Context.Services.GetService(); AnnotationAdornerService annotationService = this.Context.Services.GetService(); ViewStateService viewStateService = this.Context.Services.GetService(); foreach (ModelItem item in ModelTreeManager.Find(modelTreeManager.Root, new Predicate(ModelItemExtensions.HasAnnotation), false)) { viewStateService.StoreViewState(item, Annotation.IsAnnotationDockedViewStateName, true); } e.Handled = true; } void OnHideAllAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { if (this.context.Services.GetService().AnnotationEnabled != true) { e.CanExecute = false; return; } e.CanExecute = true; e.Handled = true; } void OnHideAllAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e) { ModelTreeManager modelTreeManager = this.Context.Services.GetService(); AnnotationAdornerService annotationService = this.Context.Services.GetService(); ViewStateService viewStateService = this.Context.Services.GetService(); foreach (ModelItem item in ModelTreeManager.Find(modelTreeManager.Root, new Predicate(ModelItemExtensions.HasAnnotation), false)) { viewStateService.StoreViewState(item, Annotation.IsAnnotationDockedViewStateName, false); } e.Handled = true; } void OnDeleteAllAnnotationCommandCanExecute(object sender, CanExecuteRoutedEventArgs e) { ContextMenuUtilities.OnDeleteAllAnnotationCommandCanExecute(e, this.Context); } void OnDeleteAllAnnotationCommandExecuted(object sender, ExecutedRoutedEventArgs e) { ModelTreeManager modelTreeManager = this.Context.Services.GetService(); AnnotationAdornerService annotationService = this.Context.Services.GetService(); ViewStateService viewStateService = this.Context.Services.GetService(); MessageBoxResult result = MessageBox.Show(SR.DeleteAllAnnotationMessage, SR.DeleteAnnotationTitle, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No); if (result != MessageBoxResult.Yes) { e.Handled = true; return; } ModelEditingScope editingScope = null; bool isModified = false; try { foreach (ModelItem item in ModelTreeManager.Find(modelTreeManager.Root, new Predicate(ModelItemExtensions.HasAnnotation), false)) { isModified = true; if (editingScope == null) { editingScope = item.BeginEdit(SR.DeleteAllAnnotationsDescription); } item.Properties[Annotation.AnnotationTextPropertyName].ClearValue(); viewStateService.StoreViewStateWithUndo(item, Annotation.IsAnnotationDockedViewStateName, null); } if (isModified) { modelTreeManager.AddToCurrentEditingScope(new NotifyArgumentVariableAnnotationTextChanged() { ArgumentDesigner = this.arguments1, VariableDesigner = this.variables1, }); } } finally { if (editingScope != null) { editingScope.Complete(); } } e.Handled = true; } void ExecuteCommand(int command) { IDesignerDebugView debuggerService = this.Context.Services.GetService(); ICommandService commandService = this.Context.Services.GetService(); if (null != commandService) { //setup parameters var commandParameters = (Dictionary)null; if (null != debuggerService && (command == CommandValues.InsertBreakpoint || command == CommandValues.DeleteBreakpoint || command == CommandValues.EnableBreakpoint || command == CommandValues.DisableBreakpoint)) { commandParameters = new Dictionary(); if (command == CommandValues.InsertBreakpoint) { commandParameters.Add(typeof(BreakpointTypes).Name, BreakpointTypes.Bounded); } commandParameters.Add(typeof(SourceLocation).Name, debuggerService.SelectedLocation); } //execute command commandService.ExecuteCommand(command, commandParameters); } } static FrameworkElement GetMenuItemOrigin(DependencyObject obj) { return (FrameworkElement)obj.GetValue(MenuItemOriginProperty); } static void SetMenuItemOrigin(DependencyObject obj, FrameworkElement value) { obj.SetValue(MenuItemOriginProperty, value); } public static CommandMenuMode GetCommandMenuMode(DependencyObject obj) { return (CommandMenuMode)obj.GetValue(CommandMenuModeProperty); } public static void SetCommandMenuMode(DependencyObject obj, CommandMenuMode value) { obj.SetValue(CommandMenuModeProperty, value); } sealed class ContextMenuItemStyleSelector : StyleSelector { DesignerView owner; public ContextMenuItemStyleSelector(DesignerView owner) { this.owner = owner; } public override Style SelectStyle(object item, DependencyObject container) { if (item is MenuItem && null != this.owner.MenuItemStyle) { ((MenuItem)item).ItemContainerStyleSelector = this; return this.owner.MenuItemStyle; } else if (item is Separator && null != this.owner.MenuSeparatorStyle) { return this.owner.MenuSeparatorStyle; } return base.SelectStyle(item, container); } } } [Fx.Tag.XamlVisible(false)] public sealed class CommandMenuMode { [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes, Justification = "The class being an empty class, the readonly mutable referencetypes cannot be modified")] public static readonly CommandMenuMode NoCommandMenu = new CommandMenuMode(); [SuppressMessage(FxCop.Category.Security, FxCop.Rule.DoNotDeclareReadOnlyMutableReferenceTypes)] public static readonly CommandMenuMode FullCommandMenu = new CommandMenuMode(); private CommandMenuMode() { } } }