mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-30 09:47:58 +01:00
Smarter StatusBar bottom tracking.
This commit is contained in:
153
Example/demo.cs
153
Example/demo.cs
@@ -7,8 +7,8 @@ using System.Globalization;
|
||||
using System.Reflection;
|
||||
using NStack;
|
||||
|
||||
static class Demo {
|
||||
//class Box10x : View, IScrollView {
|
||||
static class Demo {
|
||||
//class Box10x : View, IScrollView {
|
||||
class Box10x : View {
|
||||
int w = 40;
|
||||
int h = 50;
|
||||
@@ -30,20 +30,20 @@ static class Demo {
|
||||
}
|
||||
|
||||
public override void Redraw (Rect region)
|
||||
{
|
||||
//Point pos = new Point (region.X, region.Y);
|
||||
{
|
||||
//Point pos = new Point (region.X, region.Y);
|
||||
Driver.SetAttribute (ColorScheme.Focus);
|
||||
|
||||
for (int y = 0; y < h; y++) {
|
||||
Move (0, y);
|
||||
Driver.AddStr (y.ToString ());
|
||||
for (int x = 0; x < w - y.ToString ().Length; x++) {
|
||||
//Driver.AddRune ((Rune)('0' + (x + y) % 10));
|
||||
for (int x = 0; x < w - y.ToString ().Length; x++) {
|
||||
//Driver.AddRune ((Rune)('0' + (x + y) % 10));
|
||||
if (y.ToString ().Length < w)
|
||||
Driver.AddStr (" ");
|
||||
}
|
||||
}
|
||||
//Move (pos.X, pos.Y);
|
||||
}
|
||||
//Move (pos.X, pos.Y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,10 +93,10 @@ static class Demo {
|
||||
int i = 0;
|
||||
string txt = "Hello world, how are you doing today";
|
||||
container.Add (
|
||||
new Label (new Rect (0, 1, 40, 3), $"{i+1}-{txt}") { TextAlignment = TextAlignment.Left },
|
||||
new Label (new Rect (0, 3, 40, 3), $"{i+2}-{txt}") { TextAlignment = TextAlignment.Right },
|
||||
new Label (new Rect (0, 5, 40, 3), $"{i+3}-{txt}") { TextAlignment = TextAlignment.Centered },
|
||||
new Label (new Rect (0, 7, 40, 3), $"{i+4}-{txt}") { TextAlignment = TextAlignment.Justified }
|
||||
new Label (new Rect (0, 1, 40, 3), $"{i + 1}-{txt}") { TextAlignment = TextAlignment.Left },
|
||||
new Label (new Rect (0, 3, 40, 3), $"{i + 2}-{txt}") { TextAlignment = TextAlignment.Right },
|
||||
new Label (new Rect (0, 5, 40, 3), $"{i + 3}-{txt}") { TextAlignment = TextAlignment.Centered },
|
||||
new Label (new Rect (0, 7, 40, 3), $"{i + 4}-{txt}") { TextAlignment = TextAlignment.Justified }
|
||||
);
|
||||
|
||||
Application.Run (container);
|
||||
@@ -105,18 +105,18 @@ static class Demo {
|
||||
static void ShowEntries (View container)
|
||||
{
|
||||
var scrollView = new ScrollView (new Rect (50, 10, 20, 8)) {
|
||||
ContentSize = new Size (20, 50),
|
||||
//ContentOffset = new Point (0, 0),
|
||||
ContentSize = new Size (20, 50),
|
||||
//ContentOffset = new Point (0, 0),
|
||||
ShowVerticalScrollIndicator = true,
|
||||
ShowHorizontalScrollIndicator = true
|
||||
};
|
||||
};
|
||||
#if false
|
||||
scrollView.Add (new Box10x (0, 0));
|
||||
#else
|
||||
scrollView.Add (new Filler (new Rect (0, 0, 40, 40)));
|
||||
scrollView.Add (new Filler (new Rect (0, 0, 40, 40)));
|
||||
#endif
|
||||
|
||||
// This is just to debug the visuals of the scrollview when small
|
||||
|
||||
// This is just to debug the visuals of the scrollview when small
|
||||
var scrollView2 = new ScrollView (new Rect (72, 10, 3, 3)) {
|
||||
ContentSize = new Size (100, 100),
|
||||
ShowVerticalScrollIndicator = true,
|
||||
@@ -130,12 +130,12 @@ static class Demo {
|
||||
return true;
|
||||
}
|
||||
|
||||
Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (300), timer);
|
||||
|
||||
|
||||
// A little convoluted, this is because I am using this to test the
|
||||
// layout based on referencing elements of another view:
|
||||
|
||||
Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (300), timer);
|
||||
|
||||
|
||||
// A little convoluted, this is because I am using this to test the
|
||||
// layout based on referencing elements of another view:
|
||||
|
||||
var login = new Label ("Login: ") { X = 3, Y = 6 };
|
||||
var password = new Label ("Password: ") {
|
||||
X = Pos.Left (login),
|
||||
@@ -154,8 +154,8 @@ static class Demo {
|
||||
Width = Dim.Width (loginText)
|
||||
};
|
||||
|
||||
var tf = new Button (3, 19, "Ok");
|
||||
// Add some content
|
||||
var tf = new Button (3, 19, "Ok");
|
||||
// Add some content
|
||||
container.Add (
|
||||
login,
|
||||
loginText,
|
||||
@@ -202,10 +202,10 @@ static class Demo {
|
||||
ml2 = new Label (1, 1, "Mouse Debug Line");
|
||||
d.Add (ml2);
|
||||
Application.Run (d);
|
||||
}
|
||||
|
||||
//
|
||||
// Creates a nested editor
|
||||
}
|
||||
|
||||
//
|
||||
// Creates a nested editor
|
||||
static void Editor (Toplevel top)
|
||||
{
|
||||
var tframe = top.Frame;
|
||||
@@ -255,12 +255,12 @@ static class Demo {
|
||||
static void Close ()
|
||||
{
|
||||
MessageBox.ErrorQuery (50, 7, "Error", "There is nothing to close", "Ok");
|
||||
}
|
||||
|
||||
// Watch what happens when I try to introduce a newline after the first open brace
|
||||
// it introduces a new brace instead, and does not indent. Then watch me fight
|
||||
// the editor as more oddities happen.
|
||||
|
||||
}
|
||||
|
||||
// Watch what happens when I try to introduce a newline after the first open brace
|
||||
// it introduces a new brace instead, and does not indent. Then watch me fight
|
||||
// the editor as more oddities happen.
|
||||
|
||||
public static void Open ()
|
||||
{
|
||||
var d = new OpenDialog ("Open", "Open a file") { AllowsMultipleSelection = true };
|
||||
@@ -368,10 +368,10 @@ static class Demo {
|
||||
static void Help ()
|
||||
{
|
||||
MessageBox.Query (50, 7, "Help", "This is a small help\nBe kind.", "Ok");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#region Selection Demo
|
||||
|
||||
|
||||
static void ListSelectionDemo (bool multiple)
|
||||
{
|
||||
var d = new Dialog ("Selection Demo", 60, 20,
|
||||
@@ -404,20 +404,19 @@ static class Demo {
|
||||
}
|
||||
}
|
||||
MessageBox.Query (60, 10, "Selected Animals", result == "" ? "No animals selected" : result, "Ok");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
#region OnKeyDown / OnKeyUp Demo
|
||||
private static void OnKeyDownUpDemo ()
|
||||
{
|
||||
var container = new Dialog (
|
||||
"OnKeyDown & OnKeyUp demo", 80, 20,
|
||||
new Button ("Close") { Clicked = () => { Application.RequestStop (); } }) {
|
||||
Width = Dim.Fill (),
|
||||
"OnKeyDown & OnKeyUp demo", 0, 0) {
|
||||
Width = Dim.Fill () ,
|
||||
Height = Dim.Fill (),
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
var list = new List<string> ();
|
||||
var listView = new ListView (list) {
|
||||
X = 0,
|
||||
@@ -431,23 +430,24 @@ static class Demo {
|
||||
void KeyUpDown (KeyEvent keyEvent, string updown)
|
||||
{
|
||||
if ((keyEvent.Key & Key.CtrlMask) != 0) {
|
||||
list.Add ($"Key{updown, -4}: Ctrl ");
|
||||
list.Add ($"Key{updown,-4}: Ctrl ");
|
||||
} else if ((keyEvent.Key & Key.AltMask) != 0) {
|
||||
list.Add ($"Key{updown, -4}: Alt ");
|
||||
list.Add ($"Key{updown,-4}: Alt ");
|
||||
} else {
|
||||
list.Add ($"Key{updown, -4}: {(((uint)keyEvent.KeyValue & (uint)Key.CharMask) > 26 ? $"{(char)keyEvent.KeyValue}" : $"{keyEvent.Key}")}");
|
||||
list.Add ($"Key{updown,-4}: {(((uint)keyEvent.KeyValue & (uint)Key.CharMask) > 26 ? $"{(char)keyEvent.KeyValue}" : $"{keyEvent.Key}")}");
|
||||
}
|
||||
listView.MoveDown ();
|
||||
}
|
||||
|
||||
container.OnKeyDown += (KeyEvent keyEvent) => KeyUpDown (keyEvent, "Down");
|
||||
container.OnKeyUp += (KeyEvent keyEvent) => KeyUpDown (keyEvent, "Up");
|
||||
container.OnKeyUp += (KeyEvent keyEvent) => KeyUpDown (keyEvent, "Up");
|
||||
|
||||
Application.Run (container);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
public static Label ml;
|
||||
public static MenuBar menu;
|
||||
public static CheckBox menuKeysStyle;
|
||||
@@ -455,23 +455,23 @@ static class Demo {
|
||||
static void Main ()
|
||||
{
|
||||
if (Debugger.IsAttached)
|
||||
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US");
|
||||
|
||||
//Application.UseSystemConsole = true;
|
||||
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US");
|
||||
|
||||
//Application.UseSystemConsole = true;
|
||||
Console.WindowHeight = 35;
|
||||
|
||||
Application.Init ();
|
||||
|
||||
var top = Application.Top;
|
||||
|
||||
//Open ();
|
||||
var top = Application.Top;
|
||||
|
||||
//Open ();
|
||||
#if true
|
||||
var win = new Window ("Hello") {
|
||||
X = 1,
|
||||
Y = 1,
|
||||
Width = Dim.Fill (),
|
||||
Height = Dim.Fill () - 1
|
||||
};
|
||||
};
|
||||
#else
|
||||
var tframe = top.Frame;
|
||||
|
||||
@@ -561,27 +561,30 @@ static class Demo {
|
||||
new StatusItem(Key.F2, "~F2~ Load", null),
|
||||
new StatusItem(Key.F3, "~F3~ Save", null),
|
||||
new StatusItem(Key.ControlX, "~^X~ Quit", () => { if (Quit ()) top.Running = false; }),
|
||||
});
|
||||
|
||||
win.Add (drag, dragText);
|
||||
#if true
|
||||
// This currently causes a stack overflow, because it is referencing a window that has not had its size allocated yet
|
||||
}) {
|
||||
Style = StatusBar.StatusBarStyle.SnapToBottom,
|
||||
Parent = null,
|
||||
};
|
||||
|
||||
win.Add (drag, dragText);
|
||||
#if false
|
||||
// This currently causes a stack overflow, because it is referencing a window that has not had its size allocated yet
|
||||
|
||||
var bottom = new Label ("This should go on the bottom!");
|
||||
win.Add (bottom);
|
||||
|
||||
Application.OnResized = () => {
|
||||
Application.OnResized += () => {
|
||||
bottom.X = Pos.Left (win);
|
||||
bottom.Y = Pos.Bottom (win);
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
top.Add (win);
|
||||
//top.Add (menu);
|
||||
|
||||
|
||||
top.Add (win);
|
||||
//top.Add (menu);
|
||||
top.Add (menu, statusBar, ml);
|
||||
|
||||
OnKeyDownUpDemo ();
|
||||
//OnKeyDownUpDemo ();
|
||||
|
||||
Application.Run ();
|
||||
}
|
||||
|
||||
@@ -6,149 +6,165 @@
|
||||
//
|
||||
// TODO:
|
||||
// Add mouse support
|
||||
// Uses internals of Application
|
||||
using System;
|
||||
using NStack;
|
||||
|
||||
using System;
|
||||
using NStack;
|
||||
|
||||
namespace Terminal.Gui {
|
||||
/// <summary>
|
||||
/// A statusbar item has a title, a shortcut aka hotkey, and an action to execute on activation.
|
||||
/// Such an item is ment to be as part of the global hotkeys of the application, which are available in the current context of the screen.
|
||||
/// The colour of the text will be changed after each ~. Having an statusbar item with a text of `~F1~ Help` will draw *F1* as shortcut and
|
||||
/// *Help* as standard text.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// A statusbar item has a title, a shortcut aka hotkey, and an action to execute on activation.
|
||||
/// Such an item is ment to be as part of the global hotkeys of the application, which are available in the current context of the screen.
|
||||
/// The colour of the text will be changed after each ~. Having an statusbar item with a text of `~F1~ Help` will draw *F1* as shortcut and
|
||||
/// *Help* as standard text.
|
||||
/// </summary>
|
||||
public class StatusItem {
|
||||
/// <summary>
|
||||
/// Initializes a new <see cref="T:Terminal.Gui.StatusItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="shortcut">Shortcut to activate the item.</param>
|
||||
/// <param name="title">Title for the statusbar item.</param>
|
||||
/// <param name="action">Action to invoke when the staturbar item is activated.</param>
|
||||
/// <summary>
|
||||
/// Initializes a new <see cref="T:Terminal.Gui.StatusItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="shortcut">Shortcut to activate the item.</param>
|
||||
/// <param name="title">Title for the statusbar item.</param>
|
||||
/// <param name="action">Action to invoke when the staturbar item is activated.</param>
|
||||
public StatusItem (Key shortcut, ustring title, Action action)
|
||||
{
|
||||
Title = title ?? "";
|
||||
Shortcut = shortcut;
|
||||
Action = action;
|
||||
{
|
||||
Title = title ?? "";
|
||||
Shortcut = shortcut;
|
||||
Action = action;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the global setting that can be used as a global shortcut to invoke the action on the menu.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// This is the global setting that can be used as a global shortcut to invoke the action on the menu.
|
||||
/// </summary>
|
||||
public Key Shortcut { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the title.
|
||||
/// </summary>
|
||||
/// <value>The title.</value>
|
||||
/// <summary>
|
||||
/// Gets or sets the title.
|
||||
/// </summary>
|
||||
/// <value>The title.</value>
|
||||
public ustring Title { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the action to be invoked when the statusbar item is triggered
|
||||
/// </summary>
|
||||
/// <value>Method to invoke.</value>
|
||||
public Action Action { get; }
|
||||
/// <summary>
|
||||
/// Gets or sets the action to be invoked when the statusbar item is triggered
|
||||
/// </summary>
|
||||
/// <value>Method to invoke.</value>
|
||||
public Action Action { get; }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A statusbar for your application.
|
||||
/// The statusbar should be context sensitive. This means, if the main menu and an open text editor are visible, the items probably shown will
|
||||
/// be ~F1~ Help ~F2~ Save ~F3~ Load. While a dialog to ask a file to load is executed, the remaining commands will probably be ~F1~ Help.
|
||||
/// So for each context must be a new instance of a statusbar.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// A statusbar for your application.
|
||||
/// The statusbar should be context sensitive. This means, if the main menu and an open text editor are visible, the items probably shown will
|
||||
/// be ~F1~ Help ~F2~ Save ~F3~ Load. While a dialog to ask a file to load is executed, the remaining commands will probably be ~F1~ Help.
|
||||
/// So for each context must be a new instance of a statusbar.
|
||||
/// </summary>
|
||||
public class StatusBar : View {
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The style supported by StatusBar
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// The style supported by StatusBar
|
||||
/// </summary>
|
||||
public enum StatusBarStyle {
|
||||
/// <summary>
|
||||
/// The StatusBar will snap at the the bottom line of the console window.
|
||||
/// If the console window is made larger while the app is runing, the StatusBar
|
||||
/// will continue to snap to the bottom. If the console window is subsequently
|
||||
/// made shorter, the status bar will be invisible. This is the default.
|
||||
/// </summary>
|
||||
SnapToConsoleBottom = 0,
|
||||
Default = 0,
|
||||
/// <summary>
|
||||
/// The StatusBar will snap at the the bottom line of the Parent view.
|
||||
/// If the console window is made larger while the app is runing, the StatusBar
|
||||
/// will continue to snap to the bottom line of the Parent, staying visible.
|
||||
/// On consoles that support resizing of console apps (e.g. Windows Terminal and ConEmu),
|
||||
/// if the console window is subsequently made shorter, the status bar will remain visible
|
||||
/// as the Parent view resizes. If Parent is null, the StatusBar will snap to the bottom line
|
||||
/// of the console window.
|
||||
/// This is the default.
|
||||
/// </summary>
|
||||
SnapToBottom = Default,
|
||||
|
||||
/// <summary>
|
||||
/// The StatusBar will snap at the the bottom line of the Application.Top view.
|
||||
/// If the console window is made larger while the app is runing, the StatusBar
|
||||
/// will continue to snap to the bottom line of Application.Top, staying visible.
|
||||
/// If the console window is subsequently made shorter, the status bar will remain visible
|
||||
/// at the last visible line.
|
||||
/// </summary>
|
||||
SnapToAppBottom = 1,
|
||||
/// <summary>
|
||||
/// The StatusBar will act identically to MenuBar, snapping to the first line of the
|
||||
/// console window.
|
||||
/// </summary>
|
||||
SnapToTop = 1,
|
||||
}
|
||||
|
||||
public StatusBarStyle Style { get; set; } = StatusBarStyle.Default;
|
||||
|
||||
public View Parent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The StatusBar will act identically to MenuBar, snapping to the first line of the
|
||||
/// console window.
|
||||
/// </summary>
|
||||
SnapToTop = 2,
|
||||
}
|
||||
|
||||
public StatusItem [] Items { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:Terminal.Gui.StatusBar"/> class with the specified set of statusbar items.
|
||||
/// It will be drawn in the lowest line of the terminal.
|
||||
/// </summary>
|
||||
/// <param name="items">A list of statusbar items.</param>
|
||||
public StatusBar (StatusItem [] items) : base ()
|
||||
{
|
||||
X = 0;
|
||||
Y = Application.Driver.Rows - 1; // TODO: using internals of Application
|
||||
Width = Dim.Fill ();
|
||||
Height = 1;
|
||||
Items = items;
|
||||
CanFocus = false;
|
||||
ColorScheme = Colors.Menu;
|
||||
}
|
||||
|
||||
Attribute ToggleScheme (Attribute scheme)
|
||||
{
|
||||
var result = scheme == ColorScheme.Normal ? ColorScheme.HotNormal : ColorScheme.Normal;
|
||||
Driver.SetAttribute (result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:Terminal.Gui.StatusBar"/> class with the specified set of statusbar items.
|
||||
/// It will be drawn in the lowest line of the terminal.
|
||||
/// </summary>
|
||||
/// <param name="items">A list of statusbar items.</param>
|
||||
public StatusBar (StatusItem [] items) : base ()
|
||||
{
|
||||
Width = Dim.Fill ();
|
||||
Height = 1;
|
||||
Items = items;
|
||||
CanFocus = false;
|
||||
ColorScheme = Colors.Menu;
|
||||
|
||||
Application.OnResized += () => {
|
||||
X = 0;
|
||||
Height = 1;
|
||||
|
||||
switch (Style) {
|
||||
case StatusBarStyle.SnapToBottom:
|
||||
if (Parent == null) {
|
||||
Y = Application.Driver.Rows - 1; // TODO: using internals of Application
|
||||
} else {
|
||||
Y = Pos.Bottom (Parent);
|
||||
}
|
||||
break;
|
||||
case StatusBarStyle.SnapToTop:
|
||||
X = 0;
|
||||
Y = 0;
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Attribute ToggleScheme (Attribute scheme)
|
||||
{
|
||||
var result = scheme == ColorScheme.Normal ? ColorScheme.HotNormal : ColorScheme.Normal;
|
||||
Driver.SetAttribute (result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void Redraw (Rect region)
|
||||
{
|
||||
if (Frame.Y != Driver.Rows - 1) {
|
||||
Frame = new Rect (Frame.X, Driver.Rows - 1, Frame.Width, Frame.Height);
|
||||
Y = Driver.Rows - 1;
|
||||
SetNeedsDisplay ();
|
||||
}
|
||||
|
||||
Move (0, 0);
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
for (int i = 0; i < Frame.Width; i++)
|
||||
Driver.AddRune (' ');
|
||||
|
||||
Move (1, 0);
|
||||
var scheme = ColorScheme.Normal;
|
||||
Driver.SetAttribute (scheme);
|
||||
for (int i = 0; i < Items.Length; i++) {
|
||||
var title = Items [i].Title;
|
||||
for (int n = 0; n < title.Length; n++) {
|
||||
if (title [n] == '~') {
|
||||
scheme = ToggleScheme (scheme);
|
||||
continue;
|
||||
}
|
||||
Driver.AddRune (title [n]);
|
||||
}
|
||||
Driver.AddRune (' ');
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ProcessHotKey (KeyEvent kb)
|
||||
{
|
||||
foreach (var item in Items) {
|
||||
if (kb.Key == item.Shortcut) {
|
||||
if (item.Action != null) item.Action ();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
{
|
||||
//if (Frame.Y != Driver.Rows - 1) {
|
||||
// Frame = new Rect (Frame.X, Driver.Rows - 1, Frame.Width, Frame.Height);
|
||||
// Y = Driver.Rows - 1;
|
||||
// SetNeedsDisplay ();
|
||||
//}
|
||||
|
||||
Move (0, 0);
|
||||
Driver.SetAttribute (ColorScheme.Normal);
|
||||
for (int i = 0; i < Frame.Width; i++)
|
||||
Driver.AddRune (' ');
|
||||
|
||||
Move (1, 0);
|
||||
var scheme = ColorScheme.Normal;
|
||||
Driver.SetAttribute (scheme);
|
||||
for (int i = 0; i < Items.Length; i++) {
|
||||
var title = Items [i].Title;
|
||||
for (int n = 0; n < title.Length; n++) {
|
||||
if (title [n] == '~') {
|
||||
scheme = ToggleScheme (scheme);
|
||||
continue;
|
||||
}
|
||||
Driver.AddRune (title [n]);
|
||||
}
|
||||
Driver.AddRune (' ');
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ProcessHotKey (KeyEvent kb)
|
||||
{
|
||||
foreach (var item in Items) {
|
||||
if (kb.Key == item.Shortcut) {
|
||||
if (item.Action != null) item.Action ();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user