RenderEmpty fixes
This commit is contained in:
@@ -7,6 +7,24 @@ namespace TerminalUI.Controls;
|
||||
|
||||
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 _padding = 0;
|
||||
[Notify] private char _topChar = '─';
|
||||
@@ -59,6 +77,27 @@ public sealed partial class Border<T> : ContentView<Border<T>, 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<T> : ContentView<Border<T>, 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<T> : ContentView<Border<T>, 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<T> : ContentView<Border<T>, 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};
|
||||
|
||||
@@ -44,11 +44,10 @@ public abstract partial class ContentView<TConcrete, T>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -239,8 +239,7 @@ public sealed class Grid<T> : ChildCollectionView<Grid<T>, 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<T> : ChildCollectionView<Grid<T>, 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.
|
||||
|
||||
@@ -218,6 +218,7 @@ public sealed partial class ListView<TDataContext, TItem> : View<ListView<TDataC
|
||||
}
|
||||
|
||||
var deltaX = 0;
|
||||
var anyRendered = false;
|
||||
for (var i = renderStartIndex; i < _listViewItemLength; i++)
|
||||
{
|
||||
var item = listViewItems[i];
|
||||
@@ -229,13 +230,13 @@ public sealed partial class ListView<TDataContext, TItem> : View<ListView<TDataC
|
||||
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;
|
||||
}
|
||||
|
||||
//TODO: render empty to remaining space
|
||||
|
||||
return true;
|
||||
return anyRendered;
|
||||
}
|
||||
|
||||
private bool RenderVertical(in RenderContext renderContext, Position position, Size size)
|
||||
@@ -283,15 +284,12 @@ public sealed partial class ListView<TDataContext, TItem> : View<ListView<TDataC
|
||||
for (var i = renderStartIndex; i < lastItemIndex; i++)
|
||||
{
|
||||
var item = listViewItems[i];
|
||||
anyRendered =
|
||||
item.Render(renderContext, position with {Y = position.Y + deltaY}, requestedItemSize with {Width = size.Width})
|
||||
anyRendered =
|
||||
item.Render(renderContext, position with {Y = position.Y + deltaY}, requestedItemSize with {Width = size.Width})
|
||||
|| anyRendered;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,10 +64,11 @@ public sealed partial class TextBlock<T> : View<TextBlock<T>, T>, IDisplayView
|
||||
|
||||
if (_textLines is null)
|
||||
{
|
||||
if (_placeholderRenderDone)
|
||||
if (!_placeholderRenderDone)
|
||||
{
|
||||
_placeholderRenderDone = true;
|
||||
RenderEmpty(renderContext, position, size, skipRender);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user