Skip to content

Commit

Permalink
Fixes gui-cs#2539. Add feature to draw menus with or without border.
Browse files Browse the repository at this point in the history
  • Loading branch information
BDisp committed Apr 15, 2023
1 parent 9aaf84f commit 544d1b4
Show file tree
Hide file tree
Showing 4 changed files with 502 additions and 267 deletions.
53 changes: 34 additions & 19 deletions Terminal.Gui/Views/Menu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -436,15 +436,16 @@ class Menu : View {
internal int current;
internal View previousSubFocused;

internal static Rect MakeFrame (int x, int y, MenuItem [] items, Menu parent = null)
internal static Rect MakeFrame (int x, int y, MenuItem [] items, Menu parent = null, LineStyle border = LineStyle.Single)
{
if (items == null || items.Length == 0) {
return new Rect ();
}
int minX = x;
int minY = y;
int maxW = (items.Max (z => z?.Width) ?? 0) + 2; // This 2 is frame border?
int maxH = items.Length + 2; // This 2 is frame border?
var borderOffset = border != LineStyle.None ? 2 : 0; // This 2 is frame border?
int maxW = (items.Max (z => z?.Width) ?? 0) + borderOffset;
int maxH = items.Length + borderOffset;
if (parent != null && x + maxW > Driver.Cols) {
minX = Math.Max (parent.Frame.Right - parent.Frame.Width - maxW, 0);
}
Expand All @@ -454,8 +455,8 @@ internal static Rect MakeFrame (int x, int y, MenuItem [] items, Menu parent = n
return new Rect (minX, minY, maxW, maxH);
}

public Menu (MenuBar host, int x, int y, MenuBarItem barItems, Menu parent = null)
: base (MakeFrame (x, y, barItems.Children, parent))
public Menu (MenuBar host, int x, int y, MenuBarItem barItems, Menu parent = null, LineStyle border = LineStyle.Single)
: base (MakeFrame (x, y, barItems.Children, parent, border))
{
this.barItems = barItems;
this.host = host;
Expand All @@ -477,8 +478,7 @@ public Menu (MenuBar host, int x, int y, MenuBarItem barItems, Menu parent = nul
WantMousePositionReports = host.WantMousePositionReports;
}

Border.Thickness = new Thickness (1);
Border.BorderStyle = LineStyle.Single;
BorderStyle = host.MenusBorderStyle;

if (Application.Current != null) {
Application.Current.DrawContentComplete += Current_DrawContentComplete;
Expand Down Expand Up @@ -554,7 +554,7 @@ public override void Redraw (Rect bounds)
var item = barItems.Children [i];
Driver.SetAttribute (item == null ? GetNormalColor ()
: i == current ? ColorScheme.Focus : GetNormalColor ());
if (item == null) {
if (item == null && BorderStyle != LineStyle.None) {
Move (-1, i);
Driver.AddRune (Driver.LeftTee);
} else if (Frame.X < Driver.Cols) {
Expand All @@ -577,7 +577,7 @@ public override void Redraw (Rect bounds)
}

if (item == null) {
if (SuperView?.Frame.Right - Frame.X > Frame.Width) {
if (BorderStyle != LineStyle.None && SuperView?.Frame.Right - Frame.X > Frame.Width) {
Move (Frame.Width - 2, i);
Driver.AddRune (Driver.RightTee);
}
Expand Down Expand Up @@ -858,11 +858,12 @@ public override bool MouseEvent (MouseEvent me)
}
host.handled = false;
bool disabled;
var meYOffset = BorderStyle != LineStyle.None ? 1 : 0;
if (me.Flags == MouseFlags.Button1Clicked) {
disabled = false;
if (me.Y < 1)
if (me.Y < meYOffset)
return true;
var meY = me.Y - 1;
var meY = me.Y - meYOffset;
if (meY >= barItems.Children.Length)
return true;
var item = barItems.Children [meY];
Expand All @@ -877,14 +878,14 @@ public override bool MouseEvent (MouseEvent me)
me.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition)) {

disabled = false;
if (me.Y < 1 || me.Y - 1 >= barItems.Children.Length) {
if (me.Y < meYOffset || me.Y - meYOffset >= barItems.Children.Length) {
return true;
}
var item = barItems.Children [me.Y - 1];
var item = barItems.Children [me.Y - meYOffset];
if (item == null) return true;
if (item == null || !item.IsEnabled ()) disabled = true;
if (item != null && !disabled)
current = me.Y - 1;
current = me.Y - meYOffset;
if (host.UseSubMenusSingleFrame || !CheckSubMenu ()) {
SetNeedsDisplay ();
SetParentSetNeedsDisplay ();
Expand Down Expand Up @@ -988,6 +989,11 @@ public class MenuBar : View {
/// <value>The menu array.</value>
public MenuBarItem [] Menus { get; set; }

/// <summary>
/// The default <see cref="LineStyle"/> for <see cref="Menus"/>'s border. The default is <see cref="LineStyle.Single"/>.
/// </summary>
public LineStyle MenusBorderStyle { get; set; } = LineStyle.Single;

private bool useKeysUpDownAsKeysLeftRight = false;

/// <summary>
Expand Down Expand Up @@ -1391,7 +1397,7 @@ internal void OpenMenu (int index, int sIndex = -1, MenuBarItem subMenu = null)
} else {
locationOffset = new Point (superView.Frame.X, superView.Frame.Y);
}
openMenu = new Menu (this, Frame.X + pos + locationOffset.X, Frame.Y + 1 + locationOffset.Y, Menus [index]);
openMenu = new Menu (this, Frame.X + pos + locationOffset.X, Frame.Y + 1 + locationOffset.Y, Menus [index], null, MenusBorderStyle);
openCurrentMenu = openMenu;
openCurrentMenu.previousSubFocused = openMenu;

Expand All @@ -1407,7 +1413,8 @@ internal void OpenMenu (int index, int sIndex = -1, MenuBarItem subMenu = null)
} else {
var last = openSubMenu.Count > 0 ? openSubMenu.Last () : openMenu;
if (!UseSubMenusSingleFrame) {
openCurrentMenu = new Menu (this, last.Frame.Left + last.Frame.Width, last.Frame.Top + 1 + last.current, subMenu, last);
locationOffset = GetLocationOffset ();
openCurrentMenu = new Menu (this, last.Frame.Left + last.Frame.Width + locationOffset.X, last.Frame.Top + locationOffset.Y + last.current, subMenu, last, MenusBorderStyle);
} else {
var first = openSubMenu.Count > 0 ? openSubMenu.First () : openMenu;
var mbi = new MenuItem [2 + subMenu.Children.Length];
Expand All @@ -1418,7 +1425,7 @@ internal void OpenMenu (int index, int sIndex = -1, MenuBarItem subMenu = null)
}
var newSubMenu = new MenuBarItem (mbi);
ViewToScreen (first.Frame.Left, first.Frame.Top, out int rx, out int ry);
openCurrentMenu = new Menu (this, rx, ry, newSubMenu);
openCurrentMenu = new Menu (this, rx, ry, newSubMenu, null, MenusBorderStyle);
last.Visible = false;
Application.GrabMouse (openCurrentMenu);
}
Expand All @@ -1436,6 +1443,14 @@ internal void OpenMenu (int index, int sIndex = -1, MenuBarItem subMenu = null)
IsMenuOpen = true;
}

Point GetLocationOffset ()
{
if (MenusBorderStyle != LineStyle.None) {
return new Point (0, 1);
}
return new Point (-2, 0);
}

/// <summary>
/// Opens the Menu programatically, as though the F9 key were pressed.
/// </summary>
Expand Down Expand Up @@ -1792,7 +1807,7 @@ private void ProcessMenu (int i, MenuBarItem mi)

if (mi.IsTopLevel) {
ViewToScreen (i, 0, out int rx, out int ry);
var menu = new Menu (this, rx, ry, mi);
var menu = new Menu (this, rx, ry, mi, null, MenusBorderStyle);
menu.Run (mi.Action);
menu.Dispose ();
} else {
Expand Down Expand Up @@ -1914,7 +1929,7 @@ public override bool MouseEvent (MouseEvent me)
if (me.Flags == MouseFlags.Button1Clicked) {
if (Menus [i].IsTopLevel) {
ViewToScreen (i, 0, out int rx, out int ry);
var menu = new Menu (this, rx, ry, Menus [i]);
var menu = new Menu (this, rx, ry, Menus [i], null, MenusBorderStyle);
menu.Run (Menus [i].Action);
menu.Dispose ();
} else if (!IsMenuOpen) {
Expand Down
9 changes: 5 additions & 4 deletions Terminal.Gui/Views/Toplevel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -777,10 +777,11 @@ public override void Redraw (Rect bounds)
}
base.Redraw (Bounds);

if (this.MenuBar != null && this.MenuBar.IsMenuOpen && this.MenuBar.openMenu != null) {
// TODO: Hack until we can get compositing working right.
this.MenuBar.openMenu.Redraw (this.MenuBar.openMenu.Bounds);
}
// This is causing the menus drawn incorrectly if UseSubMenusSingleFrame is true
//if (this.MenuBar != null && this.MenuBar.IsMenuOpen && this.MenuBar.openMenu != null) {
// // TODO: Hack until we can get compositing working right.
// this.MenuBar.openMenu.Redraw (this.MenuBar.openMenu.Bounds);
//}
}
}

Expand Down
23 changes: 21 additions & 2 deletions UICatalog/UICatalog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ static Scenario RunUICatalogTopLevel ()
/// the command line) and each time a Scenario ends.
/// </summary>
public class UICatalogTopLevel : Toplevel {
public MenuItem? miIsMenuBorderDisabled;
public MenuItem? miIsMouseDisabled;
public MenuItem? miEnableConsoleScrolling;

Expand Down Expand Up @@ -343,7 +344,7 @@ public UICatalogTopLevel ()
//ContentPane.Tiles.ElementAt (0).ContentView.Add (CategoryListView);

ScenarioListView = new ListView () {
X = Pos.Right(CategoryListView) - 1,
X = Pos.Right (CategoryListView) - 1,
Y = 1,
Width = Dim.Fill (0),
Height = Dim.Fill (1),
Expand Down Expand Up @@ -447,11 +448,29 @@ List<MenuItem []> CreateDiagnosticMenuItems ()
new MenuItem [] { },
CreateEnableConsoleScrollingMenuItems (),
CreateDisabledEnabledMouseItems (),
CreateDisabledEnabledMenuBorder (),
CreateKeybindingsMenuItems ()
};
return menuItems;
}

MenuItem [] CreateDisabledEnabledMenuBorder ()
{
List<MenuItem> menuItems = new List<MenuItem> ();
miIsMenuBorderDisabled = new MenuItem {
Title = "Disable _Menu Border"
};
miIsMenuBorderDisabled.Shortcut = Key.CtrlMask | Key.AltMask | (Key)miIsMenuBorderDisabled!.Title!.ToString ()!.Substring (1, 1) [0];
miIsMenuBorderDisabled.CheckType |= MenuItemCheckStyle.Checked;
miIsMenuBorderDisabled.Action += () => {
miIsMenuBorderDisabled.Checked = (bool)!miIsMenuBorderDisabled.Checked!;
MenuBar.MenusBorderStyle = !(bool)miIsMenuBorderDisabled.Checked ? LineStyle.Single : LineStyle.None;
};
menuItems.Add (miIsMenuBorderDisabled);

return menuItems.ToArray ();
}

MenuItem [] CreateDisabledEnabledMouseItems ()
{
List<MenuItem> menuItems = new List<MenuItem> ();
Expand Down Expand Up @@ -676,7 +695,7 @@ public void ConfigChanged ()
miEnableConsoleScrolling!.Checked = Application.EnableConsoleScrolling;

var height = (UICatalogApp.ShowStatusBar ? 1 : 0);// + (MenuBar.Visible ? 1 : 0);
//ContentPane.Height = Dim.Fill (height);
//ContentPane.Height = Dim.Fill (height);

StatusBar.Visible = UICatalogApp.ShowStatusBar;

Expand Down
Loading

0 comments on commit 544d1b4

Please sign in to comment.