From 01848bc5eed7819a1cdfb09ff93cfb4b0686549c Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Sat, 6 Jan 2018 16:39:18 -0500 Subject: [PATCH] Some work on activation --- Core.cs | 31 +++++++++++ Views/Menu.cs | 139 +++++++++++++++++++++----------------------------- demo.cs | 2 +- 3 files changed, 91 insertions(+), 81 deletions(-) diff --git a/Core.cs b/Core.cs index 750189085..82e3246cd 100644 --- a/Core.cs +++ b/Core.cs @@ -15,6 +15,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Threading; namespace Terminal { @@ -808,6 +809,35 @@ namespace Terminal { throw new NotImplementedException (); } + class MainLoopSyncContext : SynchronizationContext { + Mono.Terminal.MainLoop mainLoop; + + public MainLoopSyncContext (Mono.Terminal.MainLoop mainLoop) + { + this.mainLoop = mainLoop; + } + + public override SynchronizationContext CreateCopy () + { + return new MainLoopSyncContext (MainLoop); + } + + public override void Post (SendOrPostCallback d, object state) + { + mainLoop.AddIdle (() => { + d (state); + return false; + }); + } + + public override void Send (SendOrPostCallback d, object state) + { + mainLoop.Invoke (() => { + d (state); + }); + } + } + /// /// Initializes the Application /// @@ -818,6 +848,7 @@ namespace Terminal { Driver.Init (TerminalResized); MainLoop = new Mono.Terminal.MainLoop (); + SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext (MainLoop)); Top = Toplevel.Create (); focus = Top; } diff --git a/Views/Menu.cs b/Views/Menu.cs index 6a5465fae..7a3514c40 100644 --- a/Views/Menu.cs +++ b/Views/Menu.cs @@ -5,10 +5,9 @@ // Miguel de Icaza (miguel@gnome.org) // // TODO: -// Add accelerator support (ShortCut in MenuItem) +// Add accelerator support, but should also support chords (ShortCut in MenuItem) // Add mouse support // Allow menus inside menus -// Handle actual activation using System; namespace Terminal { @@ -55,29 +54,33 @@ namespace Terminal { public class MenuBarItem { public MenuBarItem (string title, MenuItem [] children) { - Title = title ?? ""; + SetTitle (title ?? ""); Children = children; } + void SetTitle (string title) + { + if (title == null) + title = ""; + Title = title; + int len = 0; + foreach (var ch in Title) { + if (ch == '_') + continue; + len++; + } + TitleLength = len; + } + public string Title { get; set; } public MenuItem [] Children { get; set; } - public int Current { get; set; } - internal int TitleLength { - get { - int len = 0; - foreach (var ch in Title) { - if (ch == '_') - continue; - len++; - } - return len; - } - } + internal int TitleLength { get; private set; } } class Menu : View { MenuBarItem barItems; MenuBar host; + int current; static Rect MakeFrame (int x, int y, MenuItem [] items) { @@ -106,7 +109,7 @@ namespace Terminal { for (int i = 0; i < barItems.Children.Length; i++){ var item = barItems.Children [i]; Move (1, i+1); - Driver.SetAttribute (item == null ? Colors.Base.Focus : i == barItems.Current ? Colors.Menu.Focus : Colors.Menu.Normal); + Driver.SetAttribute (item == null ? Colors.Base.Focus : i == current ? Colors.Menu.Focus : Colors.Menu.Normal); for (int p = 0; p < Frame.Width-2; p++) if (item == null) Driver.AddSpecial (SpecialChar.HLine); @@ -118,8 +121,8 @@ namespace Terminal { Move (2, i + 1); DrawHotString (item.Title, - i == barItems.Current ? Colors.Menu.HotFocus : Colors.Menu.HotNormal, - i == barItems.Current ? Colors.Menu.Focus : Colors.Menu.Normal); + i == current? Colors.Menu.HotFocus : Colors.Menu.HotNormal, + i == current ? Colors.Menu.Focus : Colors.Menu.Normal); // The help string var l = item.Help.Length; @@ -130,22 +133,33 @@ namespace Terminal { public override void PositionCursor () { - Move (2, 1 + barItems.Current); + Move (2, 1 + current); + } + + void Run (Action action) + { + if (action == null) + return; + + Application.MainLoop.AddIdle (() => { + action (); + return false; + }); } public override bool ProcessKey (KeyEvent kb) { switch (kb.Key) { case Key.CursorUp: - barItems.Current--; - if (barItems.Current < 0) - barItems.Current = barItems.Children.Length - 1; + current--; + if (current < 0) + current = barItems.Children.Length - 1; SetNeedsDisplay (); break; case Key.CursorDown: - barItems.Current++; - if (barItems.Current == barItems.Children.Length) - barItems.Current = 0; + current++; + if (current== barItems.Children.Length) + current = 0; SetNeedsDisplay (); break; case Key.CursorLeft: @@ -157,6 +171,24 @@ namespace Terminal { case Key.Esc: host.CloseMenu (); break; + case Key.Enter: + host.CloseMenu (); + Run (barItems.Children [current].Action); + break; + default: + // TODO: rune-ify + if (Char.IsLetterOrDigit ((char)kb.KeyValue)) { + var x = Char.ToUpper ((char)kb.KeyValue); + + foreach (var item in barItems.Children) { + if (item.HotKey == x) { + host.CloseMenu (); + Run (item.Action); + return true; + } + } + } + break; } return true; } @@ -177,28 +209,6 @@ namespace Terminal { selected = -1; } - /// - /// Activates the menubar - /// - public void Activate (int idx) - { - if (idx < 0 || idx > Menus.Length) - throw new ArgumentException ("idx"); - - action = null; - selected = idx; - - foreach (var m in Menus) - m.Current = 0; - - // TODO: Application.Run (this); - selected = -1; - SuperView.SetNeedsDisplay (); - - if (action != null) - action (); - } - public override void Redraw (Rect region) { Move (0, 0); @@ -312,38 +322,14 @@ namespace Terminal { StartMenu (); return true; } + var kc = kb.KeyValue; + return base.ProcessHotKey (kb); } public override bool ProcessKey (KeyEvent kb) { switch (kb.Key) { - case Key.CursorUp: - if (Menus [selected].Children == null) - return false; - - int current = Menus [selected].Current; - do { - current--; - if (current < 0) - current = Menus [selected].Children.Length - 1; - } while (Menus [selected].Children [current] == null); - Menus [selected].Current = current; - - SetNeedsDisplay (); - return true; - - case Key.CursorDown: - if (Menus [selected].Children == null) - return false; - - do { - Menus [selected].Current = (Menus [selected].Current + 1) % Menus [selected].Children.Length; - } while (Menus [selected].Children [Menus [selected].Current] == null); - - SetNeedsDisplay (); - break; - case Key.CursorLeft: selected--; if (selected < 0) @@ -353,13 +339,6 @@ namespace Terminal { selected = (selected + 1) % Menus.Length; break; - case Key.Enter: - if (Menus [selected].Children == null) - return false; - - Selected (Menus [selected].Children [Menus [selected].Current]); - break; - case Key.Esc: case Key.ControlC: //TODO: Running = false; diff --git a/demo.cs b/demo.cs index 136b764ee..8dd460ca0 100644 --- a/demo.cs +++ b/demo.cs @@ -33,7 +33,7 @@ class Demo { var win = new Window (new Rect (0, 1, tframe.Width, tframe.Height-1), "Hello"); var menu = new MenuBar (new MenuBarItem [] { new MenuBarItem ("_File", new MenuItem [] { - new MenuItem ("_New", "Creates new file", null), + new MenuItem ("_New", "Creates new file", () => System.Console.WriteLine ("foo")), new MenuItem ("_Open", "", null), new MenuItem ("_Close", "", null), new MenuItem ("_Quit", "", null)