+ Added IsCurrentTop read-only property to Gui.Toplevel class to allow a more convenient checking if a view's instance is currently on top (active and displayed).

- Fixed an elusive crash that may occur in the Application.RunLoop method due to a null'ed Toplevel.NeedDisplay property. This issue appears to be caused by a race condition that may occur when switching Views (TopLevel) too fast. Extended to all other NeedDisplay checks too.
- ListView control now displays empty rows for Null items in its Items collection, instead of crashing with a NullReferenceException.
- Improved MenuBarItem constructor behaviour by performing an additional sanity check on the MenuItem[] children parameter to ensure its not null. If so, raise an ArgumentNullException. Using an empty array of type MenuItem for this parameter still displays an empty menu as intended.
This commit is contained in:
Fabian R
2020-05-23 18:41:41 -05:00
parent e3e7c29014
commit f2e5b08a88
3 changed files with 28 additions and 12 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;
}