d0d055fcea8459cb8d97dc1d99a8975790fdd285
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / DefaultCommandExtensionCallback.cs
1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------
4
5 namespace System.Activities.Presentation
6 {
7     using System.Activities.Presentation.View;
8     using System.Activities.Presentation.Hosting;
9     using System.Collections.Generic;
10     using System.Linq;
11     using System.Windows.Input;
12     using System.Globalization;
13     using System.Runtime;
14
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
19     {
20         Dictionary<ICommand, List<KeyGesture>> defaultGestures = new Dictionary<ICommand, List<KeyGesture>>();
21
22         public DefaultCommandExtensionCallback()
23         {
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) });
84
85
86         }
87
88         public void OnWorkflowCommandLoaded(CommandInfo commandInfo)
89         {
90             if (commandInfo == null)
91             {
92                 throw FxTrace.Exception.AsError(new ArgumentNullException("commandInfo"));
93             }
94             RoutedCommand cmd = commandInfo.Command as RoutedCommand;
95             if (cmd != null)
96             {
97                 List<KeyGesture> gestures = null;
98                 if (defaultGestures.TryGetValue(cmd, out gestures))
99                 {
100                     gestures.ForEach((gesture) =>
101                     {
102                         if (!this.ContainsGesture(cmd, gesture))
103                         {
104                             cmd.InputGestures.Add(gesture);
105                         }
106                     });
107                 }
108             }
109         }
110
111         protected bool ContainsGesture(RoutedCommand cmd, KeyGesture gesture)
112         {
113             return cmd.InputGestures.OfType<KeyGesture>().Any(p => string.Equals(p.DisplayString, gesture.DisplayString));
114         }
115
116
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
121         {
122             bool isInKeyChordMode = false;
123             Key chordKey;
124
125             private WeakReference ownerReference;
126
127             internal DesignerView Owner
128             {
129                 get
130                 {
131                     if (this.ownerReference != null)
132                     {
133                         return this.ownerReference.Target as DesignerView;
134                     }
135
136                     return null;
137                 }
138                 set
139                 {
140                     if (value == null)
141                     {
142                         this.ownerReference = null;
143                     }
144                     else
145                     {
146                         this.ownerReference = new WeakReference(value);
147                     }
148                 }
149             }
150
151             public ChordKeyGesture(Key key, Key chordKey) :
152                 base(key, ModifierKeys.Control, string.Format(CultureInfo.InvariantCulture, "Ctrl+{0}, {1}", key, chordKey))
153             {
154                 this.chordKey = chordKey;
155             }
156             public void ResetChordMode()
157             {
158                 this.isInKeyChordMode = false;
159             }
160             public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
161             {
162                 bool result = false;
163                 KeyEventArgs keyArgs = inputEventArgs as KeyEventArgs;
164                 //lookup only for keyboard events
165                 if (null != keyArgs)
166                 {
167                     //by default - check if we are entering double key navigation
168                     if (!this.isInKeyChordMode)
169                     {
170                         //call base implementation to match Ctrl + actual key
171                         if (base.Matches(targetElement, keyArgs))
172                         {
173                             this.isInKeyChordMode = true;
174                         }
175                     }
176                     //if we are waiting for chord key
177                     else if (keyArgs.Key == this.chordKey && (Keyboard.Modifiers == ModifierKeys.None || Keyboard.Modifiers == ModifierKeys.Control))
178                     {
179                         //ok - we found a match, reset state to default
180                         System.Diagnostics.Debug.WriteLine(this.DisplayString);
181                         result = true;
182                         // reset all the chord key after this command
183                         if (this.Owner != null)
184                         {
185                             this.Owner.ResetAllChordKeyGesturesMode();
186                         }
187                     }
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)
191                     {
192                         this.isInKeyChordMode = false;
193                     }
194                 }
195                 //any other input event resets state to default
196                 else
197                 {
198                     this.isInKeyChordMode = false;
199                 }
200                 return result;
201             }
202         }
203
204     }
205 }