RenderEmpty fixes

This commit is contained in:
2023-08-17 16:41:44 +02:00
parent df4fe93c81
commit 9d36336808
6 changed files with 70 additions and 27 deletions

View File

@@ -7,6 +7,24 @@ namespace TerminalUI.Controls;
public sealed partial class Border<T> : ContentView<Border<T>, T>, IDisplayView public sealed partial class Border<T> : ContentView<Border<T>, 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 _borderThickness = 1;
[Notify] private Thickness _padding = 0; [Notify] private Thickness _padding = 0;
[Notify] private char _topChar = '─'; [Notify] private char _topChar = '─';
@@ -60,6 +78,27 @@ public sealed partial class Border<T> : ContentView<Border<T>, T>, IDisplayView
var foregroundColor = Foreground ?? renderContext.Foreground; var foregroundColor = Foreground ?? renderContext.Foreground;
var fillColor = Fill ?? Background ?? renderContext.Background; 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 childPosition = new Position(X: position.X + _borderThickness.Left, Y: position.Y + _borderThickness.Top);
var childSize = new Size( var childSize = new Size(
Width: size.Width - _borderThickness.Left - _borderThickness.Right, Width: size.Width - _borderThickness.Left - _borderThickness.Right,
@@ -96,7 +135,7 @@ public sealed partial class Border<T> : ContentView<Border<T>, T>, IDisplayView
SetStyleColor(renderContext, foregroundColor, backgroundColor); SetStyleColor(renderContext, foregroundColor, backgroundColor);
} }
var updateCellsOnly = !contentRendered; var updateCellsOnly = !contentRendered || skipBorderRender;
RenderTopBorder(renderContext, position, size, updateCellsOnly); RenderTopBorder(renderContext, position, size, updateCellsOnly);
RenderBottomBorder(renderContext, position, size, updateCellsOnly); RenderBottomBorder(renderContext, position, size, updateCellsOnly);
RenderLeftBorder(renderContext, position, size, updateCellsOnly); RenderLeftBorder(renderContext, position, size, updateCellsOnly);
@@ -120,20 +159,22 @@ public sealed partial class Border<T> : ContentView<Border<T>, T>, IDisplayView
childPositionWithoutPadding, childPositionWithoutPadding,
childSizeWithoutPadding 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; return contentRendered;
} }
private bool NeedsRerender(RenderState renderState) => renderState != _lastRenderState;
private void RenderTopBorder(in RenderContext renderContext, Position position, Size size, bool updateCellsOnly) private void RenderTopBorder(in RenderContext renderContext, Position position, Size size, bool updateCellsOnly)
{ {
position = position with {X = position.X + _borderThickness.Left}; position = position with {X = position.X + _borderThickness.Left};

View File

@@ -44,11 +44,10 @@ public abstract partial class ContentView<TConcrete, T>
private bool DefaultContentRender(in RenderContext renderContext, Position position, Size size) private bool DefaultContentRender(in RenderContext renderContext, Position position, Size size)
{ {
if (Content is null || !Content.IsVisible) if (Content is null)
{ {
if (_placeholderRenderDone) return false; if (_placeholderRenderDone) return false;
_placeholderRenderDone = true; _placeholderRenderDone = true;
RenderEmpty(renderContext, position, size, false);
return true; return true;
} }

View File

@@ -239,8 +239,7 @@ public sealed class Grid<T> : ChildCollectionView<Grid<T>, T>, IVisibilityChange
if (!viewsByPosition.TryGetValue((column, row), out var children)) if (!viewsByPosition.TryGetValue((column, row), out var children))
{ {
RenderEmpty(context, renderPosition, renderSize, false); return false;
return true;
} }
var needsRerender = children.Any(forceRerenderChildren.Contains); var needsRerender = children.Any(forceRerenderChildren.Contains);
@@ -248,7 +247,6 @@ public sealed class Grid<T> : ChildCollectionView<Grid<T>, T>, IVisibilityChange
if (needsRerender) if (needsRerender)
{ {
updatedContext = context with {ForceRerender = true}; 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. //This implies that children further back in the list will be rendered on top of children placed before in the list.

View File

@@ -218,6 +218,7 @@ public sealed partial class ListView<TDataContext, TItem> : View<ListView<TDataC
} }
var deltaX = 0; var deltaX = 0;
var anyRendered = false;
for (var i = renderStartIndex; i < _listViewItemLength; i++) for (var i = renderStartIndex; i < _listViewItemLength; i++)
{ {
var item = listViewItems[i]; var item = listViewItems[i];
@@ -229,13 +230,13 @@ public sealed partial class ListView<TDataContext, TItem> : View<ListView<TDataC
width = size.Width - deltaX; width = size.Width - deltaX;
} }
item.Render(renderContext, position with {X = position.X + deltaX}, size with {Width = width}); anyRendered =
item.Render(renderContext, position with {X = position.X + deltaX}, size with {Width = width})
|| anyRendered;
deltaX = nextDeltaX; deltaX = nextDeltaX;
} }
//TODO: render empty to remaining space return anyRendered;
return true;
} }
private bool RenderVertical(in RenderContext renderContext, Position position, Size size) private bool RenderVertical(in RenderContext renderContext, Position position, Size size)
@@ -289,9 +290,6 @@ public sealed partial class ListView<TDataContext, TItem> : View<ListView<TDataC
deltaY += requestedItemSize.Height; deltaY += requestedItemSize.Height;
} }
// TODO: this should only render if deltaY is changed compared to last render or if last render was a horizontal
RenderEmpty(renderContext, position with {Y = position.Y + deltaY}, size with {Height = size.Height - deltaY}, false);
return anyRendered; return anyRendered;
} }

View File

@@ -64,10 +64,11 @@ public sealed partial class TextBlock<T> : View<TextBlock<T>, T>, IDisplayView
if (_textLines is null) if (_textLines is null)
{ {
if (_placeholderRenderDone) if (!_placeholderRenderDone)
{ {
_placeholderRenderDone = true; _placeholderRenderDone = true;
RenderEmpty(renderContext, position, size, skipRender); RenderEmpty(renderContext, position, size, skipRender);
return true;
} }
return false; return false;

View File

@@ -146,7 +146,13 @@ public class RenderEngine : IRenderEngine
} }
driver.ResetStyle(); driver.ResetStyle();
Array2DHelper.RenderEmpty(driver, _updatedCells, _filledCells, _applicationContext.EmptyCharacter, initialPosition, size); Array2DHelper.RenderEmpty(
driver,
_updatedCells,
_filledCells,
_applicationContext.EmptyCharacter,
initialPosition,
size);
(_lastFilledCells, _filledCells) = (_filledCells, _lastFilledCells); (_lastFilledCells, _filledCells) = (_filledCells, _lastFilledCells);