Skip to content

Commit a3316ca

Browse files
committed
WIP
1 parent 7c00793 commit a3316ca

File tree

4 files changed

+188
-83
lines changed

4 files changed

+188
-83
lines changed

Terminal.Gui/ViewBase/View.Command.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,9 @@ private void SetupCommands ()
164164

165165
if (SuperView is { })
166166
{
167-
Logging.Debug ($"{Title} ({ctx?.Source?.Title}) - Invoking Accept on SuperView ({SuperView.Title}/{SuperView.Id})...");
167+
Logging.Debug ($"{Title} ({ctx?.Source?.Title}) - Invoking {ctx!.Command} on SuperView ({SuperView.Title}/{SuperView.Id})...");
168168

169-
return SuperView?.InvokeCommand (Command.Accept, ctx);
169+
return SuperView?.InvokeCommand (ctx!.Command, ctx);
170170
}
171171
}
172172

@@ -280,6 +280,18 @@ public interface IDefaultAcceptView
280280
// If the event is not canceled by the virtual method, raise the event to notify any external subscribers.
281281
Activating?.Invoke (this, args);
282282

283+
// Activate is a special case where if the event is not canceled, the event is
284+
// - propagated up the SuperView hierarchy.
285+
if (!args.Handled)
286+
{
287+
if (SuperView is { })
288+
{
289+
Logging.Debug ($"{Title} ({ctx?.Source?.Title}) - Invoking {ctx!.Command} on SuperView ({SuperView.Title}/{SuperView.Id})...");
290+
291+
return SuperView?.InvokeCommand (ctx!.Command, ctx);
292+
}
293+
}
294+
283295
return Activating is null ? null : args.Handled;
284296
}
285297

Terminal.Gui/Views/Shortcut.cs

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -238,11 +238,24 @@ protected override void OnSubViewLayout (LayoutEventArgs e)
238238
private void AddCommands ()
239239
{
240240
// Accept (Enter key) -
241-
AddCommand (Command.Accept, DispatchCommand);
241+
//AddCommand (Command.Accept, DispatchCommand);
242242
// Hotkey -
243-
AddCommand (Command.HotKey, DispatchCommand);
243+
//AddCommand (Command.HotKey, DispatchCommand);
244244
// Activate (Space key or click) -
245-
AddCommand (Command.Activate, DispatchCommand);
245+
// AddCommand (Command.Activate, DispatchCommand);
246+
}
247+
248+
/// <inheritdoc />
249+
protected override bool OnHandlingHotKey (CommandEventArgs args)
250+
{
251+
return base.OnHandlingHotKey (args);
252+
}
253+
254+
/// <inheritdoc />
255+
protected override bool OnActivating (CommandEventArgs args)
256+
{
257+
258+
return base.OnActivating (args);
246259
}
247260

248261
/// <summary>
@@ -261,20 +274,20 @@ private void AddCommands ()
261274

262275
Logging.Debug ($"{Title} ({commandContext?.Source?.Title}) Command: {commandContext?.Command}");
263276

264-
if (keyCommandContext?.Binding.Data != this)
265-
{
266-
// TODO: Optimize this to only do this if CommandView is custom (non View)
267-
// Invoke Activate on the CommandView to cause it to change state if it wants to
268-
// If this causes CommandView to raise Accept, we eat it
269-
keyCommandContext = keyCommandContext!.Value with { Binding = keyCommandContext.Value.Binding with { Data = this } };
277+
//if (keyCommandContext?.Binding.Data != this)
278+
//{
279+
// // TODO: Optimize this to only do this if CommandView is custom (non View)
280+
// // Invoke Activate on the CommandView to cause it to change state if it wants to
281+
// // If this causes CommandView to raise Accept, we eat it
282+
// keyCommandContext = keyCommandContext!.Value with { Binding = keyCommandContext.Value.Binding with { Data = this } };
270283

271-
Logging.Debug ($"{Title} ({commandContext?.Source?.Title}) - Invoking Activate on CommandView ({CommandView.GetType ().Name}).");
284+
// Logging.Debug ($"{Title} ({commandContext?.Source?.Title}) - Invoking Activate on CommandView ({CommandView.GetType ().Name}).");
272285

273-
if (CommandView.InvokeCommand (Command.Activate, keyCommandContext) is true)
274-
{
275-
return true;
276-
}
277-
}
286+
// if (CommandView.InvokeCommand (Command.Activate, keyCommandContext) is true)
287+
// {
288+
// return true;
289+
// }
290+
//}
278291

