11using Terminal . Gui ;
2- using Terminal . Gui . Text ;
2+ using Terminal . Gui . App ;
3+ using Terminal . Gui . Input ;
34using Terminal . Gui . Views ;
4- using TerminalGuiDesigner . Operations . MenuOperations ;
55
66namespace TerminalGuiDesigner ;
77
@@ -10,6 +10,8 @@ namespace TerminalGuiDesigner;
1010/// </summary>
1111public static class MenuBarExtensions
1212{
13+ /// <summary>The title used to mark a <see cref="MenuItem"/> as a separator in the designer.</summary>
14+ public const string SeparatorTitle = "---" ;
1315 /// <summary>
1416 /// Gets the top level selected <see cref="MenuBarItem"/> in the <paramref name="menuBar"/>
1517 /// or null if it is not open/no selection is set. Note that this is the top level menu item only
@@ -19,20 +21,16 @@ public static class MenuBarExtensions
1921 /// <returns>Selected <see cref="MenuItem"/> or null if none.</returns>
2022 public static MenuBarItem ? GetSelectedMenuItem ( this MenuBar menuBar )
2123 {
22- int selected = menuBar . GetNonNullNonPublicFieldValue < int , MenuBar > ( "selected" ) ;
24+ if ( menuBar . Focused is MenuBarItem mbi )
25+ return mbi ;
2326
24- if ( selected < 0 || selected >= menuBar . SubViews . OfType < MenuBarItem > ( ) . Count ( ) )
25- {
26- return null ;
27- }
28-
29- return menuBar . SubViews . OfType < MenuBarItem > ( ) . ElementAt ( selected ) ;
27+ return menuBar . SubViews . OfType < MenuBarItem > ( ) . FirstOrDefault ( ) ;
3028 }
3129
3230 /// <summary>
3331 /// Walks all menus in <paramref name="menuBar"/> and replaces any <see cref="Line"/> views
3432 /// (produced by code generation for separators) with sentinel <see cref="MenuItem"/> instances
35- /// whose <see cref="MenuItem.Title"/> is <see cref="ConvertMenuItemToSeperatorOperation. SeparatorTitle"/>.
33+ /// whose <see cref="MenuItem.Title"/> is <see cref="SeparatorTitle"/>.
3634 /// Call this after loading a <see cref="MenuBar"/> from generated code.
3735 /// </summary>
3836 public static void ConvertLineSeparatorsToSentinels ( this MenuBar menuBar )
@@ -60,7 +58,7 @@ private static void ConvertLineSeparatorsInMenu(Menu menu)
6058 foreach ( var v in allViews )
6159 {
6260 menu . Add ( v is Line
63- ? new MenuItem { Title = ConvertMenuItemToSeperatorOperation . SeparatorTitle }
61+ ? new MenuItem { Title = SeparatorTitle }
6462 : v ) ;
6563 }
6664 }
@@ -85,48 +83,25 @@ private static void ConvertLineSeparatorsInMenu(Menu menu)
8583 /// <param name="menuBar"><see cref="MenuBar"/> you want to find the clicked <see cref="MenuBarItem"/> (top level menu) for.</param>
8684 /// <param name="screenX">Screen coordinate of the click in X.</param>
8785 /// <returns>The <see cref="MenuBarItem"/> under the mouse at this position or null (only considers X).</returns>
88- public static MenuBarItem ? ScreenToMenuBarItem ( this MenuBar menuBar , int screenX )
86+ public static MenuBarItem ? ScreenToMenuBarItem ( this MenuBar menuBar , IApplication application , Mouse mouse )
8987 {
90- // These might be changed in Terminal.Gui library
91- // TODO: Maybe load these from a config file, so we aren't at TG's mercy
92- const int initialWhitespace = 1 ;
93- const int afterEachItemWhitespace = 2 ;
88+ var hit = menuBar . HitTest ( application , mouse , out _ , out _ ) ;
9489
95- if ( menuBar . SubViews . OfType < MenuBarItem > ( ) . Count ( ) == 0 )
90+ if ( hit == null )
9691 {
9792 return null ;
9893 }
9994
100- var clientPoint = menuBar . ScreenToViewport ( new Point ( screenX , 0 ) ) ;
101-
102- // if click is not in our client area
103- if ( clientPoint . X < initialWhitespace )
95+ if ( hit is MenuBarItem mbi )
10496 {
105- return null ;
97+ return mbi ;
10698 }
107-
108- // Calculate the x display positions of each menu
109- int distance = initialWhitespace ;
110- Dictionary < int , MenuBarItem ? > menuXLocations = new ( ) ;
111-
112- foreach ( var mb in menuBar . SubViews . OfType < MenuBarItem > ( ) )
113- {
114- menuXLocations . Add ( distance , mb ) ;
115- distance += mb . Title . GetColumns ( ) + afterEachItemWhitespace ;
116- }
117-
118- // anything after this is not a click on a menu
119- menuXLocations . Add ( distance , null ) ;
120-
121- // LastOrDefault does not work with Dictionaries, if we somehow still have a point outside bounds
122- // of anything then just return null;
123- if ( ! menuXLocations . Any ( m => m . Key <= clientPoint . X ) )
99+ if ( hit . SuperView is MenuBarItem super )
124100 {
125- return null ;
101+ return super ;
126102 }
127103
128- // Return the last menu item that begins rendering before this X point
129- return menuXLocations . Last ( m => m . Key <= clientPoint . X ) . Value ;
104+ return null ;
130105 }
131106
132107 /// <summary>
0 commit comments