Implemented ShortCut in the View class within the UICatalog example.

This commit is contained in:
BDisp
2020-10-26 12:23:11 +00:00
parent 01d4b4f55f
commit b1cc2f8035
7 changed files with 115 additions and 36 deletions

View File

@@ -29,6 +29,32 @@ namespace Terminal.Gui {
/// </summary>
public virtual ustring ShortCutTag => GetShortCutTag (shortCut);
/// <summary>
/// The action to run if the <see cref="ShortCut"/> is defined.
/// </summary>
public virtual Action ShortCutAction { get; set; }
/// <summary>
/// Gets the key with all the keys modifiers, especially the shift key that sometimes have to be injected later.
/// </summary>
/// <param name="kb">The <see cref="KeyEvent"/> to check.</param>
/// <returns>The <see cref="KeyEvent.Key"/> with all the keys modifiers.</returns>
public static Key GetModifiersKey (KeyEvent kb)
{
var key = kb.Key;
if (kb.IsAlt && (key & Key.AltMask) == 0) {
key |= Key.AltMask;
}
if (kb.IsCtrl && (key & Key.CtrlMask) == 0) {
key |= Key.CtrlMask;
}
if (kb.IsShift && (key & Key.ShiftMask) == 0) {
key |= Key.ShiftMask;
}
return key;
}
/// <summary>
/// Get the <see cref="ShortCut"/> key as string.
/// </summary>
@@ -202,5 +228,38 @@ namespace Terminal.Gui {
}
return false;
}
/// <summary>
/// Allows a view to run a <see cref="View.ShortCutAction"/> if defined.
/// </summary>
/// <param name="kb">The <see cref="KeyEvent"/></param>
/// <param name="view">The <see cref="View"/></param>
/// <returns><c>true</c> if defined <c>false</c>otherwise.</returns>
public static bool FindAndOpenByShortCut (KeyEvent kb, View view = null)
{
if (view == null) {
return false; }
var key = kb.KeyValue;
var keys = GetModifiersKey (kb);
key |= (int)keys;
foreach (var v in view.Subviews) {
if (v.ShortCut != Key.Null && v.ShortCut == (Key)key) {
var action = v.ShortCutAction;
if (action != null) {
Application.MainLoop.AddIdle (() => {
action ();
return false;
});
}
return true;
}
if (FindAndOpenByShortCut (kb, v)) {
return true;
}
}
return false;
}
}
}

View File

