1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //----------------------------------------------------------------
5 namespace System.Activities.Presentation
7 using System.Activities.Presentation.View;
8 using System.Activities.Presentation.Hosting;
9 using System.Collections.Generic;
11 using System.Windows.Input;
12 using System.Globalization;
15 //DefaultCommandExtensionCallback - provides default key input gestures for most of the
16 //WF commands. user can either implmeent his own class or override this one and provide special
17 //handling for specific commands
18 class DefaultCommandExtensionCallback : IWorkflowCommandExtensionCallback
20 Dictionary<ICommand, List<KeyGesture>> defaultGestures = new Dictionary<ICommand, List<KeyGesture>>();
22 public DefaultCommandExtensionCallback()
24 defaultGestures.Add(DesignerView.GoToParentCommand,
25 new List<KeyGesture> { new ChordKeyGesture(Key.E, Key.P) });
26 defaultGestures.Add(DesignerView.ExpandInPlaceCommand,
27 new List<KeyGesture> { new ChordKeyGesture(Key.E, Key.E) });
28 defaultGestures.Add(DesignerView.ExpandAllCommand,
29 new List<KeyGesture> { new ChordKeyGesture(Key.E, Key.X) });
30 defaultGestures.Add(DesignerView.CollapseCommand,
31 new List<KeyGesture> { new ChordKeyGesture(Key.E, Key.C) });
32 defaultGestures.Add(DesignerView.CollapseAllCommand,
33 new List<KeyGesture> { new ChordKeyGesture(Key.E, Key.Y) });
34 defaultGestures.Add(DesignerView.RestoreCommand,
35 new List<KeyGesture> { new ChordKeyGesture(Key.E, Key.R) });
36 defaultGestures.Add(DesignerView.ZoomInCommand,
37 new List<KeyGesture> {
38 new KeyGesture(Key.OemPlus, ModifierKeys.Control, "Ctrl +"),
39 new KeyGesture(Key.Add, ModifierKeys.Control) });
40 defaultGestures.Add(DesignerView.ZoomOutCommand,
41 new List<KeyGesture> {
42 new KeyGesture(Key.OemMinus, ModifierKeys.Control, "Ctrl -"),
43 new KeyGesture(Key.Subtract, ModifierKeys.Control) });
44 defaultGestures.Add(DesignerView.ToggleArgumentDesignerCommand,
45 new List<KeyGesture> { new ChordKeyGesture(Key.E, Key.A) });
46 defaultGestures.Add(DesignerView.ToggleVariableDesignerCommand,
47 new List<KeyGesture> { new ChordKeyGesture(Key.E, Key.V) });
48 defaultGestures.Add(DesignerView.ToggleImportsDesignerCommand,
49 new List<KeyGesture> { new ChordKeyGesture(Key.E, Key.I) });
50 defaultGestures.Add(DesignerView.ToggleMiniMapCommand,
51 new List<KeyGesture> { new ChordKeyGesture(Key.E, Key.O) });
52 defaultGestures.Add(DesignerView.CreateVariableCommand,
53 new List<KeyGesture> { new ChordKeyGesture(Key.E, Key.N) });
54 defaultGestures.Add(DesignerView.CycleThroughDesignerCommand,
55 new List<KeyGesture> { new KeyGesture(Key.F6, ModifierKeys.Control | ModifierKeys.Alt, "Ctrl + Alt + F6") });
56 defaultGestures.Add(ExpressionTextBox.CompleteWordCommand,
57 new List<KeyGesture> { new KeyGesture(Key.Right, ModifierKeys.Alt, "Alt + Right Arrow") });
58 defaultGestures.Add(ExpressionTextBox.GlobalIntellisenseCommand,
59 new List<KeyGesture> { new KeyGesture(Key.J, ModifierKeys.Control, "Ctrl + J") });
60 defaultGestures.Add(ExpressionTextBox.ParameterInfoCommand,
61 new List<KeyGesture> { new ChordKeyGesture(Key.K, Key.P) });
62 defaultGestures.Add(ExpressionTextBox.QuickInfoCommand,
63 new List<KeyGesture> { new ChordKeyGesture(Key.K, Key.I) });
64 defaultGestures.Add(DesignerView.MoveFocusCommand,
65 new List<KeyGesture> { new ChordKeyGesture(Key.E, Key.M) });
66 defaultGestures.Add(DesignerView.ToggleSelectionCommand,
67 new List<KeyGesture> { new ChordKeyGesture(Key.E, Key.S) });
68 defaultGestures.Add(DesignerView.CutCommand,
69 new List<KeyGesture> { new KeyGesture(Key.X, ModifierKeys.Control) });
70 defaultGestures.Add(DesignerView.CopyCommand,
71 new List<KeyGesture> { new KeyGesture(Key.C, ModifierKeys.Control) });
72 defaultGestures.Add(DesignerView.PasteCommand,
73 new List<KeyGesture> { new KeyGesture(Key.V, ModifierKeys.Control) });
74 defaultGestures.Add(DesignerView.SelectAllCommand,
75 new List<KeyGesture> { new KeyGesture(Key.A, ModifierKeys.Control) });
76 defaultGestures.Add(DesignerView.UndoCommand,
77 new List<KeyGesture> { new KeyGesture(Key.Z, ModifierKeys.Control) });
78 defaultGestures.Add(DesignerView.RedoCommand,
79 new List<KeyGesture> { new KeyGesture(Key.Y, ModifierKeys.Control) });
80 defaultGestures.Add(ExpressionTextBox.IncreaseFilterLevelCommand,
81 new List<KeyGesture> { new KeyGesture(Key.Decimal, ModifierKeys.Alt) });
82 defaultGestures.Add(ExpressionTextBox.DecreaseFilterLevelCommand,
83 new List<KeyGesture> { new KeyGesture(Key.OemComma, ModifierKeys.Alt) });
88 public void OnWorkflowCommandLoaded(CommandInfo commandInfo)
90 if (commandInfo == null)
92 throw FxTrace.Exception.AsError(new ArgumentNullException("commandInfo"));
94 RoutedCommand cmd = commandInfo.Command as RoutedCommand;
97 List<KeyGesture> gestures = null;
98 if (defaultGestures.TryGetValue(cmd, out gestures))
100 gestures.ForEach((gesture) =>
102 if (!this.ContainsGesture(cmd, gesture))
104 cmd.InputGestures.Add(gesture);
111 protected bool ContainsGesture(RoutedCommand cmd, KeyGesture gesture)
113 return cmd.InputGestures.OfType<KeyGesture>().Any(p => string.Equals(p.DisplayString, gesture.DisplayString));
117 //ChordKeyGesture - class derived from KeyGesture - provides simple state machine implementation
118 //to handle chord keyboard navigation. Invoke when ChordKey or ChordKey + Ctrl is pressed after
119 //entering chord mode
120 internal sealed class ChordKeyGesture : KeyGesture
122 bool isInKeyChordMode = false;
125 private WeakReference ownerReference;
127 internal DesignerView Owner
131 if (this.ownerReference != null)
133 return this.ownerReference.Target as DesignerView;
142 this.ownerReference = null;
146 this.ownerReference = new WeakReference(value);
151 public ChordKeyGesture(Key key, Key chordKey) :
152 base(key, ModifierKeys.Control, string.Format(CultureInfo.InvariantCulture, "Ctrl+{0}, {1}", key, chordKey))
154 this.chordKey = chordKey;
156 public void ResetChordMode()
158 this.isInKeyChordMode = false;
160 public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
163 KeyEventArgs keyArgs = inputEventArgs as KeyEventArgs;
164 //lookup only for keyboard events
167 //by default - check if we are entering double key navigation
168 if (!this.isInKeyChordMode)
170 //call base implementation to match Ctrl + actual key
171 if (base.Matches(targetElement, keyArgs))
173 this.isInKeyChordMode = true;
176 //if we are waiting for chord key
177 else if (keyArgs.Key == this.chordKey && (Keyboard.Modifiers == ModifierKeys.None || Keyboard.Modifiers == ModifierKeys.Control))
179 //ok - we found a match, reset state to default
180 System.Diagnostics.Debug.WriteLine(this.DisplayString);
182 // reset all the chord key after this command
183 if (this.Owner != null)
185 this.Owner.ResetAllChordKeyGesturesMode();
188 //no, second key didn't match the chord
189 //if ctrl is pressed, just let it stay in chord mode
190 else if (Keyboard.Modifiers != ModifierKeys.Control)
192 this.isInKeyChordMode = false;
195 //any other input event resets state to default
198 this.isInKeyChordMode = false;