Merge pull request #525 from KDERazorback/master

Edge case handling and Quality-of-life improvements on Core, ListView and MenuBar
This commit is contained in:
Charlie Kindel
2020-05-23 19:45:45 -06:00
committed by GitHub
3 changed files with 62 additions and 39 deletions

View File

@@ -350,6 +350,15 @@ namespace Terminal.Gui {
/// <value>The identifier.</value>
public ustring Id { get; set; } = "";
/// <summary>
/// Returns a value indicating if this View is currently on Top (Active)
/// </summary>
public bool IsCurrentTop {
get {
return Application.Current == this;
}
}
/// <summary>
/// Gets or sets a value indicating whether this <see cref="View"/> want mouse position reports.
/// </summary>
@@ -531,7 +540,7 @@ namespace Terminal.Gui {
/// <param name="region">The region that must be flagged for repaint.</param>
public void SetNeedsDisplay (Rect region)
{
if (NeedDisplay.IsEmpty)
if (NeedDisplay == null || NeedDisplay.IsEmpty)
NeedDisplay = region;
else {
var x = Math.Min (NeedDisplay.X, region.X);
@@ -1015,7 +1024,7 @@ namespace Terminal.Gui {
if (subviews != null) {
foreach (var view in subviews) {
if (!view.NeedDisplay.IsEmpty || view.childNeedsDisplay) {
if (view.NeedDisplay != null && (!view.NeedDisplay.IsEmpty || view.childNeedsDisplay)) {
if (view.Frame.IntersectsWith (clipRect) && view.Frame.IntersectsWith (region)) {
// FIXED: optimize this by computing the intersection of region and view.Bounds
@@ -1704,8 +1713,8 @@ namespace Terminal.Gui {
{
Application.CurrentView = this;
if (this == Application.Top || this == Application.Current) {
if (!NeedDisplay.IsEmpty) {
if (IsCurrentTop) {
if (NeedDisplay != null && !NeedDisplay.IsEmpty) {
Driver.SetAttribute (Colors.TopLevel.Normal);
Clear (region);
Driver.SetAttribute (Colors.Base.Normal);
@@ -1887,7 +1896,7 @@ namespace Terminal.Gui {
{
Application.CurrentView = this;
if (!NeedDisplay.IsEmpty) {
if (NeedDisplay != null && !NeedDisplay.IsEmpty) {
DrawFrameWindow ();
}
contentView.Redraw (contentView.Bounds);
@@ -2487,7 +2496,7 @@ namespace Terminal.Gui {
Iteration?.Invoke (null, EventArgs.Empty);
} else if (wait == false)
return;
if (!state.Toplevel.NeedDisplay.IsEmpty || state.Toplevel.childNeedsDisplay) {
if (state.Toplevel.NeedDisplay != null && (!state.Toplevel.NeedDisplay.IsEmpty || state.Toplevel.childNeedsDisplay)) {
state.Toplevel.Redraw (state.Toplevel.Bounds);
if (DebugDrawBounds)
DrawBounds (state.Toplevel);

View File

@@ -593,12 +593,16 @@ namespace Terminal.Gui {
{
container.Move (col, line);
var t = src [item];
if (t is ustring) {
RenderUstr (driver, (ustring)t, col, line, width);
} else if (t is string) {
RenderUstr (driver, (string)t, col, line, width);
} else
RenderUstr (driver, t.ToString (), col, line, width);
if (t == null) {
RenderUstr (driver, ustring.Make(""), col, line, width);
} else {
if (t is ustring) {
RenderUstr (driver, (ustring)t, col, line, width);
} else if (t is string) {
RenderUstr (driver, (string)t, col, line, width);
} else
RenderUstr (driver, t.ToString (), col, line, width);
}
}
/// <summary>

View File

@@ -162,6 +162,9 @@ namespace Terminal.Gui {
/// <param name="children">The items in the current menu.</param>
public MenuBarItem (ustring title, MenuItem [] children)
{
if (children == null)
throw new ArgumentNullException (nameof (children), "The parameter cannot be null. Use an empty array instead.");
SetTitle (title ?? "");
Children = children;
}
@@ -320,7 +323,7 @@ namespace Terminal.Gui {
public override void PositionCursor ()
{
if (host == null || !host.isMenuClosed)
if (host == null || host.IsMenuOpen)
if (barItems.IsTopLevel) {
host.PositionCursor ();
} else
@@ -403,11 +406,11 @@ namespace Terminal.Gui {
var item = barItems.Children [current];
if (item == null || !item.IsEnabled ()) disabled = true;
if (host.UseKeysUpDownAsKeysLeftRight && barItems.Children [current]?.SubMenu != null &&
!disabled && !host.isMenuClosed) {
!disabled && host.IsMenuOpen) {
CheckSubMenu ();
break;
}
if (host.isMenuClosed)
if (!host.IsMenuOpen)
host.OpenMenu (host.selected);
} while (barItems.Children [current] == null || disabled);
SetNeedsDisplay ();
@@ -563,7 +566,7 @@ namespace Terminal.Gui {
selectedSub = -1;
ColorScheme = Colors.Menu;
WantMousePositionReports = true;
isMenuClosed = true;
IsMenuOpen = false;
}
bool openedByAltKey;
@@ -584,14 +587,14 @@ namespace Terminal.Gui {
{
if (keyEvent.IsAlt) {
// User pressed Alt - this may be a precursor to a menu accelerator (e.g. Alt-F)
if (!keyEvent.IsCtrl && openedByAltKey && isMenuClosed && openMenu == null && ((uint)keyEvent.Key & (uint)Key.CharMask) == 0) {
if (!keyEvent.IsCtrl && openedByAltKey && !IsMenuOpen && openMenu == null && ((uint)keyEvent.Key & (uint)Key.CharMask) == 0) {
// There's no open menu, the first menu item should be highlight.
// The right way to do this is to SetFocus(MenuBar), but for some reason
// that faults.
//Activate (0);
//StartMenu ();
isMenuClosed = false;
IsMenuOpen = true;
selected = 0;
CanFocus = true;
lastFocused = SuperView.MostFocused;
@@ -606,7 +609,7 @@ namespace Terminal.Gui {
if (openMenu != null)
CloseAllMenus ();
openedByAltKey = false;
isMenuClosed = true;
IsMenuOpen = false;
selected = -1;
CanFocus = false;
if (lastFocused != null)
@@ -658,13 +661,13 @@ namespace Terminal.Gui {
for (int i = 0; i < Menus.Length; i++) {
if (i == selected) {
pos++;
if (!isMenuClosed)
if (IsMenuOpen)
Move (pos + 1, 0);
else
Move (pos + 1, 0);
return;
} else {
if (!isMenuClosed)
if (IsMenuOpen)
pos += 1 + Menus [i].TitleLength + 2;
else
pos += 2 + Menus [i].TitleLength + 1;
@@ -695,12 +698,11 @@ namespace Terminal.Gui {
View previousFocused;
internal bool isMenuOpening;
internal bool isMenuClosing;
internal bool isMenuClosed;
/// <summary>
/// True of the menu is open; otherwise false.
/// True if the menu is open; otherwise false.
/// </summary>
public bool MenuOpen { get; set; }
public bool IsMenuOpen { get; protected set; }
View lastFocused;
@@ -748,12 +750,13 @@ namespace Terminal.Gui {
break;
}
isMenuOpening = false;
isMenuClosed = false;
MenuOpen = true;
IsMenuOpen = true;
}
// Starts the menu from a hotkey
void StartMenu ()
/// <summary>
/// Opens the current Menu programatically.
/// </summary>
public void OpenMenu ()
{
if (openMenu != null)
return;
@@ -778,6 +781,13 @@ namespace Terminal.Gui {
SetNeedsDisplay ();
}
/// <summary>
/// Closes the current Menu programatically, if open.
/// </summary>
public void CloseMenu()
{
CloseMenu (false, false);
}
internal void CloseMenu (bool reopen = false, bool isSubMenu = false)
{
isMenuClosing = true;
@@ -799,12 +809,12 @@ namespace Terminal.Gui {
if (!reopen)
selected = -1;
LastFocused.SuperView?.SetFocus (LastFocused);
IsMenuOpen = false;
} else {
SuperView.SetFocus (this);
isMenuClosed = true;
IsMenuOpen = false;
PositionCursor ();
}
isMenuClosed = true;
break;
case true:
@@ -816,7 +826,7 @@ namespace Terminal.Gui {
break;
}
isMenuClosing = false;
MenuOpen = false;
IsMenuOpen = false;
}
void RemoveSubMenu (int index)
@@ -879,7 +889,7 @@ namespace Terminal.Gui {
if (LastFocused != null && LastFocused != this)
selected = -1;
}
isMenuClosed = true;
IsMenuOpen = false;
openedByHotKey = false;
openedByAltKey = false;
}
@@ -993,8 +1003,8 @@ namespace Terminal.Gui {
public override bool ProcessHotKey (KeyEvent kb)
{
if (kb.Key == Key.F9) {
if (isMenuClosed)
StartMenu ();
if (!IsMenuOpen)
OpenMenu ();
else
CloseAllMenus ();
return true;
@@ -1085,7 +1095,7 @@ namespace Terminal.Gui {
for (int i = 0; i < Menus.Length; i++) {
if (cx > pos && me.X < pos + 1 + Menus [i].TitleLength) {
if (selected == i && (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked) &&
!isMenuClosed) {
IsMenuOpen) {
Application.UngrabMouse ();
if (Menus [i].IsTopLevel) {
var menu = new Menu (this, i, 0, Menus [i]);
@@ -1094,7 +1104,7 @@ namespace Terminal.Gui {
CloseMenu ();
}
} else if ((me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked) &&
isMenuClosed) {
!IsMenuOpen) {
if (Menus [i].IsTopLevel) {
var menu = new Menu (this, i, 0, Menus [i]);
menu.Run (Menus [i].Action);
@@ -1102,12 +1112,12 @@ namespace Terminal.Gui {
Activate (i);
}
} else if (selected != i && selected > -1 && me.Flags == MouseFlags.ReportMousePosition) {
if (!isMenuClosed) {
if (IsMenuOpen) {
CloseMenu ();
Activate (i);
}
} else {
if (!isMenuClosed)
if (IsMenuOpen)
Activate (i);
}
return true;
@@ -1139,7 +1149,7 @@ namespace Terminal.Gui {
handled = false;
return false;
}
} else if (isMenuClosed && (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked ||
} else if (!IsMenuOpen && (me.Flags == MouseFlags.Button1Pressed || me.Flags == MouseFlags.Button1DoubleClicked ||
me.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition))) {
Application.GrabMouse (current);
} else {