From 9d3633680825e6134a4b694cacaa2f1d06acd3de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Kov=C3=A1cs?= Date: Thu, 17 Aug 2023 16:41:44 +0200 Subject: [PATCH] RenderEmpty fixes --- src/Library/TerminalUI/Controls/Border.cs | 63 +++++++++++++++---- .../TerminalUI/Controls/ContentView.cs | 3 +- src/Library/TerminalUI/Controls/Grid.cs | 4 +- src/Library/TerminalUI/Controls/ListView.cs | 16 +++-- src/Library/TerminalUI/Controls/TextBlock.cs | 3 +- src/Library/TerminalUI/RenderEngine.cs | 8 ++- 6 files changed, 70 insertions(+), 27 deletions(-) diff --git a/src/Library/TerminalUI/Controls/Border.cs b/src/Library/TerminalUI/Controls/Border.cs index 0394c4d..5cfb224 100644 --- a/src/Library/TerminalUI/Controls/Border.cs +++ b/src/Library/TerminalUI/Controls/Border.cs @@ -7,6 +7,24 @@ namespace TerminalUI.Controls; public sealed partial class Border : ContentView, T>, IDisplayView { + private record struct RenderState( + Position Position, + Size Size, + Thickness BorderThickness, + Thickness Padding, + char TopChar, + char LeftChar, + char RightChar, + char BottomChar, + char TopLeftChar, + char TopRightChar, + char BottomLeftChar, + char BottomRightChar, + IColor? Fill + ); + + private RenderState _lastRenderState; + [Notify] private Thickness _borderThickness = 1; [Notify] private Thickness _padding = 0; [Notify] private char _topChar = '─'; @@ -59,6 +77,27 @@ public sealed partial class Border : ContentView, T>, IDisplayView var backgroundColor = Background ?? renderContext.Background; var foregroundColor = Foreground ?? renderContext.Foreground; var fillColor = Fill ?? Background ?? renderContext.Background; + + var renderState = new RenderState( + position, + size, + _borderThickness, + _padding, + _topChar, + _leftChar, + _rightChar, + _bottomChar, + _topLeftChar, + _topRightChar, + _bottomLeftChar, + _bottomRightChar, + fillColor + ); + var skipBorderRender = !renderContext.ForceRerender && !NeedsRerender(renderState); + if (!skipBorderRender) + { + _lastRenderState = renderState; + } var childPosition = new Position(X: position.X + _borderThickness.Left, Y: position.Y + _borderThickness.Top); var childSize = new Size( @@ -96,7 +135,7 @@ public sealed partial class Border : ContentView, T>, IDisplayView SetStyleColor(renderContext, foregroundColor, backgroundColor); } - var updateCellsOnly = !contentRendered; + var updateCellsOnly = !contentRendered || skipBorderRender; RenderTopBorder(renderContext, position, size, updateCellsOnly); RenderBottomBorder(renderContext, position, size, updateCellsOnly); RenderLeftBorder(renderContext, position, size, updateCellsOnly); @@ -110,7 +149,7 @@ public sealed partial class Border : ContentView, T>, IDisplayView if (fillColor != null) { SetStyleColor(renderContext, foregroundColor, fillColor); - + // Use the same array that children use. Also use that area, so we working only inside the border Array2DHelper.RenderEmpty( renderContext.ConsoleDriver, @@ -120,20 +159,22 @@ public sealed partial class Border : ContentView, T>, IDisplayView childPositionWithoutPadding, childSizeWithoutPadding ); - - //Write back the changes to the original array - Array2DHelper.CombineArray2Ds( - renderContext.UpdatedCells, - borderChildUpdatedCells, - new Position(0, 0), - renderContext.UpdatedCells, - (a, b) => (a ?? false) || (b ?? false) - ); } + //Write back the changes to the original array + Array2DHelper.CombineArray2Ds( + renderContext.UpdatedCells, + borderChildUpdatedCells, + new Position(0, 0), + renderContext.UpdatedCells, + (a, b) => (a ?? false) || (b ?? false) + ); + return contentRendered; } + private bool NeedsRerender(RenderState renderState) => renderState != _lastRenderState; + private void RenderTopBorder(in RenderContext renderContext, Position position, Size size, bool updateCellsOnly) { position = position with {X = position.X + _borderThickness.Left}; diff --git a/src/Library/TerminalUI/Controls/ContentView.cs b/src/Library/TerminalUI/Controls/ContentView.cs index 52dd73d..45a5073 100644 --- a/src/Library/TerminalUI/Controls/ContentView.cs +++ b/src/Library/TerminalUI/Controls/ContentView.cs @@ -44,11 +44,10 @@ public abstract partial class ContentView private bool DefaultContentRender(in RenderContext renderContext, Position position, Size size) { - if (Content is null || !Content.IsVisible) + if (Content is null) { if (_placeholderRenderDone) return false; _placeholderRenderDone = true; - RenderEmpty(renderContext, position, size, false); return true; } diff --git a/src/Library/TerminalUI/Controls/Grid.cs b/src/Library/TerminalUI/Controls/Grid.cs index 70aca32..008063f 100644 --- a/src/Library/TerminalUI/Controls/Grid.cs +++ b/src/Library/TerminalUI/Controls/Grid.cs @@ -239,8 +239,7 @@ public sealed class Grid : ChildCollectionView, T>, IVisibilityChange if (!viewsByPosition.TryGetValue((column, row), out var children)) { - RenderEmpty(context, renderPosition, renderSize, false); - return true; + return false; } var needsRerender = children.Any(forceRerenderChildren.Contains); @@ -248,7 +247,6 @@ public sealed class Grid : ChildCollectionView, T>, IVisibilityChange if (needsRerender) { updatedContext = context with {ForceRerender = true}; - RenderEmpty(updatedContext, renderPosition, renderSize, false); } //This implies that children further back in the list will be rendered on top of children placed before in the list. diff --git a/src/Library/TerminalUI/Controls/ListView.cs b/src/Library/TerminalUI/Controls/ListView.cs index 7789572..19a8fae 100644 --- a/src/Library/TerminalUI/Controls/ListView.cs +++ b/src/Library/TerminalUI/Controls/ListView.cs @@ -218,6 +218,7 @@ public sealed partial class ListView : View : View : View : View, T>, IDisplayView if (_textLines is null) { - if (_placeholderRenderDone) + if (!_placeholderRenderDone) { _placeholderRenderDone = true; RenderEmpty(renderContext, position, size, skipRender); + return true; } return false; diff --git a/src/Library/TerminalUI/RenderEngine.cs b/src/Library/TerminalUI/RenderEngine.cs index c760b83..1472332 100644 --- a/src/Library/TerminalUI/RenderEngine.cs +++ b/src/Library/TerminalUI/RenderEngine.cs @@ -146,7 +146,13 @@ public class RenderEngine : IRenderEngine } driver.ResetStyle(); - Array2DHelper.RenderEmpty(driver, _updatedCells, _filledCells, _applicationContext.EmptyCharacter, initialPosition, size); + Array2DHelper.RenderEmpty( + driver, + _updatedCells, + _filledCells, + _applicationContext.EmptyCharacter, + initialPosition, + size); (_lastFilledCells, _filledCells) = (_filledCells, _lastFilledCells);