@@ -3,94 +3,19 @@ namespace Terminal.Gui;
3
3
4
4
public static partial class Application // Keyboard handling
5
5
{
6
- private static Key _nextTabGroupKey = Key . F6 ; // Resources/config.json overrrides
7
- private static Key _nextTabKey = Key . Tab ; // Resources/config.json overrrides
8
- private static Key _prevTabGroupKey = Key . F6 . WithShift ; // Resources/config.json overrrides
9
- private static Key _prevTabKey = Key . Tab . WithShift ; // Resources/config.json overrrides
10
- private static Key _quitKey = Key . Esc ; // Resources/config.json overrrides
11
- private static Key _arrangeKey = Key . F5 . WithCtrl ; // Resources/config.json overrrides
12
-
13
- static Application ( ) { AddApplicationKeyBindings ( ) ; }
14
-
15
- /// <summary>Gets the key bindings for this view.</summary>
16
- public static KeyBindings KeyBindings { get ; internal set ; } = new ( ) ;
17
-
18
- /// <summary>
19
- /// Event fired when the user presses a key. Fired by <see cref="OnKeyDown"/>.
20
- /// <para>
21
- /// Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
22
- /// additional processing.
23
- /// </para>
24
- /// </summary>
25
- /// <remarks>
26
- /// All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
27
- /// <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
28
- /// <para>Fired after <see cref="KeyDown"/> and before <see cref="KeyUp"/>.</para>
29
- /// </remarks>
30
- public static event EventHandler < Key > ? KeyDown ;
31
-
32
6
/// <summary>
33
- /// Event fired when the user releases a key. Fired by <see cref="OnKeyUp"/>.
34
- /// <para>
35
- /// Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
36
- /// additional processing.
37
- /// </para>
38
- /// </summary>
39
- /// <remarks>
40
- /// All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
41
- /// <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
42
- /// <para>Fired after <see cref="KeyDown"/>.</para>
43
- /// </remarks>
44
- public static event EventHandler < Key > ? KeyUp ;
45
-
46
- /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
47
- [ SerializableConfigurationProperty ( Scope = typeof ( SettingsScope ) ) ]
48
- public static Key NextTabGroupKey
49
- {
50
- get => _nextTabGroupKey ;
51
- set
52
- {
53
- if ( _nextTabGroupKey != value )
54
- {
55
- ReplaceKey ( _nextTabGroupKey , value ) ;
56
- _nextTabGroupKey = value ;
57
- }
58
- }
59
- }
60
-
61
- /// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
62
- [ SerializableConfigurationProperty ( Scope = typeof ( SettingsScope ) ) ]
63
- public static Key NextTabKey
64
- {
65
- get => _nextTabKey ;
66
- set
67
- {
68
- if ( _nextTabKey != value )
69
- {
70
- ReplaceKey ( _nextTabKey , value ) ;
71
- _nextTabKey = value ;
72
- }
73
- }
74
- }
75
-
76
- /// <summary>
77
- /// Called by the <see cref="ConsoleDriver"/> when the user presses a key. Fires the <see cref="KeyDown"/> event
78
- /// then calls <see cref="View.NewKeyDownEvent"/> on all top level views. Called after <see cref="OnKeyDown"/> and
79
- /// before <see cref="OnKeyUp"/>.
7
+ /// Called when the user presses a key (by the <see cref="ConsoleDriver"/>). Raises the cancelable
8
+ /// <see cref="KeyDown"/> event, then calls <see cref="View.NewKeyDownEvent"/> on all top level views, and finally
9
+ /// if the key was not handled, invokes any Application-scoped <see cref="KeyBindings"/>.
80
10
/// </summary>
81
11
/// <remarks>Can be used to simulate key press events.</remarks>
82
- /// <param name="keyEvent "></param>
12
+ /// <param name="key "></param>
83
13
/// <returns><see langword="true"/> if the key was handled.</returns>
84
- public static bool OnKeyDown ( Key keyEvent )
14
+ public static bool RaiseKeyDownEvent ( Key key )
85
15
{
86
- //if (!IsInitialized)
87
- //{
88
- // return true;
89
- //}
16
+ KeyDown ? . Invoke ( null , key ) ;
90
17
91
- KeyDown ? . Invoke ( null , keyEvent ) ;
92
-
93
- if ( keyEvent . Handled )
18
+ if ( key . Handled )
94
19
{
95
20
return true ;
96
21
}
@@ -99,7 +24,7 @@ public static bool OnKeyDown (Key keyEvent)
99
24
{
100
25
foreach ( Toplevel topLevel in TopLevels . ToList ( ) )
101
26
{
102
- if ( topLevel . NewKeyDownEvent ( keyEvent ) )
27
+ if ( topLevel . NewKeyDownEvent ( key ) )
103
28
{
104
29
return true ;
105
30
}
@@ -112,15 +37,15 @@ public static bool OnKeyDown (Key keyEvent)
112
37
}
113
38
else
114
39
{
115
- if ( Top . NewKeyDownEvent ( keyEvent ) )
40
+ if ( Top . NewKeyDownEvent ( key ) )
116
41
{
117
42
return true ;
118
43
}
119
44
}
120
45
121
46
// Invoke any Application-scoped KeyBindings.
122
47
// The first view that handles the key will stop the loop.
123
- foreach ( KeyValuePair < Key , KeyBinding > binding in KeyBindings . Bindings . Where ( b => b . Key == keyEvent . KeyCode ) )
48
+ foreach ( KeyValuePair < Key , KeyBinding > binding in KeyBindings . Bindings . Where ( b => b . Key == key . KeyCode ) )
124
49
{
125
50
if ( binding . Value . BoundView is { } )
126
51
{
@@ -133,7 +58,7 @@ public static bool OnKeyDown (Key keyEvent)
133
58
}
134
59
else
135
60
{
136
- if ( ! KeyBindings . TryGet ( keyEvent , KeyBindingScope . Application , out KeyBinding appBinding ) )
61
+ if ( ! KeyBindings . TryGet ( key , KeyBindingScope . Application , out KeyBinding appBinding ) )
137
62
{
138
63
continue ;
139
64
}
@@ -142,67 +67,74 @@ public static bool OnKeyDown (Key keyEvent)
142
67
143
68
foreach ( Command command in appBinding . Commands )
144
69
{
145
- toReturn = InvokeCommand ( command , keyEvent , appBinding ) ;
70
+ toReturn = InvokeCommand ( command , key , appBinding ) ;
146
71
}
147
72
148
73
return toReturn ?? true ;
149
74
}
150
75
}
151
76
152
77
return false ;
153
- }
154
78
155
- /// <summary>
156
- /// INTENRAL method to invoke one of the commands in <see cref="CommandImplementations"/>
157
- /// </summary>
158
- /// <param name="command"></param>
159
- /// <param name="keyEvent"></param>
160
- /// <param name="appBinding"></param>
161
- /// <returns></returns>
162
- /// <exception cref="NotSupportedException"></exception>
163
- private static bool ? InvokeCommand ( Command command , Key keyEvent , KeyBinding appBinding )
164
- {
165
- if ( ! CommandImplementations ! . ContainsKey ( command ) )
79
+ static bool ? InvokeCommand ( Command command , Key key , KeyBinding appBinding )
166
80
{
167
- throw new NotSupportedException (
168
- @$ "A KeyBinding was set up for the command { command } ({ keyEvent } ) but that command is not supported by Application."
169
- ) ;
170
- }
81
+ if ( ! CommandImplementations ! . ContainsKey ( command ) )
82
+ {
83
+ throw new NotSupportedException (
84
+ @$ "A KeyBinding was set up for the command { command } ({ key } ) but that command is not supported by Application."
85
+ ) ;
86
+ }
171
87
172
- if ( CommandImplementations . TryGetValue ( command , out View . CommandImplementation ? implementation ) )
173
- {
174
- var context = new CommandContext ( command , keyEvent , appBinding ) ; // Create the context here
88
+ if ( CommandImplementations . TryGetValue ( command , out View . CommandImplementation ? implementation ) )
89
+ {
90
+ var context = new CommandContext ( command , key , appBinding ) ; // Create the context here
175
91
176
- return implementation ( context ) ;
177
- }
92
+ return implementation ( context ) ;
93
+ }
178
94
179
- return false ;
95
+ return false ;
96
+ }
180
97
}
181
98
182
99
/// <summary>
183
- /// Called by the <see cref="ConsoleDriver"/> when the user releases a key. Fires the <see cref="KeyUp"/> event
184
- /// then calls <see cref="View.NewKeyUpEvent"/> on all top level views. Called after <see cref="OnKeyDown"/>.
100
+ /// Raised when the user presses a key.
101
+ /// <para>
102
+ /// Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
103
+ /// additional processing.
104
+ /// </para>
185
105
/// </summary>
186
- /// <remarks>Can be used to simulate key press events.</remarks>
187
- /// <param name="a"></param>
106
+ /// <remarks>
107
+ /// All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
108
+ /// <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
109
+ /// <para>Fired after <see cref="KeyDown"/> and before <see cref="KeyUp"/>.</para>
110
+ /// </remarks>
111
+ public static event EventHandler < Key > ? KeyDown ;
112
+
113
+ /// <summary>
114
+ /// Called when the user releases a key (by the <see cref="ConsoleDriver"/>). Raises the cancelable <see cref="KeyUp"/>
115
+ /// event
116
+ /// then calls <see cref="View.NewKeyUpEvent"/> on all top level views. Called after <see cref="RaiseKeyDownEvent"/>.
117
+ /// </summary>
118
+ /// <remarks>Can be used to simulate key release events.</remarks>
119
+ /// <param name="key"></param>
188
120
/// <returns><see langword="true"/> if the key was handled.</returns>
189
- public static bool OnKeyUp ( Key a )
121
+ public static bool RaiseKeyUpEvent ( Key key )
190
122
{
191
123
if ( ! IsInitialized )
192
124
{
193
125
return true ;
194
126
}
195
127
196
- KeyUp ? . Invoke ( null , a ) ;
128
+ KeyUp ? . Invoke ( null , key ) ;
197
129
198
- if ( a . Handled )
130
+ if ( key . Handled )
199
131
{
200
132
return true ;
201
133
}
202
134
203
135
foreach ( Toplevel topLevel in TopLevels . ToList ( ) )
204
136
{
205
- if ( topLevel . NewKeyUpEvent ( a ) )
137
+ if ( topLevel . NewKeyUpEvent ( key ) )
206
138
{
207
139
return true ;
208
140
}
@@ -216,65 +148,12 @@ public static bool OnKeyUp (Key a)
216
148
return false ;
217
149
}
218
150
219
- /// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
220
- [ SerializableConfigurationProperty ( Scope = typeof ( SettingsScope ) ) ]
221
- public static Key PrevTabGroupKey
222
- {
223
- get => _prevTabGroupKey ;
224
- set
225
- {
226
- if ( _prevTabGroupKey != value )
227
- {
228
- ReplaceKey ( _prevTabGroupKey , value ) ;
229
- _prevTabGroupKey = value ;
230
- }
231
- }
232
- }
233
-
234
- /// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
235
- [ SerializableConfigurationProperty ( Scope = typeof ( SettingsScope ) ) ]
236
- public static Key PrevTabKey
237
- {
238
- get => _prevTabKey ;
239
- set
240
- {
241
- if ( _prevTabKey != value )
242
- {
243
- ReplaceKey ( _prevTabKey , value ) ;
244
- _prevTabKey = value ;
245
- }
246
- }
247
- }
151
+ #region Application-scoped KeyBindings
248
152
249
- /// <summary>Gets or sets the key to quit the application.</summary>
250
- [ SerializableConfigurationProperty ( Scope = typeof ( SettingsScope ) ) ]
251
- public static Key QuitKey
252
- {
253
- get => _quitKey ;
254
- set
255
- {
256
- if ( _quitKey != value )
257
- {
258
- ReplaceKey ( _quitKey , value ) ;
259
- _quitKey = value ;
260
- }
261
- }
262
- }
153
+ static Application ( ) { AddApplicationKeyBindings ( ) ; }
263
154
264
- /// <summary>Gets or sets the key to activate arranging views using the keyboard.</summary>
265
- [ SerializableConfigurationProperty ( Scope = typeof ( SettingsScope ) ) ]
266
- public static Key ArrangeKey
267
- {
268
- get => _arrangeKey ;
269
- set
270
- {
271
- if ( _arrangeKey != value )
272
- {
273
- ReplaceKey ( _arrangeKey , value ) ;
274
- _arrangeKey = value ;
275
- }
276
- }
277
- }
155
+ /// <summary>Gets the Application-scoped key bindings.</summary>
156
+ public static KeyBindings KeyBindings { get ; internal set ; } = new ( ) ;
278
157
279
158
internal static void AddApplicationKeyBindings ( )
280
159
{
@@ -286,6 +165,7 @@ internal static void AddApplicationKeyBindings ()
286
165
static ( ) =>
287
166
{
288
167
RequestStop ( ) ;
168
+
289
169
return true ;
290
170
}
291
171
) ;
@@ -348,7 +228,7 @@ internal static void AddApplicationKeyBindings ()
348
228
349
229
KeyBindings . Clear ( ) ;
350
230
351
- // Resources/config.json overrrides
231
+ // Resources/config.json overrides
352
232
NextTabKey = Key . Tab ;
353
233
PrevTabKey = Key . Tab . WithShift ;
354
234
NextTabGroupKey = Key . F6 ;
@@ -397,6 +277,26 @@ internal static List<KeyBinding> GetViewKeyBindings ()
397
277
. ToList ( ) ;
398
278
}
399
279
280
+ private static void ReplaceKey ( Key oldKey , Key newKey )
281
+ {
282
+ if ( KeyBindings . Bindings . Count == 0 )
283
+ {
284
+ return ;
285
+ }
286
+
287
+ if ( newKey == Key . Empty )
288
+ {
289
+ KeyBindings . Remove ( oldKey ) ;
290
+ }
291
+ else
292
+ {
293
+ KeyBindings . ReplaceKey ( oldKey , newKey ) ;
294
+ }
295
+ }
296
+
297
+
298
+ #endregion Application-scoped KeyBindings
299
+
400
300
/// <summary>
401
301
/// <para>
402
302
/// Sets the function that will be invoked for a <see cref="Command"/>.
@@ -420,20 +320,4 @@ internal static List<KeyBinding> GetViewKeyBindings ()
420
320
/// </summary>
421
321
private static Dictionary < Command , View . CommandImplementation > ? CommandImplementations { get ; set ; }
422
322
423
- private static void ReplaceKey ( Key oldKey , Key newKey )
424
- {
425
- if ( KeyBindings . Bindings . Count == 0 )
426
- {
427
- return ;
428
- }
429
-
430
- if ( newKey == Key . Empty )
431
- {
432
- KeyBindings . Remove ( oldKey ) ;
433
- }
434
- else
435
- {
436
- KeyBindings . ReplaceKey ( oldKey , newKey ) ;
437
- }
438
- }
439
323
}
0 commit comments