diff --git a/Example/demo.cs b/Example/demo.cs
index 8c794f305..9ab69011c 100644
--- a/Example/demo.cs
+++ b/Example/demo.cs
@@ -105,7 +105,7 @@ static class Demo {
static void ShowTextAlignments ()
{
- var container = new Window ($"Show Text Alignments") {
+ var container = new Window ("Show Text Alignments - Press Esc to return") {
X = 0,
Y = 0,
Width = Dim.Fill (),
@@ -244,12 +244,12 @@ static class Demo {
var menu = new MenuBar (new MenuBarItem [] {
new MenuBarItem ("_File", new MenuItem [] {
- new MenuItem ("_Close", "", () => { if (Quit ()) { running = MainApp; Application.RequestStop (); } }),
+ new MenuItem ("_Close", "", () => { if (Quit ()) { running = MainApp; Application.RequestStop (); } }, null, null, Key.AltMask | Key.F4),
}),
new MenuBarItem ("_Edit", new MenuItem [] {
- new MenuItem ("_Copy", "", null),
- new MenuItem ("C_ut", "", null),
- new MenuItem ("_Paste", "", null)
+ new MenuItem ("_Copy", "", null, null, null, Key.ControlC),
+ new MenuItem ("C_ut", "", null, null, null, Key.ControlX),
+ new MenuItem ("_Paste", "", null, null, null, Key.ControlV)
}),
});
ntop.Add (menu);
@@ -309,13 +309,12 @@ static class Demo {
MessageBox.Query (50, 7, "Selected File", d.FilePaths.Count > 0 ? string.Join (", ", d.FilePaths) : d.FilePath, "Ok");
}
- public static void ShowHex (Toplevel top)
+ public static void ShowHex ()
{
- var tframe = top.Frame;
- var ntop = new Toplevel (tframe);
+ var ntop = Application.Top;
var menu = new MenuBar (new MenuBarItem [] {
new MenuBarItem ("_File", new MenuItem [] {
- new MenuItem ("_Close", "", () => {Application.RequestStop ();}),
+ new MenuItem ("_Close", "", () => { running = MainApp; Application.RequestStop (); }, null, null, Key.AltMask | Key.F4),
}),
});
ntop.Add (menu);
@@ -338,7 +337,6 @@ static class Demo {
};
win.Add (hex);
Application.Run (ntop);
-
}
public class MenuItemDetails : MenuItem {
@@ -382,7 +380,7 @@ static class Demo {
static void Copy ()
{
- TextField textField = menu.LastFocused as TextField;
+ TextField textField = menu.LastFocused as TextField ?? Application.Top.MostFocused as TextField;
if (textField != null && textField.SelectedLength != 0) {
textField.Copy ();
}
@@ -390,7 +388,7 @@ static class Demo {
static void Cut ()
{
- TextField textField = menu.LastFocused as TextField;
+ TextField textField = menu.LastFocused as TextField ?? Application.Top.MostFocused as TextField;
if (textField != null && textField.SelectedLength != 0) {
textField.Cut ();
}
@@ -398,10 +396,8 @@ static class Demo {
static void Paste ()
{
- TextField textField = menu.LastFocused as TextField;
- if (textField != null) {
- textField.Paste ();
- }
+ TextField textField = menu.LastFocused as TextField ?? Application.Top.MostFocused as TextField;
+ textField?.Paste ();
}
static void Help ()
@@ -601,31 +597,31 @@ static class Demo {
menu = new MenuBar (new MenuBarItem [] {
new MenuBarItem ("_File", new MenuItem [] {
- new MenuItem ("Text _Editor Demo", "", () => { running = Editor; Application.RequestStop (); }),
- new MenuItem ("_New", "Creates new file", NewFile),
- new MenuItem ("_Open", "", Open),
- new MenuItem ("_Hex", "", () => ShowHex (top)),
- new MenuItem ("_Close", "", () => Close ()),
+ new MenuItem ("Text _Editor Demo", "", () => { running = Editor; Application.RequestStop (); }, null, null, Key.AltMask | Key.ControlD),
+ new MenuItem ("_New", "Creates new file", NewFile, null, null, Key.AltMask | Key.ControlN),
+ new MenuItem ("_Open", "", Open, null, null, Key.AltMask | Key.ControlO),
+ new MenuItem ("_Hex", "", () => { running = ShowHex; Application.RequestStop (); }, null, null, Key.AltMask | Key.ControlH),
+ new MenuItem ("_Close", "", Close, null, null, Key.AltMask | Key.F4),
new MenuItem ("_Disabled", "", () => { }, () => false),
null,
- new MenuItem ("_Quit", "", () => { if (Quit ()) { running = null; top.Running = false; } })
+ new MenuItem ("_Quit", "", () => { if (Quit ()) { running = null; top.Running = false; } }, null, null, Key.ControlQ)
}),
new MenuBarItem ("_Edit", new MenuItem [] {
- new MenuItem ("_Copy", "", Copy),
- new MenuItem ("C_ut", "", Cut),
- new MenuItem ("_Paste", "", Paste),
+ new MenuItem ("_Copy", "", Copy, null, null, Key.AltMask | Key.ControlC),
+ new MenuItem ("C_ut", "", Cut, null, null, Key.AltMask | Key.ControlX),
+ new MenuItem ("_Paste", "", Paste, null, null, Key.AltMask | Key.ControlV),
new MenuBarItem ("_Find and Replace",
new MenuItem [] { menuItems [0], menuItems [1] }),
menuItems[3]
}),
new MenuBarItem ("_List Demos", new MenuItem [] {
- new MenuItem ("Select _Multiple Items", "", () => ListSelectionDemo (true)),
- new MenuItem ("Select _Single Item", "", () => ListSelectionDemo (false)),
- new MenuItem ("Search Single Item", "", ComboBoxDemo)
+ new MenuItem ("Select _Multiple Items", "", () => ListSelectionDemo (true), null, null, Key.AltMask + 0.ToString () [0]),
+ new MenuItem ("Select _Single Item", "", () => ListSelectionDemo (false), null, null, Key.AltMask + 1.ToString () [0]),
+ new MenuItem ("Search Single Item", "", ComboBoxDemo, null, null, Key.AltMask + 2.ToString () [0])
}),
new MenuBarItem ("A_ssorted", new MenuItem [] {
- new MenuItem ("_Show text alignments", "", () => ShowTextAlignments ()),
- new MenuItem ("_OnKeyDown/Press/Up", "", () => OnKeyDownPressUpDemo ())
+ new MenuItem ("_Show text alignments", "", () => ShowTextAlignments (), null, null, Key.AltMask | Key.ControlG),
+ new MenuItem ("_OnKeyDown/Press/Up", "", () => OnKeyDownPressUpDemo (), null, null, Key.AltMask | Key.ControlK)
}),
new MenuBarItem ("_Test Menu and SubMenus", new MenuBarItem [] {
new MenuBarItem ("SubMenu1Item_1", new MenuBarItem [] {
diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
index fc652219b..20dedb5c6 100644
--- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
@@ -439,11 +439,11 @@ namespace Terminal.Gui {
if (keyModifiers == null)
keyModifiers = new KeyModifiers ();
- if (!keyModifiers.Shift && key.HasFlag (Key.ShiftMask))
+ if (!keyModifiers.Shift && (key & Key.ShiftMask) != 0)
keyModifiers.Shift = true;
- if (!keyModifiers.Alt && key.HasFlag (Key.AltMask))
+ if (!keyModifiers.Alt && (key & Key.AltMask) != 0)
keyModifiers.Alt = true;
- if (!keyModifiers.Ctrl && key.HasFlag (Key.CtrlMask))
+ if (!keyModifiers.Ctrl && (key & Key.CtrlMask) != 0)
keyModifiers.Ctrl = true;
return keyModifiers;
@@ -472,8 +472,23 @@ namespace Terminal.Gui {
mouseHandler (ToDriverMouse (ev));
return;
}
- keyHandler (new KeyEvent (MapCursesKey (wch), keyModifiers));
- keyUpHandler (new KeyEvent (MapCursesKey (wch), keyModifiers));
+ k = MapCursesKey (wch);
+ if (wch >= 277 && wch <= 288) { // Shift+(F1 - F12)
+ wch -= 12;
+ k = Key.ShiftMask | MapCursesKey (wch);
+ } else if (wch >= 289 && wch <= 300) { // Ctrl+(F1 - F12)
+ wch -= 24;
+ k = Key.CtrlMask | MapCursesKey (wch);
+ } else if (wch >= 301 && wch <= 312) { // Ctrl+Shift+(F1 - F12)
+ wch -= 36;
+ k = Key.CtrlMask | Key.ShiftMask | MapCursesKey (wch);
+ } else if (wch >= 313 && wch <= 324) { // Alt+(F1 - F12)
+ wch -= 48;
+ k = Key.AltMask | MapCursesKey (wch);
+ }
+ keyDownHandler (new KeyEvent (k, MapKeyModifiers (k)));
+ keyHandler (new KeyEvent (k, MapKeyModifiers (k)));
+ keyUpHandler (new KeyEvent (k, MapKeyModifiers (k)));
return;
}
@@ -498,19 +513,65 @@ namespace Terminal.Gui {
} else if (wch2 - (int)Key.Space >= 'A' && wch2 - (int)Key.Space <= 'Z') {
k = (Key)((uint)Key.AltMask + (wch2 - (int)Key.Space));
key = new KeyEvent (k, MapKeyModifiers (k));
- } else if (wch2 >= '1' && wch <= '9') {
- k = (Key)((int)Key.F1 + (wch2 - '0' - 1));
+ } else if (wch2 >= (uint)Key.ControlA && wch2 <= (uint)Key.ControlZ) {
+ k = (Key)((uint)(Key.AltMask | Key.CtrlMask) + wch2);
key = new KeyEvent (k, MapKeyModifiers (k));
- } else if (wch2 == '0') {
- k = Key.F10;
+ } else if (wch2 >= '0' && wch2 <= '9') {
+ k = (Key)((uint)Key.AltMask + (uint)Key.D0 + (wch2 - '0'));
key = new KeyEvent (k, MapKeyModifiers (k));
} else if (wch2 == 27) {
k = (Key)wch2;
key = new KeyEvent (k, MapKeyModifiers (k));
+ } else if (wch2 == 91) {
+ int [] c = null;
+ while (code == 0) {
+ code = Curses.get_wch (out wch2);
+ if (wch2 > 0) {
+ Array.Resize (ref c, c == null ? 1 : c.Length + 1);
+ c [c.Length - 1] = wch2;
+ }
+ }
+ if (c [0] == 49 && c [1] == 59 && c [2] == 55) { // Ctrl+Alt+(F1 - F4)
+ wch2 = c [3] + 185;
+ k = Key.CtrlMask | Key.AltMask | MapCursesKey (wch2);
+ } else if (c [0] == 49 && c [2] == 59 && c [3] == 55 && c [4] == 126) { // Ctrl+Alt+(F5 - F8)
+ wch2 = c [1] == 53 ? c [1] + 216 : c [1] + 215;
+ k = Key.CtrlMask | Key.AltMask | MapCursesKey (wch2);
+ } else if (c [0] == 50 && c [2] == 59 && c [3] == 55 && c [4] == 126) { // Ctrl+Alt+(F9 - F12)
+ wch2 = c [1] < 51 ? c [1] + 225 : c [1] + 224;
+ k = Key.CtrlMask | Key.AltMask | MapCursesKey (wch2);
+ } else if (c [0] == 49 && c [1] == 59 && c [2] == 56) { // Ctrl+Shift+Alt+(F1 - F4)
+ wch2 = c [3] + 185;
+ k = Key.CtrlMask | Key.ShiftMask | Key.AltMask | MapCursesKey (wch2);
+ } else if (c [0] == 49 && c [2] == 59 && c [3] == 56 && c [4] == 126) { // Ctrl+Shift+Alt+(F5 - F8)
+ wch2 = c [1] == 53 ? c [1] + 216 : c [1] + 215;
+ k = Key.CtrlMask | Key.ShiftMask | Key.AltMask | MapCursesKey (wch2);
+ } else if (c [0] == 50 && c [2] == 59 && c [3] == 56 && c [4] == 126) { // Ctrl+Shift+Alt+(F9 - F12)
+ wch2 = c [1] < 51 ? c [1] + 225 : c [1] + 224;
+ k = Key.CtrlMask | Key.ShiftMask | Key.AltMask | MapCursesKey (wch2);
+ } else {
+ k = MapCursesKey (wch2);
+ }
+ key = new KeyEvent (k, MapKeyModifiers (k));
} else {
- k = Key.AltMask | (Key)wch2;
+ // Unfortunately there are no way to differentiate Ctrl+Alt+alfa and Ctrl+Shift+Alt+alfa.
+ if (wch2 == 0) {
+ k = Key.CtrlMask | Key.AltMask | Key.Space;
+ } else {
+ if (((Key)wch2).ToString ().Contains ("Control")) {
+ keyModifiers.Ctrl = true;
+ }
+ if (wch2 < 256) {
+ k = Key.AltMask | (Key)wch2;
+ } else {
+ //k = (Key)wch2;
+ //keyModifiers.Alt = true;
+ k = (Key)((uint)(Key.AltMask | Key.CtrlMask) + wch2);
+ }
+ }
key = new KeyEvent (k, MapKeyModifiers (k));
}
+ keyDownHandler (key);
keyHandler (key);
} else {
k = Key.Esc;
@@ -521,7 +582,16 @@ namespace Terminal.Gui {
keyDownHandler (new KeyEvent (k, MapKeyModifiers (k)));
keyHandler (new KeyEvent (k, MapKeyModifiers (k)));
} else {
+ // Unfortunately there are no way to differentiate Ctrl+alfa and Ctrl+Shift+alfa.
k = (Key)wch;
+ if (wch == 0) {
+ k = Key.CtrlMask | Key.Space;
+ } else if (wch >= (uint)Key.ControlA && wch <= (uint)Key.ControlZ) {
+ k = (Key)wch;
+ keyModifiers.Ctrl = true;
+ } else if (wch >= 'A' && wch <= 'Z') {
+ keyModifiers.Shift = true;
+ }
keyDownHandler (new KeyEvent (k, MapKeyModifiers (k)));
keyHandler (new KeyEvent (k, MapKeyModifiers (k)));
}
diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs
index ab963b8fc..7fb87438d 100644
--- a/Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs
+++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/binding.cs
@@ -271,7 +271,9 @@ namespace Unix.Terminal {
static public int mouseinterval (int interval) => methods.mouseinterval (interval);
}
+#pragma warning disable RCS1102 // Make class static.
internal class Delegates {
+#pragma warning restore RCS1102 // Make class static.
public delegate IntPtr initscr ();
public delegate int endwin ();
public delegate bool isendwin ();
diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
index a08da19f2..9812983cc 100644
--- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
@@ -1118,30 +1118,42 @@ namespace Terminal.Gui {
if (key >= ConsoleKey.A && key <= ConsoleKey.Z) {
var delta = key - ConsoleKey.A;
- if (keyInfo.Modifiers == ConsoleModifiers.Control)
+ if (keyInfo.Modifiers == ConsoleModifiers.Control) {
return (Key)((uint)Key.ControlA + delta);
- if (keyInfo.Modifiers == ConsoleModifiers.Alt)
+ }
+ if (keyInfo.Modifiers == ConsoleModifiers.Alt) {
return (Key)(((uint)Key.AltMask) | ((uint)'A' + delta));
+ }
if ((keyInfo.Modifiers & (ConsoleModifiers.Alt | ConsoleModifiers.Control)) != 0) {
- if (keyInfo.KeyChar == 0)
- return (Key)(((uint)Key.AltMask) + ((uint)Key.ControlA + delta));
- else
+ if (keyInfo.KeyChar == 0) {
+ return (Key)(((uint)Key.AltMask | (uint)Key.CtrlMask) | ((uint)Key.ControlA + delta));
+ } else {
return (Key)((uint)keyInfo.KeyChar);
+ }
}
//return (Key)((uint)alphaBase + delta);
return (Key)((uint)keyInfo.KeyChar);
}
if (key >= ConsoleKey.D0 && key <= ConsoleKey.D9) {
var delta = key - ConsoleKey.D0;
- if (keyInfo.Modifiers == ConsoleModifiers.Alt)
+ if (keyInfo.Modifiers == ConsoleModifiers.Alt) {
return (Key)(((uint)Key.AltMask) | ((uint)'0' + delta));
-
+ }
+ if (keyInfo.Modifiers == ConsoleModifiers.Control) {
+ return (Key)(((uint)Key.CtrlMask) | ((uint)'0' + delta));
+ }
+ if (keyInfo.KeyChar == 0 || keyInfo.KeyChar == 30) {
+ return MapKeyModifiers (keyInfo, (Key)((uint)'0' + delta));
+ }
return (Key)((uint)keyInfo.KeyChar);
}
if (key >= ConsoleKey.F1 && key <= ConsoleKey.F12) {
var delta = key - ConsoleKey.F1;
+ if ((keyInfo.Modifiers & (ConsoleModifiers.Shift | ConsoleModifiers.Alt | ConsoleModifiers.Control)) != 0) {
+ return MapKeyModifiers (keyInfo, (Key)((uint)Key.F1 + delta));
+ }
- return (Key)((int)Key.F1 + delta);
+ return (Key)((uint)Key.F1 + delta);
}
if (keyInfo.KeyChar != 0) {
return (Key)((uint)keyInfo.KeyChar);
@@ -1153,11 +1165,11 @@ namespace Terminal.Gui {
private Key MapKeyModifiers (ConsoleKeyInfo keyInfo, Key key)
{
Key keyMod = new Key ();
- if (keyInfo.Modifiers.HasFlag (ConsoleModifiers.Shift))
+ if ((keyInfo.Modifiers & ConsoleModifiers.Shift) != 0)
keyMod = Key.ShiftMask;
- if (keyInfo.Modifiers.HasFlag (ConsoleModifiers.Control))
+ if ((keyInfo.Modifiers & ConsoleModifiers.Control) != 0)
keyMod |= Key.CtrlMask;
- if (keyInfo.Modifiers.HasFlag (ConsoleModifiers.Alt))
+ if ((keyInfo.Modifiers & ConsoleModifiers.Alt) != 0)
keyMod |= Key.AltMask;
return keyMod != Key.ControlSpace ? keyMod | key : key;
diff --git a/Terminal.Gui/Core/Event.cs b/Terminal.Gui/Core/Event.cs
index d107bebc1..0939fb435 100644
--- a/Terminal.Gui/Core/Event.cs
+++ b/Terminal.Gui/Core/Event.cs
@@ -318,6 +318,46 @@ namespace Terminal.Gui {
///
BackTab,
///
+ /// Digit 0.
+ ///
+ D0 = 48,
+ ///
+ /// Digit 1.
+ ///
+ D1,
+ ///
+ /// Digit 2.
+ ///
+ D2,
+ ///
+ /// Digit 3.
+ ///
+ D3,
+ ///
+ /// Digit 4.
+ ///
+ D4,
+ ///
+ /// Digit 5.
+ ///
+ D5,
+ ///
+ /// Digit 6.
+ ///
+ D6,
+ ///
+ /// Digit 7.
+ ///
+ D7,
+ ///
+ /// Digit 8.
+ ///
+ D8,
+ ///
+ /// Digit 9.
+ ///
+ D9,
+ ///
/// A key with an unknown mapping was raised.
///
Unknown
diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs
index 4ce014f7f..97d8d4df8 100644
--- a/Terminal.Gui/Core/View.cs
+++ b/Terminal.Gui/Core/View.cs
@@ -2055,5 +2055,26 @@ namespace Terminal.Gui {
return true;
}
+
+ ///
+ /// Gets the key with all the keys modifiers, especially the shift key that sometimes have to be injected later.
+ ///
+ /// The to check.
+ /// The with all the keys modifiers.
+ 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;
+ }
}
}
diff --git a/Terminal.Gui/Views/Menu.cs b/Terminal.Gui/Views/Menu.cs
index 67d27a85f..cc1644ebe 100644
--- a/Terminal.Gui/Views/Menu.cs
+++ b/Terminal.Gui/Views/Menu.cs
@@ -40,14 +40,19 @@ namespace Terminal.Gui {
/// A has a title, an associated help text, and an action to execute on activation.
///
public class MenuItem {
+ ustring title;
+ Key shortCut;
///
/// Initializes a new instance of
///
- public MenuItem ()
+ public MenuItem (Key shortCut = Key.ControlSpace)
{
Title = "";
Help = "";
+ if (shortCut != Key.ControlSpace) {
+ ShortCut = shortCut;
+ }
}
///
@@ -57,26 +62,18 @@ namespace Terminal.Gui {
/// Help text to display.
/// Action to invoke when the menu item is activated.
/// Function to determine if the action can currently be executed.
- /// The parent of this menu item.
- public MenuItem (ustring title, ustring help, Action action, Func canExecute = null, MenuItem parent = null)
+ /// The of this menu item.
+ /// The keystroke combination.
+ public MenuItem (ustring title, ustring help, Action action, Func canExecute = null, MenuItem parent = null, Key shortCut = Key.ControlSpace)
{
Title = title ?? "";
Help = help ?? "";
Action = action;
CanExecute = canExecute;
- bool nextIsHot = false;
- foreach (var x in Title) {
- if (x == '_')
- nextIsHot = true;
- else {
- if (nextIsHot) {
- HotKey = Char.ToUpper ((char)x);
- break;
- }
- nextIsHot = false;
- }
- }
Parent = parent;
+ if (shortCut != Key.ControlSpace) {
+ ShortCut = shortCut;
+ }
}
///
@@ -86,11 +83,41 @@ namespace Terminal.Gui {
///
public Rune HotKey;
+ ///
+ /// This is the global setting that can be used as a global shortcut to invoke the action on the menu.
+ ///
+ public Key ShortCut {
+ get => shortCut;
+ set {
+ if (shortCut != value) {
+ if (GetKeyToString (value).Contains ("Control")) {
+ shortCut = Key.CtrlMask | value;
+ } else {
+ shortCut = value;
+ }
+ ShortCutTag = GetShortCutTag (shortCut);
+ }
+ }
+ }
+
+ ///
+ /// The keystroke combination used in the as string.
+ ///
+ public ustring ShortCutTag { get; private set; } = ustring.Empty;
+
///
/// Gets or sets the title.
///
/// The title.
- public ustring Title { get; set; }
+ public ustring Title {
+ get { return title; }
+ set {
+ if (title != value) {
+ title = value;
+ GetHotKey ();
+ }
+ }
+ }
///
/// Gets or sets the help text for the menu item.
@@ -119,7 +146,8 @@ namespace Terminal.Gui {
}
internal int Width => Title.RuneCount + Help.RuneCount + 1 + 2 +
- (Checked || CheckType.HasFlag (MenuItemCheckStyle.Checked) || CheckType.HasFlag (MenuItemCheckStyle.Radio) ? 2 : 0);
+ (Checked || CheckType.HasFlag (MenuItemCheckStyle.Checked) || CheckType.HasFlag (MenuItemCheckStyle.Radio) ? 2 : 0) +
+ (ShortCutTag.RuneCount > 0 ? ShortCutTag.RuneCount + 2 : 0);
///
/// Sets or gets whether the shows a check indicator or not. See .
@@ -157,6 +185,154 @@ namespace Terminal.Gui {
{
return IsFromSubMenu;
}
+
+ void GetHotKey ()
+ {
+ bool nextIsHot = false;
+ foreach (var x in title) {
+ if (x == '_') {
+ nextIsHot = true;
+ } else {
+ if (nextIsHot) {
+ HotKey = Char.ToUpper ((char)x);
+ break;
+ }
+ nextIsHot = false;
+ HotKey = default;
+ }
+ }
+ }
+
+ ///
+ /// Get the key as string.
+ ///
+ /// The shortcut key.
+ ///
+ public ustring GetShortCutTag (Key shortCut)
+ {
+ if (shortCut == Key.ControlSpace) {
+ return "";
+ }
+
+ var k = (uint)shortCut;
+ var delimiter = MenuBar.ShortCutDelimiter;
+ ustring tag = ustring.Empty;
+ var sCut = GetKeyToString (shortCut).ToString ();
+ if (sCut.Contains ("Control") || (shortCut & Key.CtrlMask) != 0) {
+ tag = "Ctrl";
+ }
+ if ((shortCut & Key.ShiftMask) != 0) {
+ if (!tag.IsEmpty) {
+ tag += delimiter;
+ }
+ tag += "Shift";
+ }
+ if ((shortCut & Key.AltMask) != 0) {
+ if (!tag.IsEmpty) {
+ tag += delimiter;
+ }
+ tag += "Alt";
+ }
+
+ ustring [] keys = ustring.Make (sCut).Split (",");
+ for (int i = 0; i < keys.Length; i++) {
+ var key = keys [i].TrimSpace ();
+ if (key == Key.AltMask.ToString () || key == Key.ShiftMask.ToString () || key == Key.CtrlMask.ToString ()) {
+ continue;
+ }
+ if (!tag.IsEmpty) {
+ tag += delimiter;
+ }
+ if (key.Contains ("Control")) {
+ tag += ((char)key.ElementAt (7)).ToString ();
+ } else if (!key.Contains ("F") && key.Length > 2 && keys.Length == 1) {
+ k = (uint)Key.AltMask + k;
+ tag += ((char)k).ToString ();
+ } else if (key.Length == 2 && key.StartsWith ("D")) {
+ tag += ((char)key.ElementAt (1)).ToString ();
+ } else {
+ tag += key;
+ }
+ }
+
+ return tag;
+ }
+
+ ustring GetKeyToString (Key key)
+ {
+ if (key == Key.ControlSpace) {
+ return "";
+ }
+
+ var mK = key & (Key.AltMask | Key.CtrlMask | Key.ShiftMask);
+ for (uint i = (uint)Key.F1; i < (uint)Key.F12; i++) {
+ if ((key | (Key)i) == key) {
+ mK |= (Key)i;
+ }
+ }
+ var k = key;
+ k &= ~mK;
+ int.TryParse (k.ToString (), out int c);
+ var s = mK == Key.ControlSpace ? "" : mK.ToString ();
+ if (s != "" && (k != Key.ControlSpace || c > 0)) {
+ s += ",";
+ }
+ s += c == 0 ? k == Key.ControlSpace ? "" : k.ToString () : ((char)c).ToString ();
+ return s;
+ }
+
+ ///
+ /// Allows to generate a from a
+ ///
+ /// The key as string.
+ ///
+ public Key CreateShortCutFromTag (ustring tag)
+ {
+ var sCut = tag;
+ if (sCut.IsEmpty) {
+ return default;
+ }
+
+ Key key = Key.ControlSpace;
+ var hasCtrl = false;
+ var delimiter = MenuBar.ShortCutDelimiter;
+
+ ustring [] keys = sCut.Split (MenuBar.ShortCutDelimiter);
+ for (int i = 0; i < keys.Length; i++) {
+ var k = keys [i];
+ if (k == "Ctrl") {
+ hasCtrl = true;
+ key |= Key.CtrlMask;
+ } else if (k == "Shift") {
+ key |= Key.ShiftMask;
+ } else if (k == "Alt") {
+ key |= Key.AltMask;
+ } else if (k.StartsWith ("F") && k.Length > 1) {
+ int.TryParse (k.Substring (1).ToString (), out int n);
+ for (uint j = (uint)Key.F1; j < (uint)Key.F12; j++) {
+ int.TryParse (((Key)j).ToString ().Substring (1), out int f);
+ if (f == n) {
+ key |= (Key)j;
+ }
+ }
+ } else if (k [0] >= 'A' && k [0] <= 'Z') {
+ if (hasCtrl) {
+ var n = k [0] - 'A' + 1;
+ var d = n - (uint)Key.ControlA;
+ key |= (Key)((uint)Key.ControlA + d);
+ } else {
+ key |= (Key)k [0];
+ }
+ } else if (k [0] >= '0' && k [0] <= '9') {
+ //var n = k [0] - (uint)Key.D0 + 1;
+ //var d = n - (uint)Key.D0;
+ //key |= (Key)((uint)Key.D0 + d);
+ key |= (Key)k [0];
+ }
+ }
+
+ return key;
+ }
}
///
@@ -307,7 +483,7 @@ namespace Terminal.Gui {
internal int TitleLength => GetMenuBarItemLength (Title);
- internal bool IsTopLevel { get => Parent == null && (Children == null || Children.Length == 0); }
+ internal bool IsTopLevel { get => Parent == null && (Children == null || Children.Length == 0) && Action != null; }
}
@@ -416,9 +592,16 @@ namespace Terminal.Gui {
i == current ? ColorScheme.Focus : ColorScheme.Normal);
// The help string
- var l = item.Help.RuneCount;
+ var l = item.ShortCutTag.RuneCount == 0 ? item.Help.RuneCount : item.Help.RuneCount + item.ShortCutTag.RuneCount + 2;
Move (Frame.Width - l - 2, 1 + i);
Driver.AddStr (item.Help);
+
+ // The shortcut tag string
+ if (!item.ShortCutTag.IsEmpty) {
+ l = item.ShortCutTag.RuneCount;
+ Move (Frame.Width - l - 2, 1 + i);
+ Driver.AddStr (item.ShortCutTag);
+ }
}
PositionCursor ();
}
@@ -704,6 +887,11 @@ namespace Terminal.Gui {
///
public bool UseKeysUpDownAsKeysLeftRight { get; set; } = true;
+ ///
+ /// Used for change the shortcut delimiter separator.
+ ///
+ public static ustring ShortCutDelimiter { get; set; } = "+";
+
///
/// Initializes a new instance of the .
///
@@ -828,8 +1016,8 @@ namespace Terminal.Gui {
hotColor = ColorScheme.Normal;
normalColor = ColorScheme.Normal;
}
- DrawHotString ($" {menu.Title} ", hotColor, normalColor);
- pos += 1 + menu.TitleLength + 2;
+ DrawHotString (menu.Help.IsEmpty ? $" {menu.Title} " : $" {menu.Title} {menu.Help} ", hotColor, normalColor);
+ pos += 1 + menu.TitleLength + (menu.Help.Length > 0 ? menu.Help.Length + 2 : 0) + 2;
}
PositionCursor ();
}
@@ -843,14 +1031,14 @@ namespace Terminal.Gui {
pos++;
if (IsMenuOpen)
Move (pos + 1, 0);
- else
+ else {
Move (pos + 1, 0);
+ }
return;
+ } else if (IsMenuOpen) {
+ pos += 1 + Menus [i].TitleLength + (Menus [i].Help.Length > 0 ? Menus [i].Help.Length + 2 : 0) + 2;
} else {
- if (IsMenuOpen)
- pos += 1 + Menus [i].TitleLength + 2;
- else
- pos += 2 + Menus [i].TitleLength + 1;
+ pos += 2 + Menus [i].TitleLength + (Menus [i].Help.Length > 0 ? Menus [i].Help.Length + 2 : 0) + 1;
}
}
//Move (0, 0);
@@ -923,7 +1111,7 @@ namespace Terminal.Gui {
}
for (int i = 0; i < index; i++)
- pos += Menus [i].Title.RuneCount + 2;
+ pos += Menus [i].Title.RuneCount + (Menus [i].Help.RuneCount > 0 ? Menus [i].Help.RuneCount + 2 : 0) + 2;
openMenu = new Menu (this, pos, 1, Menus [index]);
openCurrentMenu = openMenu;
openCurrentMenu.previousSubFocused = openMenu;
@@ -1258,6 +1446,44 @@ namespace Terminal.Gui {
return false;
}
+ internal bool FindAndOpenMenuByShortCut (KeyEvent kb, MenuItem [] children = null)
+ {
+ if (children == null) {
+ children = Menus;
+ }
+
+ var key = kb.KeyValue;
+ var keys = 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) {
+ continue;
+ }
+ if ((!(mi is MenuBarItem mbiTopLevel) || mbiTopLevel.IsTopLevel) && mi.ShortCut != Key.ControlSpace && mi.ShortCut == (Key)key) {
+ var action = mi.Action;
+ if (action != null) {
+ Application.MainLoop.AddIdle (() => {
+ action ();
+ return false;
+ });
+ }
+ return true;
+ }
+ if (mi is MenuBarItem menuBarItem && !menuBarItem.IsTopLevel && FindAndOpenMenuByShortCut (kb, menuBarItem.Children)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
private void ProcessMenu (int i, MenuBarItem mi)
{
if (mi.IsTopLevel) {
@@ -1293,7 +1519,7 @@ namespace Terminal.Gui {
OnKeyDown (kb);
OnKeyUp (kb);
return true;
- } else if (kb.IsAlt) {
+ } else if (kb.IsAlt && !kb.IsCtrl && !kb.IsShift) {
if (FindAndOpenMenuByHotkey (kb)) return true;
}
//var kc = kb.KeyValue;
@@ -1358,6 +1584,12 @@ namespace Terminal.Gui {
return true;
}
+ ///
+ public override bool ProcessColdKey (KeyEvent kb)
+ {
+ return FindAndOpenMenuByShortCut (kb);
+ }
+
///
public override bool MouseEvent (MouseEvent me)
{
@@ -1372,7 +1604,7 @@ namespace Terminal.Gui {
int pos = 1;
int cx = me.X;
for (int i = 0; i < Menus.Length; i++) {
- if (cx >= pos && cx < pos + 1 + Menus [i].TitleLength + 2) {
+ if (cx >= pos && cx < pos + 1 + Menus [i].TitleLength + Menus [i].Help.RuneCount + 2) {
if (me.Flags == MouseFlags.Button1Clicked) {
if (Menus [i].IsTopLevel) {
var menu = new Menu (this, i, 0, Menus [i]);
@@ -1424,6 +1656,7 @@ namespace Terminal.Gui {
};
v.MouseEvent (nme);
+ return false;
}
} else if (!(me.View is MenuBar || me.View is Menu) && (me.Flags.HasFlag (MouseFlags.Button1Clicked) ||
me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked || me.Flags == MouseFlags.Button1TripleClicked)) {
diff --git a/Terminal.Gui/Views/TextField.cs b/Terminal.Gui/Views/TextField.cs
index fdd042da0..6dd9e3ec4 100644
--- a/Terminal.Gui/Views/TextField.cs
+++ b/Terminal.Gui/Views/TextField.cs
@@ -345,9 +345,9 @@ namespace Terminal.Gui {
// Needed for the Elmish Wrapper issue https://github.com/DieselMeister/Terminal.Gui.Elmish/issues/2
var oldCursorPos = point;
- switch (kb.Key) {
+ switch (GetModifiersKey (kb)) {
case Key.DeleteChar:
- case Key.ControlD:
+ case Key.ControlD | Key.CtrlMask:
if (ReadOnly)
return true;
@@ -398,7 +398,7 @@ namespace Terminal.Gui {
// Home, C-A
case Key.Home:
- case Key.ControlA:
+ case Key.ControlA | Key.CtrlMask:
ClearAllSelection ();
point = 0;
Adjust ();
@@ -441,7 +441,7 @@ namespace Terminal.Gui {
break;
case Key.CursorLeft:
- case Key.ControlB:
+ case Key.ControlB | Key.CtrlMask:
ClearAllSelection ();
if (point > 0) {
point--;
@@ -450,14 +450,14 @@ namespace Terminal.Gui {
break;
case Key.End:
- case Key.ControlE: // End
+ case Key.ControlE | Key.CtrlMask: // End
ClearAllSelection ();
point = text.Count;
Adjust ();
break;
case Key.CursorRight:
- case Key.ControlF:
+ case Key.ControlF | Key.CtrlMask:
ClearAllSelection ();
if (point == text.Count)
break;
@@ -465,7 +465,7 @@ namespace Terminal.Gui {
Adjust ();
break;
- case Key.ControlK: // kill-to-end
+ case Key.ControlK | Key.CtrlMask: // kill-to-end
if (ReadOnly)
return true;
@@ -478,7 +478,7 @@ namespace Terminal.Gui {
break;
// Undo
- case Key.ControlZ:
+ case Key.ControlZ | Key.CtrlMask:
if (ReadOnly)
return true;
@@ -494,7 +494,7 @@ namespace Terminal.Gui {
break;
//Redo
- case Key.ControlY: // Control-y, yank
+ case Key.ControlY | Key.CtrlMask: // Control-y, yank
if (ReadOnly)
return true;
@@ -552,18 +552,18 @@ namespace Terminal.Gui {
SetNeedsDisplay ();
break;
- case Key.ControlC:
+ case Key.ControlC | Key.CtrlMask:
Copy ();
break;
- case Key.ControlX:
+ case Key.ControlX | Key.CtrlMask:
if (ReadOnly)
return true;
Cut ();
break;
- case Key.ControlV:
+ case Key.ControlV | Key.CtrlMask:
Paste ();
break;
diff --git a/UICatalog/Scenarios/DynamicMenuBar.cs b/UICatalog/Scenarios/DynamicMenuBar.cs
index 4c71bc0ec..d04dd3fbe 100644
--- a/UICatalog/Scenarios/DynamicMenuBar.cs
+++ b/UICatalog/Scenarios/DynamicMenuBar.cs
@@ -19,7 +19,7 @@ namespace UICatalog {
}
}
- class DynamicMenuItemList {
+ public class DynamicMenuItemList {
public ustring Title { get; set; }
public MenuItem MenuItem { get; set; }
@@ -34,22 +34,24 @@ namespace UICatalog {
public override string ToString () => $"{Title}, {MenuItem}";
}
- class DynamicMenuItem {
+ public class DynamicMenuItem {
public ustring title = "_New";
public ustring help = "";
public ustring action = "";
public bool isTopLevel;
public bool hasSubMenu;
public MenuItemCheckStyle checkStyle;
+ public ustring shortCut;
public DynamicMenuItem () { }
- public DynamicMenuItem (ustring title)
+ public DynamicMenuItem (ustring title, bool hasSubMenu = false)
{
this.title = title;
+ this.hasSubMenu = hasSubMenu;
}
- public DynamicMenuItem (ustring title, ustring help, ustring action, bool isTopLevel, bool hasSubMenu, MenuItemCheckStyle checkStyle = MenuItemCheckStyle.NoCheck)
+ public DynamicMenuItem (ustring title, ustring help, ustring action, bool isTopLevel, bool hasSubMenu, MenuItemCheckStyle checkStyle = MenuItemCheckStyle.NoCheck, ustring shortCut = null)
{
this.title = title;
this.help = help;
@@ -57,14 +59,16 @@ namespace UICatalog {
this.isTopLevel = isTopLevel;
this.hasSubMenu = hasSubMenu;
this.checkStyle = checkStyle;
+ this.shortCut = shortCut;
}
}
- class DynamicMenuBarSample : Window {
+ public class DynamicMenuBarSample : Window {
MenuBar _menuBar;
MenuItem _currentMenuBarItem;
int _currentSelectedMenuBar;
MenuItem _currentEditMenuBarItem;
+ ListView _lstMenus;
public DynamicMenuItemModel DataContext { get; set; }
@@ -72,6 +76,22 @@ namespace UICatalog {
{
DataContext = new DynamicMenuItemModel ();
+ var _frmDelimiter = new FrameView ("Delimiter") {
+ X = Pos.Center (),
+ Y = 3,
+ Width = 20,
+ Height = 4
+ };
+
+ var _txtDelimiter = new TextField (MenuBar.ShortCutDelimiter.ToString ()) {
+ X = Pos.Center(),
+ Width = 2,
+ };
+ _txtDelimiter.TextChanged += (_) => MenuBar.ShortCutDelimiter = _txtDelimiter.Text;
+ _frmDelimiter.Add (_txtDelimiter);
+
+ Add (_frmDelimiter);
+
var _frmMenu = new FrameView ("Menus:") {
Y = 7,
Width = Dim.Percent (50),
@@ -144,7 +164,7 @@ namespace UICatalog {
};
_frmMenu.Add (_btnPreviowsParent);
- var _lstMenus = new ListView (new List ()) {
+ _lstMenus = new ListView (new List ()) {
ColorScheme = Colors.Dialog,
X = Pos.Right (_btnPrevious) + 1,
Y = Pos.Top (_btnPrevious) + 2,
@@ -178,124 +198,13 @@ namespace UICatalog {
Add (_frmMenu);
- var _frmMenuDetails = new FrameView ("Menu Details:") {
+
+ var _frmMenuDetails = new DynamicMenuBarDetails ("Menu Details:") {
X = Pos.Right (_frmMenu),
Y = Pos.Top (_frmMenu),
Width = Dim.Fill (),
- Height = Dim.Fill ()
+ Height = Dim.Fill (2)
};
-
- var _lblTitle = new Label ("Title:") {
- Y = 1
- };
- _frmMenuDetails.Add (_lblTitle);
-
- var _txtTitle = new TextField () {
- X = Pos.Right (_lblTitle) + 2,
- Y = Pos.Top (_lblTitle),
- Width = Dim.Fill ()
- };
- _frmMenuDetails.Add (_txtTitle);
-
- var _lblHelp = new Label ("Help:") {
- X = Pos.Left (_lblTitle),
- Y = Pos.Bottom (_lblTitle) + 1
- };
- _frmMenuDetails.Add (_lblHelp);
-
- var _txtHelp = new TextField () {
- X = Pos.Left (_txtTitle),
- Y = Pos.Top (_lblHelp),
- Width = Dim.Fill ()
- };
- _frmMenuDetails.Add (_txtHelp);
-
- var _lblAction = new Label ("Action:") {
- X = Pos.Left (_lblTitle),
- Y = Pos.Bottom (_lblHelp) + 1
- };
- _frmMenuDetails.Add (_lblAction);
-
- var _txtAction = new TextView () {
- ColorScheme = Colors.Dialog,
- X = Pos.Left (_txtTitle),
- Y = Pos.Top (_lblAction),
- Width = Dim.Fill (),
- Height = 5
- };
- _frmMenuDetails.Add (_txtAction);
-
- var _ckbIsTopLevel = new CheckBox ("IsTopLevel") {
- X = Pos.Left (_lblTitle),
- Y = Pos.Bottom (_lblAction) + 5
- };
- _frmMenuDetails.Add (_ckbIsTopLevel);
-
- var _ckbSubMenu = new CheckBox ("Has sub-menus") {
- X = Pos.Left (_lblTitle),
- Y = Pos.Bottom (_ckbIsTopLevel)
- };
- _frmMenuDetails.Add (_ckbSubMenu);
- _ckbIsTopLevel.Toggled += (e) => {
- if (_ckbIsTopLevel.Checked && _currentEditMenuBarItem.Parent != null) {
- MessageBox.ErrorQuery ("Invalid IsTopLevel", "Only menu bar can have top level menu item!", "Ok");
- _ckbIsTopLevel.Checked = false;
- return;
- }
- if (_ckbIsTopLevel.Checked) {
- _ckbSubMenu.Checked = false;
- _ckbSubMenu.SetNeedsDisplay ();
- _txtAction.ReadOnly = false;
- } else {
- _txtAction.ReadOnly = true;
- }
- };
- _ckbSubMenu.Toggled += (e) => {
- if (_ckbSubMenu.Checked) {
- _ckbIsTopLevel.Checked = false;
- _ckbIsTopLevel.SetNeedsDisplay ();
- _txtAction.ReadOnly = true;
- } else {
- _txtAction.ReadOnly = false;
- }
- };
-
- var _rChkLabels = new ustring [] { "NoCheck", "Checked", "Radio" };
- var _rbChkStyle = new RadioGroup (_rChkLabels) {
- X = Pos.Left (_lblTitle),
- Y = Pos.Bottom (_ckbSubMenu) + 1,
- };
- _frmMenuDetails.Add (_rbChkStyle);
-
- var _btnOk = new Button ("Ok") {
- X = Pos.Left (_lblTitle) + 20,
- Y = Pos.Bottom (_rbChkStyle) + 1,
- };
- _btnOk.Clicked += () => {
- if (ustring.IsNullOrEmpty (_txtTitle.Text) && _currentEditMenuBarItem != null) {
- MessageBox.ErrorQuery ("Invalid title", "Must enter a valid title!.", "Ok");
- } else if (_currentEditMenuBarItem != null) {
- var menuItem = new DynamicMenuItem (_txtTitle.Text, _txtHelp.Text,
- _txtAction.Text,
- _ckbIsTopLevel != null ? _ckbIsTopLevel.Checked : false,
- _ckbSubMenu != null ? _ckbSubMenu.Checked : false,
- _rbChkStyle.SelectedItem == 0 ? MenuItemCheckStyle.NoCheck :
- _rbChkStyle.SelectedItem == 1 ? MenuItemCheckStyle.Checked :
- MenuItemCheckStyle.Radio);
- UpdateMenuItem (_currentEditMenuBarItem, menuItem, _lstMenus.SelectedItem);
- }
- };
- _frmMenuDetails.Add (_btnOk);
-
- var _btnCancel = new Button ("Cancel") {
- X = Pos.Right (_btnOk) + 3,
- Y = Pos.Top (_btnOk),
- };
- _btnCancel.Clicked += () => {
- _txtTitle.Text = ustring.Empty;
- };
- _frmMenuDetails.Add (_btnCancel);
-
Add (_frmMenuDetails);
_btnAdd.Clicked += () => {
@@ -305,15 +214,16 @@ namespace UICatalog {
return;
}
- var item = EnterMenuItem (_currentMenuBarItem);
- if (ustring.IsNullOrEmpty (item.title)) {
+ var frameDetails = new DynamicMenuBarDetails (null, _currentMenuBarItem != null);
+ var item = frameDetails.EnterMenuItem ();
+ if (item == null) {
return;
}
if (!(_currentMenuBarItem is MenuBarItem)) {
var parent = _currentMenuBarItem.Parent as MenuBarItem;
var idx = parent.GetChildrenIndex (_currentMenuBarItem);
- _currentMenuBarItem = new MenuBarItem (_currentMenuBarItem.Title, new MenuItem [] { new MenuItem ("_New", "", CreateAction (_currentEditMenuBarItem, new DynamicMenuItem ())) }, _currentMenuBarItem.Parent);
+ _currentMenuBarItem = new MenuBarItem (_currentMenuBarItem.Title, new MenuItem [] { }, _currentMenuBarItem.Parent);
_currentMenuBarItem.CheckType = item.checkStyle;
parent.Children [idx] = _currentMenuBarItem;
} else {
@@ -350,14 +260,18 @@ namespace UICatalog {
if (childrens.Length == 0) {
if (_currentMenuBarItem.Parent == null) {
((MenuBarItem)_currentMenuBarItem).Children = null;
- _currentMenuBarItem.Action = CreateAction (_currentEditMenuBarItem, new DynamicMenuItem (_currentMenuBarItem.Title));
+ _currentMenuBarItem.Action = _frmMenuDetails.CreateAction (_currentEditMenuBarItem, new DynamicMenuItem (_currentMenuBarItem.Title));
} else {
- _currentMenuBarItem = new MenuItem (_currentMenuBarItem.Title, _currentMenuBarItem.Help, CreateAction (_currentEditMenuBarItem, new DynamicMenuItem (_currentEditMenuBarItem.Title)), null, _currentMenuBarItem.Parent);
+ _currentMenuBarItem = new MenuItem (_currentMenuBarItem.Title, _currentMenuBarItem.Help, _frmMenuDetails.CreateAction (_currentEditMenuBarItem, new DynamicMenuItem (_currentEditMenuBarItem.Title)), null, _currentMenuBarItem.Parent);
}
} else {
((MenuBarItem)_currentMenuBarItem).Children = childrens;
}
DataContext.Menus.RemoveAt (_lstMenus.SelectedItem);
+ if (_lstMenus.Source.Count > 0 && _lstMenus.SelectedItem > _lstMenus.Source.Count - 1) {
+ _lstMenus.SelectedItem = _lstMenus.Source.Count - 1;
+ }
+ _lstMenus.SetNeedsDisplay ();
}
};
@@ -419,9 +333,105 @@ namespace UICatalog {
}
};
+ _btnPreviowsParent.Clicked += () => {
+ if (_currentMenuBarItem != null && _currentMenuBarItem.Parent != null) {
+ var mi = _currentMenuBarItem;
+ _currentMenuBarItem = _currentMenuBarItem.Parent as MenuBarItem;
+ SetListViewSource (_currentMenuBarItem, true);
+ var i = ((MenuBarItem)_currentMenuBarItem).GetChildrenIndex (mi);
+ if (i > -1) {
+ _lstMenus.SelectedItem = i;
+ }
+ if (_currentMenuBarItem.Parent != null) {
+ DataContext.Parent = _currentMenuBarItem.Title;
+ } else {
+ DataContext.Parent = ustring.Empty;
+ }
+ } else {
+ DataContext.Parent = ustring.Empty;
+ }
+ };
+
+
+ var _btnOk = new Button ("Ok") {
+ X = Pos.Right (_frmMenu) + 20,
+ Y = Pos.Bottom (_frmMenuDetails),
+ };
+ Add (_btnOk);
+
+ var _btnCancel = new Button ("Cancel") {
+ X = Pos.Right (_btnOk) + 3,
+ Y = Pos.Top (_btnOk),
+ };
+ _btnCancel.Clicked += () => {
+ SetFrameDetails (_currentEditMenuBarItem);
+ };
+ Add (_btnCancel);
+
+ _lstMenus.SelectedItemChanged += (e) => {
+ var menuBarItem = DataContext.Menus.Count > 0 ? DataContext.Menus [e.Item].MenuItem : null;
+ SetFrameDetails (menuBarItem);
+ };
+
+ _btnOk.Clicked += () => {
+ if (ustring.IsNullOrEmpty (_frmMenuDetails._txtTitle.Text) && _currentEditMenuBarItem != null) {
+ MessageBox.ErrorQuery ("Invalid title", "Must enter a valid title!.", "Ok");
+ } else if (_currentEditMenuBarItem != null) {
+ var menuItem = new DynamicMenuItem (_frmMenuDetails._txtTitle.Text, _frmMenuDetails._txtHelp.Text,
+ _frmMenuDetails._txtAction.Text,
+ _frmMenuDetails._ckbIsTopLevel != null ? _frmMenuDetails._ckbIsTopLevel.Checked : false,
+ _frmMenuDetails._ckbSubMenu != null ? _frmMenuDetails._ckbSubMenu.Checked : false,
+ _frmMenuDetails._rbChkStyle.SelectedItem == 0 ? MenuItemCheckStyle.NoCheck :
+ _frmMenuDetails._rbChkStyle.SelectedItem == 1 ? MenuItemCheckStyle.Checked :
+ MenuItemCheckStyle.Radio,
+ _frmMenuDetails._txtShortCut.Text);
+ UpdateMenuItem (_currentEditMenuBarItem, menuItem, _lstMenus.SelectedItem);
+ }
+ };
+
+ _lstMenus.OpenSelectedItem += (e) => {
+ _currentMenuBarItem = DataContext.Menus [e.Item].MenuItem;
+ if (!(_currentMenuBarItem is MenuBarItem)) {
+ MessageBox.ErrorQuery ("Menu Open Error", "Must allows sub menus first!", "Ok");
+ return;
+ }
+ DataContext.Parent = _currentMenuBarItem.Title;
+ DataContext.Menus = new List ();
+ SetListViewSource (_currentMenuBarItem, true);
+ var menuBarItem = DataContext.Menus.Count > 0 ? DataContext.Menus [0].MenuItem : null;
+ SetFrameDetails (menuBarItem);
+ };
+
+ _lstMenus.Enter += (_) => {
+ var menuBarItem = DataContext.Menus.Count > 0 ? DataContext.Menus [_lstMenus.SelectedItem].MenuItem : null;
+ SetFrameDetails (menuBarItem);
+ };
+
+ _btnNext.Clicked += () => {
+ if (_menuBar != null && _currentSelectedMenuBar + 1 < _menuBar.Menus.Length) {
+ _currentSelectedMenuBar++;
+ }
+ SelectCurrentMenuBarItem ();
+ };
+
+ _btnPrevious.Clicked += () => {
+ if (_currentSelectedMenuBar - 1 > -1) {
+ _currentSelectedMenuBar--;
+ }
+ SelectCurrentMenuBarItem ();
+ };
+
+ _lblMenuBar.Enter += (e) => {
+ if (_menuBar?.Menus != null) {
+ _currentMenuBarItem = _menuBar.Menus [_currentSelectedMenuBar];
+ SetFrameDetails (_menuBar.Menus [_currentSelectedMenuBar]);
+ }
+ };
+
_btnAddMenuBar.Clicked += () => {
- var item = EnterMenuItem (null);
- if (ustring.IsNullOrEmpty (item.title)) {
+ var frameDetails = new DynamicMenuBarDetails (null, false);
+ var item = frameDetails.EnterMenuItem ();
+ if (item == null) {
return;
}
@@ -441,11 +451,15 @@ namespace UICatalog {
_menuBar.Menus [_currentSelectedMenuBar] = newMenu;
_lblMenuBar.Text = newMenu.Title;
SetListViewSource (_currentMenuBarItem, true);
- EditMenuBarItem (_menuBar.Menus [_currentSelectedMenuBar]);
+ SetFrameDetails (_menuBar.Menus [_currentSelectedMenuBar]);
_menuBar.SetNeedsDisplay ();
};
_btnRemoveMenuBar.Clicked += () => {
+ if (_menuBar == null || _menuBar.Menus.Length == 0) {
+ return;
+ }
+
if (_menuBar != null && _menuBar.Menus.Length > 0) {
_menuBar.Menus [_currentSelectedMenuBar] = null;
int i = 0;
@@ -474,62 +488,12 @@ namespace UICatalog {
_lblMenuBar.Text = _menuBar.Menus [_currentSelectedMenuBar].Title;
}
SetListViewSource (_currentMenuBarItem, true);
- EditMenuBarItem (null);
+ SetFrameDetails (null);
};
- _lblMenuBar.Enter += (e) => {
- if (_menuBar?.Menus != null) {
- _currentMenuBarItem = _menuBar.Menus [_currentSelectedMenuBar];
- EditMenuBarItem (_menuBar.Menus [_currentSelectedMenuBar]);
- }
- };
- _btnPrevious.Clicked += () => {
- if (_currentSelectedMenuBar - 1 > -1) {
- _currentSelectedMenuBar--;
- }
- SelectCurrentMenuBarItem ();
- };
+ SetFrameDetails ();
- _btnNext.Clicked += () => {
- if (_menuBar != null && _currentSelectedMenuBar + 1 < _menuBar.Menus.Length) {
- _currentSelectedMenuBar++;
- }
- SelectCurrentMenuBarItem ();
- };
-
- _lstMenus.SelectedItemChanged += (e) => {
- var menuBarItem = DataContext.Menus.Count > 0 ? DataContext.Menus [e.Item].MenuItem : null;
- EditMenuBarItem (menuBarItem);
- };
-
- _lstMenus.OpenSelectedItem += (e) => {
- _currentMenuBarItem = DataContext.Menus [e.Item].MenuItem;
- DataContext.Parent = _currentMenuBarItem.Title;
- DataContext.Menus = new List ();
- SetListViewSource (_currentMenuBarItem, true);
- var menuBarItem = DataContext.Menus.Count > 0 ? DataContext.Menus [0].MenuItem : null;
- EditMenuBarItem (menuBarItem);
- };
-
- _btnPreviowsParent.Clicked += () => {
- if (_currentMenuBarItem != null && _currentMenuBarItem.Parent != null) {
- var mi = _currentMenuBarItem;
- _currentMenuBarItem = _currentMenuBarItem.Parent as MenuBarItem;
- SetListViewSource (_currentMenuBarItem, true);
- var i = ((MenuBarItem)_currentMenuBarItem).GetChildrenIndex (mi);
- if (i > -1) {
- _lstMenus.SelectedItem = i;
- }
- if (_currentMenuBarItem.Parent != null) {
- DataContext.Parent = _currentMenuBarItem.Title;
- } else {
- DataContext.Parent = ustring.Empty;
- }
- } else {
- DataContext.Parent = ustring.Empty;
- }
- };
var ustringConverter = new UStringValueConverter ();
var listWrapperConverter = new ListWrapperConverter ();
@@ -539,45 +503,29 @@ namespace UICatalog {
var lstMenus = new Binding (this, "Menus", _lstMenus, "Source", listWrapperConverter);
- ustring GetTargetAction (Action action)
+ void SetFrameDetails (MenuItem menuItem = null)
{
- var me = action.Target;
-
- if (me == null) {
- throw new ArgumentException ();
+ _currentEditMenuBarItem = menuItem;
+ _frmMenuDetails.EditMenuBarItem (menuItem);
+ var f = _btnOk.CanFocus == _frmMenuDetails.CanFocus;
+ if (!f) {
+ _btnOk.CanFocus = _frmMenuDetails.CanFocus;
+ _btnCancel.CanFocus = _frmMenuDetails.CanFocus;
}
- object v = new object ();
- foreach (var field in me.GetType ().GetFields ()) {
- if (field.Name == "item") {
- v = field.GetValue (me);
- }
- }
- return v == null || !(v is DynamicMenuItem item) ? ustring.Empty : item.action;
}
- Action CreateAction (MenuItem menuItem, DynamicMenuItem item)
+ void SelectCurrentMenuBarItem ()
{
- switch (menuItem.CheckType) {
- case MenuItemCheckStyle.NoCheck:
- return new Action (() => MessageBox.ErrorQuery (item.title, item.action, "Ok"));
- case MenuItemCheckStyle.Checked:
- return new Action (() => menuItem.Checked = !menuItem.Checked);
- case MenuItemCheckStyle.Radio:
- break;
+ MenuBarItem menuBarItem = null;
+ if (_menuBar?.Menus != null) {
+ menuBarItem = _menuBar.Menus [_currentSelectedMenuBar];
+ _lblMenuBar.Text = menuBarItem.Title;
}
- return new Action (() => {
- menuItem.Checked = true;
- var parent = menuItem?.Parent as MenuBarItem;
- if (parent != null) {
- var childrens = parent.Children;
- for (int i = 0; i < childrens.Length; i++) {
- var child = childrens [i];
- if (child != menuItem) {
- child.Checked = false;
- }
- }
- }
- });
+ SetFrameDetails (menuBarItem);
+ _currentMenuBarItem = menuBarItem;
+ DataContext.Menus = new List ();
+ SetListViewSource (_currentMenuBarItem, true);
+ _lblParent.Text = ustring.Empty;
}
void SetListViewSource (MenuItem _currentMenuBarItem, bool fill = false)
@@ -598,20 +546,24 @@ namespace UICatalog {
}
}
- void EditMenuBarItem (MenuItem menuBarItem)
+ MenuItem CreateNewMenu (DynamicMenuItem item, MenuItem parent = null)
{
- if (menuBarItem == null) {
- _frmMenuDetails.CanFocus = false;
+ MenuItem newMenu;
+ if (item.hasSubMenu) {
+ newMenu = new MenuBarItem (item.title, new MenuItem [] { }, parent);
+ } else if (parent != null) {
+ newMenu = new MenuItem (item.title, item.help, null, null, parent);
+ newMenu.CheckType = item.checkStyle;
+ newMenu.Action = _frmMenuDetails.CreateAction (newMenu, item);
+ } else if (item.isTopLevel) {
+ newMenu = new MenuBarItem (item.title, item.help, null);
+ newMenu.Action = _frmMenuDetails.CreateAction (newMenu, item);
} else {
- _frmMenuDetails.CanFocus = true;
+ newMenu = new MenuBarItem (item.title, item.help, null);
+ ((MenuBarItem)newMenu).Children [0].Action = _frmMenuDetails.CreateAction (newMenu, item);
}
- _currentEditMenuBarItem = menuBarItem;
- _txtTitle.Text = menuBarItem?.Title ?? "";
- _txtHelp.Text = menuBarItem?.Help ?? "";
- _txtAction.Text = menuBarItem != null && menuBarItem.Action != null ? GetTargetAction (menuBarItem.Action) : ustring.Empty;
- _ckbIsTopLevel.Checked = IsTopLevel (menuBarItem);
- _ckbSubMenu.Checked = HasSubMenus (menuBarItem);
- _rbChkStyle.SelectedItem = (int)(menuBarItem?.CheckType ?? MenuItemCheckStyle.NoCheck);
+
+ return newMenu;
}
void UpdateMenuItem (MenuItem _currentEditMenuBarItem, DynamicMenuItem menuItem, int index)
@@ -625,199 +577,406 @@ namespace UICatalog {
}
if (menuItem.isTopLevel && _currentEditMenuBarItem is MenuBarItem) {
((MenuBarItem)_currentEditMenuBarItem).Children = null;
- _currentEditMenuBarItem.Action = CreateAction (_currentEditMenuBarItem, menuItem);
+ _currentEditMenuBarItem.Action = _frmMenuDetails.CreateAction (_currentEditMenuBarItem, menuItem);
SetListViewSource (_currentEditMenuBarItem, true);
} else if (menuItem.hasSubMenu) {
_currentEditMenuBarItem.Action = null;
if (_currentEditMenuBarItem is MenuBarItem && ((MenuBarItem)_currentEditMenuBarItem).Children == null) {
- ((MenuBarItem)_currentEditMenuBarItem).Children = new MenuItem [] { new MenuItem ("_New", "", CreateAction (_currentEditMenuBarItem, new DynamicMenuItem ())) };
+ ((MenuBarItem)_currentEditMenuBarItem).Children = new MenuItem [] { };
} else if (_currentEditMenuBarItem.Parent != null) {
- UpdateParent (ref _currentEditMenuBarItem);
+ _frmMenuDetails.UpdateParent (ref _currentEditMenuBarItem);
} else {
- _currentEditMenuBarItem = new MenuBarItem (_currentEditMenuBarItem.Title, new MenuItem [] { new MenuItem ("_New", "", CreateAction (_currentEditMenuBarItem, new DynamicMenuItem ())) }, _currentEditMenuBarItem.Parent);
+ _currentEditMenuBarItem = new MenuBarItem (_currentEditMenuBarItem.Title, new MenuItem [] { }, _currentEditMenuBarItem.Parent);
}
SetListViewSource (_currentEditMenuBarItem, true);
} else if (_currentEditMenuBarItem is MenuBarItem && _currentEditMenuBarItem.Parent != null) {
- UpdateParent (ref _currentEditMenuBarItem);
- _currentEditMenuBarItem = new MenuItem (menuItem.title, menuItem.help, CreateAction (_currentEditMenuBarItem, menuItem), null, _currentEditMenuBarItem.Parent);
+ _frmMenuDetails.UpdateParent (ref _currentEditMenuBarItem);
+ _currentEditMenuBarItem = new MenuItem (menuItem.title, menuItem.help, _frmMenuDetails.CreateAction (_currentEditMenuBarItem, menuItem), null, _currentEditMenuBarItem.Parent);
} else {
if (_currentEditMenuBarItem is MenuBarItem) {
((MenuBarItem)_currentEditMenuBarItem).Children = null;
DataContext.Menus = new List ();
}
- _currentEditMenuBarItem.Action = CreateAction (_currentEditMenuBarItem, menuItem);
+ _currentEditMenuBarItem.Action = _frmMenuDetails.CreateAction (_currentEditMenuBarItem, menuItem);
+ _currentEditMenuBarItem.ShortCut = _currentEditMenuBarItem.CreateShortCutFromTag (menuItem.shortCut);
}
if (_currentEditMenuBarItem.Parent == null) {
DataContext.MenuBar = _currentEditMenuBarItem.Title;
} else {
+ if (DataContext.Menus.Count == 0) {
+ DataContext.Menus.Add (new DynamicMenuItemList (_currentEditMenuBarItem.Title, _currentEditMenuBarItem));
+ }
DataContext.Menus [index] = new DynamicMenuItemList (_currentEditMenuBarItem.Title, _currentEditMenuBarItem);
}
_currentEditMenuBarItem.CheckType = menuItem.checkStyle;
- EditMenuBarItem (_currentEditMenuBarItem);
+ SetFrameDetails (_currentEditMenuBarItem);
}
- void UpdateParent (ref MenuItem menuItem)
- {
- var parent = menuItem.Parent as MenuBarItem;
- var idx = parent.GetChildrenIndex (menuItem);
- if (!(menuItem is MenuBarItem)) {
- menuItem = new MenuBarItem (menuItem.Title, new MenuItem [] { new MenuItem ("_New", "", CreateAction (menuItem, new DynamicMenuItem ())) }, menuItem.Parent);
- if (idx > -1) {
- parent.Children [idx] = menuItem;
- }
+
+ _frmMenuDetails.Initialized += (s, e) => _frmMenuDetails.CanFocus = false;
+ }
+ }
+
+ public class DynamicMenuBarDetails : FrameView {
+ public MenuItem _menuItem;
+ public TextField _txtTitle;
+ public TextField _txtHelp;
+ public TextView _txtAction;
+ public CheckBox _ckbIsTopLevel;
+ public CheckBox _ckbSubMenu;
+ public RadioGroup _rbChkStyle;
+ public TextField _txtShortCut;
+
+ bool hasParent;
+
+ public DynamicMenuBarDetails (MenuItem menuItem = null, bool hasParent = false) : this (menuItem == null ? "Adding New Menu." : "Editing Menu.")
+ {
+ _menuItem = menuItem;
+ this.hasParent = hasParent;
+ }
+
+ public DynamicMenuBarDetails (ustring title) : base (title)
+ {
+ var _lblTitle = new Label ("Title:") {
+ Y = 1
+ };
+ Add (_lblTitle);
+
+ _txtTitle = new TextField () {
+ X = Pos.Right (_lblTitle) + 2,
+ Y = Pos.Top (_lblTitle),
+ Width = Dim.Fill ()
+ };
+ Add (_txtTitle);
+
+ var _lblHelp = new Label ("Help:") {
+ X = Pos.Left (_lblTitle),
+ Y = Pos.Bottom (_lblTitle) + 1
+ };
+ Add (_lblHelp);
+
+ _txtHelp = new TextField () {
+ X = Pos.Left (_txtTitle),
+ Y = Pos.Top (_lblHelp),
+ Width = Dim.Fill ()
+ };
+ Add (_txtHelp);
+
+ var _lblAction = new Label ("Action:") {
+ X = Pos.Left (_lblTitle),
+ Y = Pos.Bottom (_lblHelp) + 1
+ };
+ Add (_lblAction);
+
+ _txtAction = new TextView () {
+ ColorScheme = Colors.Dialog,
+ X = Pos.Left (_txtTitle),
+ Y = Pos.Top (_lblAction),
+ Width = Dim.Fill (),
+ Height = 5
+ };
+ Add (_txtAction);
+
+ _ckbIsTopLevel = new CheckBox ("IsTopLevel") {
+ X = Pos.Left (_lblTitle),
+ Y = Pos.Bottom (_lblAction) + 5
+ };
+ Add (_ckbIsTopLevel);
+
+ _ckbSubMenu = new CheckBox ("Has sub-menus") {
+ X = Pos.Left (_lblTitle),
+ Y = Pos.Bottom (_ckbIsTopLevel),
+ Checked = _menuItem == null ? !hasParent : HasSubMenus (_menuItem)
+ };
+ Add (_ckbSubMenu);
+
+ var _rChkLabels = new ustring [] { "NoCheck", "Checked", "Radio" };
+ _rbChkStyle = new RadioGroup (_rChkLabels) {
+ X = Pos.Left (_lblTitle),
+ Y = Pos.Bottom (_ckbSubMenu) + 1,
+ };
+ Add (_rbChkStyle);
+
+ var _lblShortCut = new Label ("ShortCut:") {
+ X = Pos.Right (_ckbSubMenu) + 10,
+ Y = Pos.Top (_ckbSubMenu)
+ };
+ Add (_lblShortCut);
+
+ _txtShortCut = new TextField () {
+ X = Pos.X (_lblShortCut),
+ Y = Pos.Bottom (_lblShortCut),
+ Width = Dim.Fill (),
+ ReadOnly = true
+ };
+ _txtShortCut.KeyDown += (e) => {
+ var k = GetModifiersKey (e.KeyEvent);
+ if (_menuItem == null || ((k & (Key.CtrlMask | Key.ShiftMask | Key.AltMask)) == 0 && !CheckFlagRange (k, Key.F1, Key.F12))) {
+ _txtShortCut.Text = "";
+ return;
+ }
+
+ var s = _menuItem.GetShortCutTag (k);
+ if (s.Contains ("Unknow")) {
+ _txtShortCut.Text = "";
} else {
- menuItem = new MenuItem (menuItem.Title, menuItem.Help, CreateAction (menuItem, new DynamicMenuItem ()), null, menuItem.Parent);
- if (idx > -1) {
- parent.Children [idx] = menuItem;
+ _txtShortCut.Text = s;
+ }
+ e.Handled = true;
+ };
+
+ bool CheckFlagRange (Key key, Key first, Key last)
+ {
+ for (uint i = (uint)first; i < (uint)last; i++) {
+ if ((key | (Key)i) == key) {
+ return true;
}
}
+ return false;
}
- bool IsTopLevel (MenuItem menuItem)
- {
- var topLevel = menuItem as MenuBarItem;
- if (topLevel != null && topLevel.Parent == null && (topLevel.Children == null || topLevel.Children.Length == 0)) {
- return true;
+ _txtShortCut.KeyUp += (e) => {
+ var k = GetModifiersKey (e.KeyEvent);
+ if (_menuItem == null || (k & (Key.CtrlMask | Key.ShiftMask | Key.AltMask)) == 0 || ((k | Key.D0) == 0 && !CheckFlagRange (k, Key.F1, Key.F12))) {
+ return;
+ }
+
+ e.Handled = true;
+ var kVal = (Key)e.KeyEvent.KeyValue;
+ if ((kVal & Key.D0) != 0) {
+
+ } else if ((kVal == Key.CtrlMask || kVal == Key.ShiftMask || kVal == Key.AltMask ||
+ (kVal & (Key.CtrlMask | Key.ShiftMask)) != 0 || (kVal & (Key.CtrlMask | Key.AltMask)) != 0 || (kVal & (Key.ShiftMask | Key.AltMask)) != 0 ||
+ (kVal & (Key.CtrlMask | Key.ShiftMask | Key.AltMask)) != 0) && !kVal.ToString ().Contains ("Control")) {
+ return;
+ }
+ var s = _menuItem.GetShortCutTag (k);
+ if (s.Contains ("Unknow")) {
+ _txtShortCut.Text = "";
} else {
- return false;
+ _txtShortCut.Text = s;
}
- }
+ };
+ Add (_txtShortCut);
- bool HasSubMenus (MenuItem menuItem)
- {
- var menuBarItem = menuItem as MenuBarItem;
- if (menuBarItem != null && menuBarItem.Children != null && menuBarItem.Children.Length > 0) {
- return true;
+ var _btnShortCut = new Button ("Clear ShirtCut") {
+ X = Pos.X (_lblShortCut),
+ Y = Pos.Bottom (_txtShortCut) + 1
+ };
+ _btnShortCut.Clicked += () => {
+ _txtShortCut.Text = "";
+ };
+ Add (_btnShortCut);
+
+ _ckbIsTopLevel.Toggled += (e) => {
+ if ((_menuItem != null && _menuItem.Parent != null && _ckbIsTopLevel.Checked) ||
+ _menuItem == null && hasParent && _ckbIsTopLevel.Checked) {
+ MessageBox.ErrorQuery ("Invalid IsTopLevel", "Only menu bar can have top level menu item!", "Ok");
+ _ckbIsTopLevel.Checked = false;
+ return;
+ }
+ if (_ckbIsTopLevel.Checked) {
+ _ckbSubMenu.Checked = false;
+ _ckbSubMenu.SetNeedsDisplay ();
+ _txtHelp.CanFocus = true;
+ _txtAction.CanFocus = true;
+ _txtShortCut.CanFocus = !_ckbIsTopLevel.Checked && !_ckbSubMenu.Checked;
} else {
- return false;
- }
- }
-
- void SelectCurrentMenuBarItem ()
- {
- MenuBarItem menuBarItem = null;
- if (_menuBar?.Menus != null) {
- menuBarItem = _menuBar.Menus [_currentSelectedMenuBar];
- _lblMenuBar.Text = menuBarItem.Title;
- }
- EditMenuBarItem (menuBarItem);
- _currentMenuBarItem = menuBarItem;
- DataContext.Menus = new List ();
- SetListViewSource (_currentMenuBarItem, true);
- _lblParent.Text = ustring.Empty;
- }
-
- DynamicMenuItem EnterMenuItem (MenuItem menuItem)
- {
- var _lblTitle = new Label (1, 3, "Title:");
- var _txtTitle = new TextField ("_New") {
- X = Pos.Right (_lblTitle) + 2,
- Y = Pos.Top (_lblTitle),
- Width = Dim.Fill (),
- };
- var _lblHelp = new Label ("Help:") {
- X = Pos.Left (_lblTitle),
- Y = Pos.Bottom (_lblTitle) + 1
- };
- var _txtHelp = new TextField () {
- X = Pos.Left (_txtTitle),
- Y = Pos.Top (_lblHelp),
- Width = Dim.Fill (),
- };
- var _lblAction = new Label ("Action:") {
- X = Pos.Left (_lblTitle),
- Y = Pos.Bottom (_lblHelp) + 1
- };
- var _txtAction = new TextView () {
- ColorScheme = Colors.Menu,
- X = Pos.Left (_txtTitle),
- Y = Pos.Top (_lblAction),
- Width = Dim.Fill (),
- Height = 5,
- ReadOnly = true
- };
- var _ckbIsTopLevel = new CheckBox ("IsTopLevel") {
- X = Pos.Left (_lblTitle),
- Y = Pos.Bottom (_lblAction) + 5
- };
- var _ckbSubMenu = new CheckBox ("Has sub-menus") {
- X = Pos.Left (_lblTitle),
- Y = Pos.Bottom (_ckbIsTopLevel),
- Checked = menuItem == null
- };
- _ckbIsTopLevel.Toggled += (e) => {
- if (_ckbIsTopLevel.Checked && menuItem != null) {
- MessageBox.ErrorQuery ("Invalid IsTopLevel", "Only menu bar can have top level menu item!", "Ok");
- _ckbIsTopLevel.Checked = false;
- return;
- }
- if (_ckbIsTopLevel.Checked) {
- _ckbSubMenu.Checked = false;
+ if (_menuItem == null && !hasParent || _menuItem.Parent == null) {
+ _ckbSubMenu.Checked = true;
_ckbSubMenu.SetNeedsDisplay ();
- _txtAction.ReadOnly = false;
- } else {
- _txtAction.ReadOnly = true;
+ _txtShortCut.CanFocus = false;
}
- };
- _ckbSubMenu.Toggled += (e) => {
- if (_ckbSubMenu.Checked) {
- _ckbIsTopLevel.Checked = false;
+ _txtHelp.Text = "";
+ _txtHelp.CanFocus = false;
+ _txtAction.Text = "";
+ _txtAction.CanFocus = false;
+ }
+ };
+ _ckbSubMenu.Toggled += (e) => {
+ if (_ckbSubMenu.Checked) {
+ _ckbIsTopLevel.Checked = false;
+ _ckbIsTopLevel.SetNeedsDisplay ();
+ _txtHelp.Text = "";
+ _txtHelp.CanFocus = false;
+ _txtAction.Text = "";
+ _txtAction.CanFocus = false;
+ _txtShortCut.CanFocus = false;
+ } else {
+ if (!hasParent) {
+ _ckbIsTopLevel.Checked = true;
_ckbIsTopLevel.SetNeedsDisplay ();
- _txtAction.ReadOnly = true;
- } else {
- _txtAction.ReadOnly = false;
+ _txtShortCut.CanFocus = false;
}
- };
- var _rChkLabels = new ustring [] { "NoCheck", "Checked", "Radio" };
- var _rbChkStyle = new RadioGroup (_rChkLabels) {
- X = Pos.Left (_lblTitle),
- Y = Pos.Bottom (_ckbSubMenu) + 1,
- };
- var _btnOk = new Button ("Ok") {
- IsDefault = true,
- };
- _btnOk.Clicked += () => {
- if (ustring.IsNullOrEmpty (_txtTitle.Text)) {
- MessageBox.ErrorQuery ("Invalid title", "Must enter a valid title!.", "Ok");
- } else {
- Application.RequestStop ();
- }
- };
- var _btnCancel = new Button ("Cancel");
- _btnCancel.Clicked += () => {
- _txtTitle.Text = ustring.Empty;
- Application.RequestStop ();
- };
- var _dialog = new Dialog ("Please enter the menu details.", _btnOk, _btnCancel);
- _dialog.Add (_lblTitle, _txtTitle, _lblHelp, _txtHelp, _lblAction, _txtAction, _ckbIsTopLevel, _ckbSubMenu, _rbChkStyle);
- _txtTitle.SetFocus ();
- Application.Run (_dialog);
+ _txtHelp.CanFocus = true;
+ _txtAction.CanFocus = true;
+ _txtShortCut.CanFocus = !_ckbIsTopLevel.Checked && !_ckbSubMenu.Checked;
+ }
+ };
- return new DynamicMenuItem (_txtTitle.Text, _txtHelp.Text, _txtAction.Text, _ckbIsTopLevel != null ? _ckbIsTopLevel.Checked : false, _ckbSubMenu != null ? _ckbSubMenu.Checked : false, _rbChkStyle.SelectedItem == 0 ? MenuItemCheckStyle.NoCheck : _rbChkStyle.SelectedItem == 1 ? MenuItemCheckStyle.Checked : MenuItemCheckStyle.Radio);
+ //Add (_frmMenuDetails);
+
+ }
+
+
+ public DynamicMenuItem EnterMenuItem ()
+ {
+ var valid = false;
+
+ if (_menuItem == null) {
+ var m = new DynamicMenuItem ();
+ _txtTitle.Text = m.title;
+ _txtHelp.Text = m.help;
+ _txtAction.Text = m.action;
+ _ckbIsTopLevel.Checked = false;
+ _ckbSubMenu.Checked = !hasParent;
+ _txtHelp.CanFocus = hasParent;
+ _txtAction.CanFocus = hasParent;
+ _txtShortCut.CanFocus = hasParent;
+ } else {
+ EditMenuBarItem (_menuItem);
}
- MenuItem CreateNewMenu (DynamicMenuItem item, MenuItem parent = null)
- {
- MenuItem newMenu;
- if (item.hasSubMenu) {
- newMenu = new MenuBarItem (item.title, new MenuItem [] { new MenuItem ("_New", "", null) }, parent);
- ((MenuBarItem)newMenu).Children [0].Action = CreateAction (newMenu, new DynamicMenuItem ());
- } else if (parent != null) {
- newMenu = new MenuItem (item.title, item.help, null, null, parent);
- newMenu.CheckType = item.checkStyle;
- newMenu.Action = CreateAction (newMenu, item);
+ var _btnOk = new Button ("Ok") {
+ IsDefault = true,
+ };
+ _btnOk.Clicked += () => {
+ if (ustring.IsNullOrEmpty (_txtTitle.Text)) {
+ MessageBox.ErrorQuery ("Invalid title", "Must enter a valid title!.", "Ok");
} else {
- newMenu = new MenuBarItem (item.title, item.help, null);
- ((MenuBarItem)newMenu).Children [0].Action = CreateAction (newMenu, item);
+ valid = true;
+ Application.RequestStop ();
}
+ };
+ var _btnCancel = new Button ("Cancel");
+ _btnCancel.Clicked += () => {
+ _txtTitle.Text = ustring.Empty;
+ Application.RequestStop ();
+ };
+ var _dialog = new Dialog ("Please enter the menu details.", _btnOk, _btnCancel);
- return newMenu;
+ Width = Dim.Fill ();
+ Height = Dim.Fill () - 1;
+ _dialog.Add (this);
+ _txtTitle.SetFocus ();
+ Application.Run (_dialog);
+
+ if (valid) {
+ return new DynamicMenuItem (_txtTitle.Text, _txtHelp.Text, _txtAction.Text,
+ _ckbIsTopLevel != null ? _ckbIsTopLevel.Checked : false,
+ _ckbSubMenu != null ? _ckbSubMenu.Checked : false,
+ _rbChkStyle.SelectedItem == 0 ? MenuItemCheckStyle.NoCheck :
+ _rbChkStyle.SelectedItem == 1 ? MenuItemCheckStyle.Checked : MenuItemCheckStyle.Radio,
+ _txtShortCut.Text);
+ } else {
+ return null;
+ }
+ }
+
+ public void EditMenuBarItem (MenuItem menuItem)
+ {
+ if (menuItem == null) {
+ hasParent = false;
+ CanFocus = false;
+ return;
+ } else {
+ hasParent = menuItem.Parent != null;
+ CanFocus = true;
+ }
+ _menuItem = menuItem;
+ _txtTitle.Text = menuItem?.Title ?? "";
+ _txtHelp.Text = menuItem?.Help ?? "";
+ _txtAction.Text = menuItem != null && menuItem.Action != null ? GetTargetAction (menuItem.Action) : ustring.Empty;
+ _ckbIsTopLevel.Checked = IsTopLevel (menuItem);
+ _ckbSubMenu.Checked = HasSubMenus (menuItem);
+ _txtHelp.CanFocus = !_ckbSubMenu.Checked;
+ _txtAction.CanFocus = !_ckbSubMenu.Checked;
+ _rbChkStyle.SelectedItem = (int)(menuItem?.CheckType ?? MenuItemCheckStyle.NoCheck);
+ _txtShortCut.Text = menuItem?.ShortCutTag ?? "";
+ _txtShortCut.CanFocus = !_ckbIsTopLevel.Checked && !_ckbSubMenu.Checked;
+ }
+
+ ustring GetTargetAction (Action action)
+ {
+ var me = action.Target;
+
+ if (me == null) {
+ throw new ArgumentException ();
+ }
+ object v = new object ();
+ foreach (var field in me.GetType ().GetFields ()) {
+ if (field.Name == "item") {
+ v = field.GetValue (me);
+ }
+ }
+ return v == null || !(v is DynamicMenuItem item) ? ustring.Empty : item.action;
+ }
+
+ bool IsTopLevel (MenuItem menuItem)
+ {
+ var topLevel = menuItem as MenuBarItem;
+ if (topLevel != null && topLevel.Parent == null && (topLevel.Children == null || topLevel.Children.Length == 0) && topLevel.Action != null) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ bool HasSubMenus (MenuItem menuItem)
+ {
+ var menuBarItem = menuItem as MenuBarItem;
+ if (menuBarItem != null && menuBarItem.Children != null && (menuBarItem.Children.Length > 0 || menuBarItem.Action == null)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public Action CreateAction (MenuItem menuItem, DynamicMenuItem item)
+ {
+ switch (menuItem.CheckType) {
+ case MenuItemCheckStyle.NoCheck:
+ return new Action (() => MessageBox.ErrorQuery (item.title, item.action, "Ok"));
+ case MenuItemCheckStyle.Checked:
+ return new Action (() => menuItem.Checked = !menuItem.Checked);
+ case MenuItemCheckStyle.Radio:
+ break;
+ }
+ return new Action (() => {
+ menuItem.Checked = true;
+ var parent = menuItem?.Parent as MenuBarItem;
+ if (parent != null) {
+ var childrens = parent.Children;
+ for (int i = 0; i < childrens.Length; i++) {
+ var child = childrens [i];
+ if (child != menuItem) {
+ child.Checked = false;
+ }
+ }
+ }
+ });
+ }
+
+ public void UpdateParent (ref MenuItem menuItem)
+ {
+ var parent = menuItem.Parent as MenuBarItem;
+ var idx = parent.GetChildrenIndex (menuItem);
+ if (!(menuItem is MenuBarItem)) {
+ menuItem = new MenuBarItem (menuItem.Title, new MenuItem [] { }, menuItem.Parent);
+ if (idx > -1) {
+ parent.Children [idx] = menuItem;
+ }
+ } else {
+ menuItem = new MenuItem (menuItem.Title, menuItem.Help, CreateAction (menuItem, new DynamicMenuItem ()), null, menuItem.Parent);
+ if (idx > -1) {
+ parent.Children [idx] = menuItem;
+ }
}
}
}
- class DynamicMenuItemModel : INotifyPropertyChanged {
+ public class DynamicMenuItemModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private ustring menuBar;
diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs
index ff61af42f..2fcac5be2 100644
--- a/UICatalog/UICatalog.cs
+++ b/UICatalog/UICatalog.cs
@@ -6,6 +6,7 @@ using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
+using System.Runtime.InteropServices;
using System.Text;
using Terminal.Gui;
using Rune = System.Rune;
@@ -156,11 +157,15 @@ namespace UICatalog {
_menu = new MenuBar (new MenuBarItem [] {
new MenuBarItem ("_File", new MenuItem [] {
- new MenuItem ("_Quit", "", () => Application.RequestStop() )
+ new MenuItem ("_Quit", "", () => Application.RequestStop(), null, null, Key.ControlQ)
}),
new MenuBarItem ("_Color Scheme", CreateColorSchemeMenuItems()),
- new MenuBarItem ("_Diagostics", CreateDiagnosticMenuItems()),
- new MenuBarItem ("_About...", "About this app", () => MessageBox.Query ("About UI Catalog", aboutMessage.ToString(), "_Ok")),
+ new MenuBarItem ("Diag_ostics", CreateDiagnosticMenuItems()),
+ new MenuBarItem ("_Help", new MenuItem [] {
+ new MenuItem ("_gui.cs API Overview", "", () => OpenUrl ("https://migueldeicaza.github.io/gui.cs/articles/overview.html"), null, null, Key.F1),
+ new MenuItem ("gui.cs _README", "", () => OpenUrl ("https://github.com/migueldeicaza/gui.cs"), null, null, Key.F2),
+ new MenuItem ("_About...", "About this app", () => MessageBox.Query ("About UI Catalog", aboutMessage.ToString(), "_Ok"), null, null, Key.ControlA),
+ })
});
_leftPane = new FrameView ("Categories") {
@@ -261,10 +266,14 @@ namespace UICatalog {
static MenuItem [] CreateDiagnosticMenuItems ()
{
+ var index = 0;
+
MenuItem CheckedMenuMenuItem (ustring menuItem, Action action, Func checkFunction)
{
var mi = new MenuItem ();
mi.Title = menuItem;
+ mi.ShortCut = Key.AltMask + index.ToString () [0];
+ index++;
mi.CheckType |= MenuItemCheckStyle.Checked;
mi.Checked = checkFunction ();
mi.Action = () => {
@@ -309,14 +318,15 @@ namespace UICatalog {
List