279292
Logging.Debug ($"{Title} ({commandContext?.Source?.Title}) - RaiseActivating ...");
280293

@@ -292,17 +305,17 @@ private void AddCommands ()
292305

293306
var cancel = false;
294307

295-
if (commandContext is { Source: null })
296-
{
297-
commandContext.Source = this;
298-
}
299-
Logging.Debug ($"{Title} ({commandContext?.Source?.Title}) - Calling RaiseAccepting...");
300-
cancel = RaiseAccepting (commandContext) is true;
308+
//if (commandContext is { Source: null })
309+
//{
310+
// commandContext.Source = this;
311+
//}
312+
//Logging.Debug ($"{Title} ({commandContext?.Source?.Title}) - Calling RaiseAccepting...");
313+
//cancel = RaiseAccepting (commandContext) is true;
301314

302-
if (cancel)
303-
{
304-
return true;
305-
}
315+
//if (cancel)
316+
//{
317+
// return true;
318+
//}
306319

307320
if (Action is { })
308321
{
@@ -398,7 +411,7 @@ public View CommandView
398411

399412
// The default behavior is for CommandView to not get focus. I
400413
// If you want it to get focus, you need to set it.
401-
// _commandView.CanFocus = false;
414+
_commandView.CanFocus = false;
402415

403416
_commandView.HotKeyChanged += (s, e) =>
404417
{
@@ -416,7 +429,7 @@ public View CommandView
416429
_commandView.Activating += CommandViewOnActivating;
417430
_commandView.Accepting += CommandViewOnAccepted;
418431

419-
//ShowHide ();
432+
ShowHide ();
420433
UpdateKeyBindings (Key.Empty);
421434

422435
return;

Tests/UnitTests/Views/ShortcutTests.cs

Lines changed: 112 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -246,71 +246,75 @@ public void MouseClick_CheckBox_CommandView_Raises_Shortcut_Accepted_Selected_Co
246246
}
247247

248248
[Theory]
249-
[InlineData (true, KeyCode.A, 1, 1)]
250-
[InlineData (true, KeyCode.C, 1, 1)]
251-
[InlineData (true, KeyCode.C | KeyCode.AltMask, 1, 1)]
252-
[InlineData (true, KeyCode.Enter, 1, 1)]
253-
[InlineData (true, KeyCode.Space, 1, 1)]
254-
[InlineData (true, KeyCode.F1, 0, 0)]
255-
[InlineData (false, KeyCode.A, 1, 1)]
256-
[InlineData (false, KeyCode.C, 1, 1)]
257-
[InlineData (false, KeyCode.C | KeyCode.AltMask, 1, 1)]
258-
[InlineData (false, KeyCode.Enter, 0, 0)]
259-
[InlineData (false, KeyCode.Space, 0, 0)]
260-
[InlineData (false, KeyCode.F1, 0, 0)]
261-
public void KeyDown_Raises_Accepted_Selected (bool canFocus, KeyCode key, int expectedAccept, int expectedSelect)
249+
[InlineData (true, KeyCode.A, 1, 0)] // CanFocus: Shortcut.key should activate and not Accept
250+
[InlineData (true, KeyCode.C, 1, 0)] // CanFocus: CommandView.HotKey should activate and not Accept
251+
[InlineData (true, KeyCode.C | KeyCode.AltMask, 1, 0)] // CanFocus: CommandView.HotKey should activate and not Accept
252+
[InlineData (true, KeyCode.Enter, 1, 1)] // CanFocus: Enter should Activate and Accept
253+
[InlineData (true, KeyCode.Space, 1, 0)] // CanFocus: Space should Activate and not Accept
254+
[InlineData (true, KeyCode.F1, 0, 0)] // CanFocus: Other key should do nothing
255+
[InlineData (false, KeyCode.A, 1, 0)] // !CanFocus: Shortcut.key should Activate and not Accept
256+
[InlineData (false, KeyCode.C, 1, 0)] // !CanFocus: CommandView.HotKey should Activate and not Accept
257+
[InlineData (false, KeyCode.C | KeyCode.AltMask, 1, 0)] // !CanFocus: CommandView.HotKey should Activate and not Accept
258+
[InlineData (false, KeyCode.Enter, 0, 0)] // !CanFocus: Enter should do nothing
259+
[InlineData (false, KeyCode.Space, 0, 0)] // !CanFocus: Space should do nothing
260+
[InlineData (false, KeyCode.F1, 0, 0)] // !CanFocus: Other key should do nothing
261+
public void KeyDown_Raises_Accepting_And_Activating_Correctly (bool canFocus, KeyCode key, int expectedActivating, int expectedAccepting)
262262
{
263263
Application.Top = new ();
264264

265265
var shortcut = new Shortcut
266266
{
267267
Key = Key.A,
268-
Text = "0",
269268
Title = "_C",
270269
CanFocus = canFocus
271270
};
272271
Application.Top.Add (shortcut);
273272
shortcut.SetFocus ();
274273

275274
Assert.Equal (canFocus, shortcut.HasFocus);
275+
// By default CommandView gets CanFocus set to false, so the CB will never have focus
276+
Assert.Equal (shortcut, Application.Top.MostFocused);
276277

277-
var accepted = 0;
278-
shortcut.Accepting += (s, e) => accepted++;
278+
var accepting = 0;
279+
shortcut.Accepting += (s, e) =>
280+
{
281+
accepting++;
282+
e.Handled = true;
283+
};
279284

280-
var selected = 0;
281-
shortcut.Activating += (s, e) => selected++;
285+
var activating = 0;
286+
shortcut.Activating += (s, e) => activating++;
282287

283288
Application.RaiseKeyDownEvent (key);
284-
285-
Assert.Equal (expectedAccept, accepted);
286-
Assert.Equal (expectedSelect, selected);
287-
288289
Application.Top.Dispose ();
289290
Application.ResetState (true);
291+
292+
Assert.Equal (expectedActivating, activating);
293+
Assert.Equal (expectedAccepting, accepting);
290294
}
291295

292296

293297
[Theory]
294-
[InlineData (true, KeyCode.A, 1, 1)]
295-
[InlineData (true, KeyCode.C, 1, 1)]
296-
[InlineData (true, KeyCode.C | KeyCode.AltMask, 1, 1)]
297-
[InlineData (true, KeyCode.Enter, 1, 1)]
298-
[InlineData (true, KeyCode.Space, 0, 1)]
299-
[InlineData (true, KeyCode.F1, 0, 0)]
300-
[InlineData (false, KeyCode.A, 1, 1)]
301-
[InlineData (false, KeyCode.C, 1, 1)]
302-
[InlineData (false, KeyCode.C | KeyCode.AltMask, 1, 1)]
303-
[InlineData (false, KeyCode.Enter, 0, 0)]
304-
[InlineData (false, KeyCode.Space, 0, 0)]
305-
[InlineData (false, KeyCode.F1, 0, 0)]
306-
public void KeyDown_CheckBox_Raises_Accepted_Activated (bool canFocus, KeyCode key, int expectedAccept, int expectedActivate)
298+
[InlineData (true, KeyCode.A, 1, 0)] // CanFocus: Shortcut.key should activate and not Accept
299+
[InlineData (true, KeyCode.C, 1, 0)] // CanFocus: CommandView.HotKey should activate and not Accept
300+
[InlineData (true, KeyCode.C | KeyCode.AltMask, 1, 0)] // CanFocus: CommandView.HotKey should activate and not Accept
301+
[InlineData (true, KeyCode.Enter, 1, 1)] // CanFocus: Enter should Activate and Accept
302+
[InlineData (true, KeyCode.Space, 1, 0)] // CanFocus: Space should Activate and not Accept
303+
[InlineData (true, KeyCode.F1, 0, 0)] // CanFocus: Other key should do nothing
304+
[InlineData (false, KeyCode.A, 1, 0)] // !CanFocus: Shortcut.key should Activate and not Accept
305+
[InlineData (false, KeyCode.C, 1, 0)] // !CanFocus: CommandView.HotKey should Activate and not Accept
306+
[InlineData (false, KeyCode.C | KeyCode.AltMask, 1, 0)] // !CanFocus: CommandView.HotKey should Activate and not Accept
307+
[InlineData (false, KeyCode.Enter, 0, 0)] // !CanFocus: Enter should do nothing
308+
[InlineData (false, KeyCode.Space, 0, 0)] // !CanFocus: Space should do nothing
309+
[InlineData (false, KeyCode.F1, 0, 0)] // !CanFocus: Other key should do nothing
310+
public void With_NotCanFocusCheckBox_CommandView_KeyDown_Raises_Accepting_And_Activating_Correctly (bool canFocus, KeyCode key, int expectedActivating, int expectedAccepting)
307311
{
308312
Application.Top = new ();
309313

314+
// Shortcut with Key = Key.A and CommandView Hotkey = Key.C
310315
var shortcut = new Shortcut
311316
{
312317
Key = Key.A,
313-
Text = "0",
314318
CommandView = new CheckBox ()
315319
{
316320
Title = "_C",
@@ -324,23 +328,79 @@ public void KeyDown_CheckBox_Raises_Accepted_Activated (bool canFocus, KeyCode k
324328
// By default CommandView gets CanFocus set to false, so the CB will never have focus
325329
Assert.Equal (shortcut, Application.Top.MostFocused);
326330

327-
var accepted = 0;
331+
var accepting = 0;
328332
shortcut.Accepting += (s, e) =>
329333
{
330-
accepted++;
334+
accepting++;
331335
e.Handled = true;
332336
};
333337

334-
var activated = 0;
335-
shortcut.Activating += (s, e) => activated++;
338+
var activating = 0;
339+
shortcut.Activating += (s, e) => activating++;
336340

337341
Application.RaiseKeyDownEvent (key);
342+
Application.Top.Dispose ();
343+
Application.ResetState (true);
338344

339-
Assert.Equal (expectedAccept, accepted);
340-
Assert.Equal (expectedActivate, activated);
345+
Assert.Equal (expectedActivating, activating);
346+
Assert.Equal (expectedAccepting, accepting);
347+
348+
}
349+
350+
351+
[Theory]
352+
[InlineData (true, KeyCode.A, 1, 0)] // CanFocus: Shortcut.key should activate and not Accept
353+
[InlineData (true, KeyCode.C, 1, 0)] // CanFocus: CommandView.HotKey should activate and not Accept
354+
[InlineData (true, KeyCode.C | KeyCode.AltMask, 1, 0)] // CanFocus: CommandView.HotKey should activate and not Accept
355+
[InlineData (true, KeyCode.Enter, 1, 1)] // CanFocus: Enter should Activate and Accept
356+
[InlineData (true, KeyCode.Space, 1, 0)] // CanFocus: Space should Activate and not Accept
357+
[InlineData (true, KeyCode.F1, 0, 0)] // CanFocus: Other key should do nothing
358+
[InlineData (false, KeyCode.A, 1, 0)] // !CanFocus: Shortcut.key should Activate and not Accept
359+
[InlineData (false, KeyCode.C, 1, 0)] // !CanFocus: CommandView.HotKey should Activate and not Accept
360+
[InlineData (false, KeyCode.C | KeyCode.AltMask, 1, 0)] // !CanFocus: CommandView.HotKey should Activate and not Accept
361+
[InlineData (false, KeyCode.Enter, 0, 0)] // !CanFocus: Enter should do nothing
362+
[InlineData (false, KeyCode.Space, 0, 0)] // !CanFocus: Space should do nothing
363+
[InlineData (false, KeyCode.F1, 0, 0)] // !CanFocus: Other key should do nothing
364+
public void With_CanFocusCheckBox_CommandView_KeyDown_Raises_Accepting_And_Activating_Correctly (bool canFocus, KeyCode key, int expectedActivating, int expectedAccepting)
365+
{
366+
Application.Top = new ();
367+
368+
// Shortcut with Key = Key.A and CommandView Hotkey = Key.C
369+
var shortcut = new Shortcut
370+
{
371+
Key = Key.A,
372+
HelpText = "0",
373+
CommandView = new CheckBox ()
374+
{
375+
Title = "_C",
376+
},
377+
CanFocus = canFocus
378+
};
379+
shortcut.CommandView.CanFocus = true;
380+
381+
Application.Top.Add (shortcut);
382+
shortcut.SetFocus ();
383+
384+
Assert.Equal (canFocus, shortcut.HasFocus);
385+
Assert.Equal (shortcut.CommandView, Application.Top.MostFocused);
386+
387+
var accepting = 0;
388+
shortcut.Accepting += (s, e) =>
389+
{
390+
accepting++;
391+
e.Handled = true;
392+
};
341393

394+
var activating = 0;
395+
shortcut.Activating += (s, e) => activating++;
396+
397+
Application.RaiseKeyDownEvent (key);
342398
Application.Top.Dispose ();
343399
Application.ResetState (true);
400+
401+
Assert.Equal (expectedActivating, activating);
402+
Assert.Equal (expectedAccepting, accepting);
403+
344404
}
345405
[Theory]
346406
[InlineData (KeyCode.A, 1)]
@@ -349,29 +409,32 @@ public void KeyDown_CheckBox_Raises_Accepted_Activated (bool canFocus, KeyCode k
349409
[InlineData (KeyCode.Enter, 1)]
350410
[InlineData (KeyCode.Space, 1)]
351411
[InlineData (KeyCode.F1, 0)]
352-
public void KeyDown_App_Scope_Invokes_Accept (KeyCode key, int expectedAccept)
412+
public void KeyDown_App_Scope_Invokes_Activating (KeyCode key, int expectedActivating)
353413
{
354414
Application.Top = new ();
355415

356416
var shortcut = new Shortcut
357417
{
358418
Key = Key.A,
359419
BindKeyToApplication = true,
360-
Text = "0",
361420
Title = "_C"
362421
};
363422
Application.Top.Add (shortcut);
364423
Application.Top.SetFocus ();
365424

366-
var accepted = 0;
367-
shortcut.Accepting += (s, e) => accepted++;
368-
369-
Application.RaiseKeyDownEvent (key);
425+
var activating = 0;
426+
shortcut.Activating += (s, e) => activating++;
370427

371-
Assert.Equal (expectedAccept, accepted);
428+
var accepting = 0;
429+
shortcut.Accepting += (s, e) => accepting++;
372430

431+
Application.RaiseKeyDownEvent (key);
373432
Application.Top.Dispose ();
374433
Application.ResetState (true);
434+
435+
Assert.Equal (expectedActivating, activating);
436+
Assert.Equal (0, accepting);
437+
375438
}
376439

377440
[Theory]

0 commit comments

Comments
 (0)