@@ -213,6 +213,19 @@ namespace Terminal.Gui {
return false;
}
///<inheritdoc/>
public override bool ProcessColdKey (KeyEvent keyEvent)
{
if (base.ProcessColdKey (keyEvent)) {
return true;
}
if (ShortCutHelper.FindAndOpenByShortCut(keyEvent, this)) {
return true;
}
return false;
}
View GetDeepestFocusedSubview (View view)
{
if (view == null) {

View File

@@ -125,6 +125,8 @@ namespace Terminal.Gui {
TextFormatter textFormatter;
ShortCutHelper shortCutHelper;
/// <summary>
/// Event fired when a subview is being added to this view.
/// </summary>
@@ -170,6 +172,28 @@ namespace Terminal.Gui {
/// </summary>
public Rune HotKeySpecifier { get => textFormatter.HotKeySpecifier; set => textFormatter.HotKeySpecifier = value; }
/// <summary>
/// This is the global setting that can be used as a global shortcut to invoke an action if provided.
/// </summary>
public Key ShortCut {
get => shortCutHelper.ShortCut;
set {
if (shortCutHelper.ShortCut != value && (ShortCutHelper.PostShortCutValidation (value) || value == Key.Null)) {
shortCutHelper.ShortCut = value;
}
}
}
/// <summary>
/// The keystroke combination used in the <see cref="ShortCut"/> as string.
/// </summary>
public ustring ShortCutTag => ShortCutHelper.GetShortCutTag (shortCutHelper.ShortCut);
/// <summary>
/// The action to run if the <see cref="ShortCut"/> is defined.
/// </summary>
public virtual Action ShortCutAction { get; set; }
/// <summary>
/// Gets or sets arbitrary data for the view.
/// </summary>
@@ -550,6 +574,8 @@ namespace Terminal.Gui {
textFormatter = new TextFormatter ();
this.Text = ustring.Empty;
shortCutHelper = new ShortCutHelper ();
this.Frame = frame;
LayoutStyle = LayoutStyle.Absolute;
}
@@ -612,6 +638,8 @@ namespace Terminal.Gui {
{
textFormatter = new TextFormatter ();
this.Text = text;
shortCutHelper = new ShortCutHelper ();
}
/// <summary>
@@ -633,6 +661,8 @@ namespace Terminal.Gui {
textFormatter = new TextFormatter ();
this.Text = text;
shortCutHelper = new ShortCutHelper ();
CanFocus = false;
TabIndex = -1;
TabStop = false;
@@ -2055,26 +2085,5 @@ namespace Terminal.Gui {
return true;
}
/// <summary>
/// Gets the key with all the keys modifiers, especially the shift key that sometimes have to be injected later.
/// </summary>
/// <param name="kb">The <see cref="KeyEvent"/> to check.</param>
/// <returns>The <see cref="KeyEvent.Key"/> with all the keys modifiers.</returns>
public Key GetModifiersKey (KeyEvent kb)
{
var key = kb.Key;
if (kb.IsAlt && (key & Key.AltMask) == 0) {
key |= Key.AltMask;
}
if (kb.IsCtrl && (key & Key.CtrlMask) == 0) {
key |= Key.CtrlMask;
}
if (kb.IsShift && (key & Key.ShiftMask) == 0) {
key |= Key.ShiftMask;
}
return key;
}
}
}

View File

@@ -1328,14 +1328,8 @@ namespace Terminal.Gui {
}
var key = kb.KeyValue;
var keys = GetModifiersKey (kb);
var keys = ShortCutHelper.GetModifiersKey (kb);
key |= (int)keys;
//if (kb.IsShift) {
// key |= (int)Key.ShiftMask;
//}
//if (kb.IsAlt) {
// key |= unchecked((int)Key.AltMask);
//}
for (int i = 0; i < children.Length; i++) {
var mi = children [i];
if (mi == null) {

View File

@@ -345,7 +345,7 @@ namespace Terminal.Gui {
// Needed for the Elmish Wrapper issue https://github.com/DieselMeister/Terminal.Gui.Elmish/issues/2
var oldCursorPos = point;
switch (GetModifiersKey (kb)) {
switch (ShortCutHelper.GetModifiersKey (kb)) {
case Key.DeleteChar:
case Key.D | Key.CtrlMask:
if (ReadOnly)

View File

@@ -725,7 +725,7 @@ namespace UICatalog {
return;
}
var k = GetModifiersKey (e.KeyEvent);
var k = ShortCutHelper.GetModifiersKey (e.KeyEvent);
if (CheckShortCut (k, true)) {
e.Handled = true;
}
@@ -764,7 +764,7 @@ namespace UICatalog {
}
_txtShortCut.KeyUp += (e) => {
var k = GetModifiersKey (e.KeyEvent);
var k = ShortCutHelper.GetModifiersKey (e.KeyEvent);
if (CheckShortCut (k, false)) {
e.Handled = true;
}

View File

@@ -105,7 +105,7 @@ namespace UICatalog {
_rightPane.SetFocus ();
_top.Ready -= ReadyHandler;
}
_top.Ready += ReadyHandler;
#if DEBUG_IDISPOSABLE
@@ -114,7 +114,7 @@ namespace UICatalog {
foreach (var inst in Responder.Instances) {
Debug.Assert (inst.WasDisposed);
}
Responder.Instances.Clear();
Responder.Instances.Clear ();
#endif
}
@@ -174,8 +174,10 @@ namespace UICatalog {
Width = 25,
Height = Dim.Fill (1),
CanFocus = false,
ShortCut = Key.CtrlMask | Key.C
};
_leftPane.Title = $"{_leftPane.Title} ({_leftPane.ShortCutTag})";
_leftPane.ShortCutAction = () => _leftPane.SetFocus ();
_categories = Scenario.GetAllCategories ().OrderBy (c => c).ToList ();
_categoryListView = new ListView (_categories) {
@@ -198,8 +200,10 @@ namespace UICatalog {
Width = Dim.Fill (),
Height = Dim.Fill (1),
CanFocus = true,
ShortCut = Key.CtrlMask | Key.S
};
_rightPane.Title = $"{_rightPane.Title} ({_rightPane.ShortCutTag})";
_rightPane.ShortCutAction = () => _rightPane.SetFocus ();
_nameColumnWidth = Scenario.ScenarioMetadata.GetName (_scenarios.OrderByDescending (t => Scenario.ScenarioMetadata.GetName (t).Length).FirstOrDefault ()).Length;
@@ -222,7 +226,7 @@ namespace UICatalog {
_numlock = new StatusItem (Key.CharMask, "Num", null);
_scrolllock = new StatusItem (Key.CharMask, "Scroll", null);
_statusBar = new StatusBar () {
_statusBar = new StatusBar () {
Visible = true,
};
_statusBar.Items = new StatusItem [] {