Force rerender on visibility change
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\TerminalUI\TerminalUI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,16 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace TerminalUI.DependencyInjection;
|
||||
|
||||
public static class TerminalUiServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddTerminalUi(this IServiceCollection collection)
|
||||
{
|
||||
collection.TryAddSingleton<IFocusManager, FocusManager>();
|
||||
collection.TryAddSingleton<IRenderEngine, RenderEngine>();
|
||||
collection.TryAddSingleton<IApplicationContext, ApplicationContext>();
|
||||
collection.TryAddSingleton<IEventLoop, EventLoop>();
|
||||
return collection;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using FileTime.App.Core.Models;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TerminalUI.ConsoleDrivers;
|
||||
|
||||
@@ -6,15 +7,23 @@ namespace TerminalUI;
|
||||
|
||||
public class ApplicationContext : IApplicationContext
|
||||
{
|
||||
public required IConsoleDriver ConsoleDriver { get; init; }
|
||||
public required IFocusManager FocusManager { get; init; }
|
||||
public ILoggerFactory? LoggerFactory { get; init; }
|
||||
public IEventLoop EventLoop { get; init; }
|
||||
private readonly Lazy<IConsoleDriver> _consoleDriver;
|
||||
private readonly Lazy<IFocusManager> _focusManager;
|
||||
private readonly Lazy<ILoggerFactory?> _loggerFactory;
|
||||
private readonly Lazy<IRenderEngine> _renderEngine;
|
||||
|
||||
public IConsoleDriver ConsoleDriver => _consoleDriver.Value;
|
||||
public IFocusManager FocusManager => _focusManager.Value;
|
||||
public ILoggerFactory? LoggerFactory => _loggerFactory.Value;
|
||||
public IRenderEngine RenderEngine => _renderEngine.Value;
|
||||
public bool IsRunning { get; set; }
|
||||
public char EmptyCharacter { get; init; } = ' ';
|
||||
|
||||
public ApplicationContext()
|
||||
public ApplicationContext(IServiceProvider serviceProvider)
|
||||
{
|
||||
EventLoop = new EventLoop(this);
|
||||
_consoleDriver = new Lazy<IConsoleDriver>(serviceProvider.GetRequiredService<IConsoleDriver>);
|
||||
_focusManager = new Lazy<IFocusManager>(serviceProvider.GetRequiredService<IFocusManager>);
|
||||
_loggerFactory = new Lazy<ILoggerFactory?>(serviceProvider.GetService<ILoggerFactory?>);
|
||||
_renderEngine = new Lazy<IRenderEngine>(serviceProvider.GetRequiredService<IRenderEngine>);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ namespace TerminalUI.Controls;
|
||||
public abstract class ChildContainerView<T> : View<T>, IChildContainer<T>
|
||||
{
|
||||
private readonly ObservableCollection<IView> _children = new();
|
||||
private readonly Dictionary<IView, bool> _visibilities = new();
|
||||
public ReadOnlyObservableCollection<IView> Children { get; }
|
||||
public ChildInitializer<T> ChildInitializer { get; }
|
||||
|
||||
@@ -27,7 +26,7 @@ public abstract class ChildContainerView<T> : View<T>, IChildContainer<T>
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationContext?.EventLoop.RequestRerender();
|
||||
ApplicationContext?.RenderEngine.RequestRerender(this);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -43,18 +42,6 @@ public abstract class ChildContainerView<T> : View<T>, IChildContainer<T>
|
||||
};
|
||||
}
|
||||
|
||||
protected void SaveVisibilities()
|
||||
{
|
||||
_visibilities.Clear();
|
||||
foreach (var child in _children)
|
||||
{
|
||||
_visibilities[child] = child.IsVisible;
|
||||
}
|
||||
}
|
||||
|
||||
protected bool? GetLastVisibility(IView view)
|
||||
=> _visibilities.TryGetValue(view, out var visibility) ? visibility : null;
|
||||
|
||||
public override TChild AddChild<TChild>(TChild child)
|
||||
{
|
||||
child = base.AddChild(child);
|
||||
|
||||
@@ -2,14 +2,17 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TerminalUI.Extensions;
|
||||
using TerminalUI.Models;
|
||||
using TerminalUI.Traits;
|
||||
using TerminalUI.ViewExtensions;
|
||||
|
||||
namespace TerminalUI.Controls;
|
||||
|
||||
public class Grid<T> : ChildContainerView<T>
|
||||
public class Grid<T> : ChildContainerView<T>, IVisibilityChangeHandler
|
||||
{
|
||||
private List<RowDefinition> _rowDefinitions = new() {RowDefinition.Star(1)};
|
||||
private List<ColumnDefinition> _columnDefinitions = new() {ColumnDefinition.Star(1)};
|
||||
private List<IView> _forceRerenderChildren = new();
|
||||
private readonly object _forceRerenderChildrenLock = new();
|
||||
private ILogger<Grid<T>>? Logger => ApplicationContext?.LoggerFactory?.CreateLogger<Grid<T>>();
|
||||
|
||||
private delegate void WithSizes(RenderContext renderContext, ReadOnlySpan<int> widths, ReadOnlySpan<int> heights);
|
||||
@@ -150,6 +153,13 @@ public class Grid<T> : ChildContainerView<T>
|
||||
new Option<Size>(size, true),
|
||||
(context, columnWidths, rowHeights) =>
|
||||
{
|
||||
IReadOnlyList<IView> forceRerenderChildren;
|
||||
lock (_forceRerenderChildrenLock)
|
||||
{
|
||||
forceRerenderChildren = _forceRerenderChildren;
|
||||
_forceRerenderChildren.Clear();
|
||||
}
|
||||
|
||||
context = new RenderContext(
|
||||
context.ConsoleDriver,
|
||||
context.ForceRerender,
|
||||
@@ -169,7 +179,8 @@ public class Grid<T> : ChildContainerView<T>
|
||||
rowHeights,
|
||||
viewsByPosition,
|
||||
column,
|
||||
row
|
||||
row,
|
||||
forceRerenderChildren
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -177,29 +188,17 @@ public class Grid<T> : ChildContainerView<T>
|
||||
return true;
|
||||
});
|
||||
|
||||
private void RenderViewsByPosition(
|
||||
RenderContext context,
|
||||
private void RenderViewsByPosition(RenderContext context,
|
||||
Position gridPosition,
|
||||
ReadOnlySpan<int> columnWidths,
|
||||
ReadOnlySpan<int> rowHeights,
|
||||
IReadOnlyDictionary<(int, int), List<IView>> viewsByPosition,
|
||||
int column,
|
||||
int row)
|
||||
int row,
|
||||
IReadOnlyList<IView> forceRerenderChildren)
|
||||
{
|
||||
if (!viewsByPosition.TryGetValue((column, row), out var children)) return;
|
||||
|
||||
var anyChangedVisibility = false;
|
||||
|
||||
foreach (var child in children)
|
||||
{
|
||||
var lastVisibility = GetLastVisibility(child);
|
||||
if (lastVisibility is { } b && b != child.IsVisible)
|
||||
{
|
||||
anyChangedVisibility = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var width = columnWidths[column];
|
||||
var height = rowHeights[row];
|
||||
var renderSize = new Size(width, height);
|
||||
@@ -212,7 +211,7 @@ public class Grid<T> : ChildContainerView<T>
|
||||
row
|
||||
);
|
||||
|
||||
var needsRerender = anyChangedVisibility;
|
||||
var needsRerender = children.Any(forceRerenderChildren.Contains);
|
||||
if (needsRerender)
|
||||
{
|
||||
context = new RenderContext(
|
||||
@@ -232,7 +231,7 @@ public class Grid<T> : ChildContainerView<T>
|
||||
{
|
||||
needsRerender = true;
|
||||
context = new RenderContext(
|
||||
context.ConsoleDriver,
|
||||
context.ConsoleDriver,
|
||||
true,
|
||||
context.Foreground,
|
||||
context.Background
|
||||
@@ -483,4 +482,20 @@ public class Grid<T> : ChildContainerView<T>
|
||||
|
||||
ColumnDefinitions = columnDefinitions;
|
||||
}
|
||||
|
||||
public void ChildVisibilityChanged(IView child)
|
||||
{
|
||||
var viewToForceRerender = child;
|
||||
while (viewToForceRerender.VisualParent != null && viewToForceRerender.VisualParent != this)
|
||||
{
|
||||
viewToForceRerender = viewToForceRerender.VisualParent;
|
||||
}
|
||||
|
||||
if (viewToForceRerender.VisualParent != this) return;
|
||||
|
||||
lock (_forceRerenderChildrenLock)
|
||||
{
|
||||
_forceRerenderChildren.Add(viewToForceRerender);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ public interface IView : INotifyPropertyChanged, IDisposableCollection
|
||||
IApplicationContext? ApplicationContext { get; set; }
|
||||
List<object> Extensions { get; }
|
||||
RenderMethod RenderMethod { get; set; }
|
||||
IView? VisualParent { get; set; }
|
||||
event Action<IView> Disposed;
|
||||
|
||||
Size GetRequestedSize();
|
||||
|
||||
@@ -102,14 +102,14 @@ public partial class ListView<TDataContext, TItem> : View<TDataContext>
|
||||
if (_itemsSource is ObservableCollection<TItem> observableDeclarative)
|
||||
{
|
||||
((INotifyCollectionChanged) observableDeclarative).CollectionChanged +=
|
||||
(_, _) => ApplicationContext?.EventLoop.RequestRerender();
|
||||
(_, _) => ApplicationContext?.RenderEngine.RequestRerender(this);
|
||||
|
||||
_getItems = () => observableDeclarative;
|
||||
}
|
||||
else if (_itemsSource is ReadOnlyObservableCollection<TItem> readOnlyObservableDeclarative)
|
||||
{
|
||||
((INotifyCollectionChanged) readOnlyObservableDeclarative).CollectionChanged +=
|
||||
(_, _) => ApplicationContext?.EventLoop.RequestRerender();
|
||||
(_, _) => ApplicationContext?.RenderEngine.RequestRerender(this);
|
||||
|
||||
_getItems = () => readOnlyObservableDeclarative;
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ public partial class TextBox<T> : View<T>, IFocusable
|
||||
HandleKeyInputInternal(keyEventArgs);
|
||||
if (keyEventArgs.Handled)
|
||||
{
|
||||
ApplicationContext?.EventLoop.RequestRerender();
|
||||
ApplicationContext?.RenderEngine.RequestRerender(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@ public abstract partial class View<T> : IView<T>
|
||||
[Notify] private string? _name;
|
||||
[Notify] private IApplicationContext? _applicationContext;
|
||||
[Notify] private bool _attached;
|
||||
|
||||
[Notify] private IView? _visualParent;
|
||||
|
||||
protected ObservableCollection<IView> VisualChildren { get; } = new();
|
||||
|
||||
public List<object> Extensions { get; } = new();
|
||||
@@ -90,7 +91,7 @@ public abstract partial class View<T> : IView<T>
|
||||
)
|
||||
)
|
||||
{
|
||||
ApplicationContext?.EventLoop.RequestRerender();
|
||||
ApplicationContext?.RenderEngine.RequestRerender(this);
|
||||
}
|
||||
|
||||
if (e.PropertyName == nameof(Attached))
|
||||
@@ -100,13 +101,17 @@ public abstract partial class View<T> : IView<T>
|
||||
visualChild.Attached = Attached;
|
||||
}
|
||||
}
|
||||
else if(e.PropertyName == nameof(ApplicationContext))
|
||||
else if (e.PropertyName == nameof(ApplicationContext))
|
||||
{
|
||||
foreach (var visualChild in VisualChildren)
|
||||
{
|
||||
visualChild.ApplicationContext = ApplicationContext;
|
||||
}
|
||||
}
|
||||
else if (e.PropertyName == nameof(IsVisible))
|
||||
{
|
||||
ApplicationContext?.RenderEngine.VisibilityChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract bool DefaultRenderer(RenderContext renderContext, Position position, Size size);
|
||||
@@ -221,7 +226,7 @@ public abstract partial class View<T> : IView<T>
|
||||
Size size)
|
||||
{
|
||||
var contentString = new string(content, size.Width);
|
||||
|
||||
|
||||
for (var i = 0; i < size.Height; i++)
|
||||
{
|
||||
var currentPosition = position with {Y = position.Y + i};
|
||||
@@ -234,7 +239,7 @@ public abstract partial class View<T> : IView<T>
|
||||
protected void SetColorsForDriver(RenderContext renderContext)
|
||||
{
|
||||
var driver = renderContext.ConsoleDriver;
|
||||
|
||||
|
||||
var foreground = Foreground ?? renderContext.Foreground;
|
||||
var background = Background ?? renderContext.Background;
|
||||
if (foreground is not null)
|
||||
@@ -264,12 +269,8 @@ public abstract partial class View<T> : IView<T>
|
||||
public virtual TChild AddChild<TChild>(TChild child) where TChild : IView<T>
|
||||
{
|
||||
child.DataContext = DataContext;
|
||||
CopyCommonPropertiesToNewChild(child);
|
||||
VisualChildren.Add(child);
|
||||
|
||||
var mapper = new DataContextMapper<T, T>(this, child, d => d);
|
||||
AddDisposable(mapper);
|
||||
child.AddDisposable(mapper);
|
||||
SetupNewChild(child, mapper);
|
||||
|
||||
return child;
|
||||
}
|
||||
@@ -278,20 +279,21 @@ public abstract partial class View<T> : IView<T>
|
||||
where TChild : IView<TDataContext>
|
||||
{
|
||||
child.DataContext = dataContextMapper(DataContext);
|
||||
CopyCommonPropertiesToNewChild(child);
|
||||
VisualChildren.Add(child);
|
||||
|
||||
var mapper = new DataContextMapper<T, TDataContext>(this, child, dataContextMapper);
|
||||
AddDisposable(mapper);
|
||||
child.AddDisposable(mapper);
|
||||
SetupNewChild(child, mapper);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
private void CopyCommonPropertiesToNewChild(IView child)
|
||||
private void SetupNewChild(IView child, IDisposable dataContextmapper)
|
||||
{
|
||||
child.ApplicationContext = ApplicationContext;
|
||||
child.Attached = Attached;
|
||||
child.VisualParent = this;
|
||||
VisualChildren.Add(child);
|
||||
|
||||
AddDisposable(dataContextmapper);
|
||||
child.AddDisposable(dataContextmapper);
|
||||
}
|
||||
|
||||
public virtual void RemoveChild<TDataContext>(IView<TDataContext> child)
|
||||
|
||||
@@ -1,86 +1,32 @@
|
||||
using TerminalUI.Controls;
|
||||
using TerminalUI.Models;
|
||||
|
||||
namespace TerminalUI;
|
||||
namespace TerminalUI;
|
||||
|
||||
public class EventLoop : IEventLoop
|
||||
{
|
||||
private readonly IApplicationContext _applicationContext;
|
||||
private readonly object _lock = new();
|
||||
private readonly List<IView> _viewsToRender = new();
|
||||
private bool _rerenderRequested;
|
||||
private bool _lastCursorVisible;
|
||||
private readonly List<Action> _permanentQueue = new();
|
||||
|
||||
public EventLoop(IApplicationContext applicationContext)
|
||||
{
|
||||
_applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public void AddToPermanentQueue(Action action) => _permanentQueue.Add(action);
|
||||
|
||||
public void Run()
|
||||
{
|
||||
_applicationContext.IsRunning = true;
|
||||
_rerenderRequested = true;
|
||||
while (_applicationContext.IsRunning)
|
||||
{
|
||||
Render();
|
||||
ProcessQueues();
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
public void RequestRerender()
|
||||
private void ProcessQueues()
|
||||
{
|
||||
lock (_lock)
|
||||
foreach (var action in _permanentQueue)
|
||||
{
|
||||
_rerenderRequested = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
List<IView> viewsToRender;
|
||||
lock (_lock)
|
||||
{
|
||||
if (!_rerenderRequested) return;
|
||||
_rerenderRequested = false;
|
||||
viewsToRender = _viewsToRender.ToList();
|
||||
}
|
||||
|
||||
var driver = _applicationContext.ConsoleDriver;
|
||||
var size = driver.GetWindowSize();
|
||||
var renderContext = new RenderContext(
|
||||
driver,
|
||||
false,
|
||||
null,
|
||||
null
|
||||
);
|
||||
foreach (var view in viewsToRender)
|
||||
{
|
||||
view.Attached = true;
|
||||
view.GetRequestedSize();
|
||||
view.Render(renderContext, new Position(0, 0), size);
|
||||
}
|
||||
|
||||
if (_applicationContext.FocusManager.Focused is { } focused)
|
||||
{
|
||||
focused.SetCursorPosition(driver);
|
||||
if (!_lastCursorVisible)
|
||||
{
|
||||
driver.SetCursorVisible(true);
|
||||
_lastCursorVisible = true;
|
||||
}
|
||||
}
|
||||
else if (_lastCursorVisible)
|
||||
{
|
||||
driver.SetCursorVisible(false);
|
||||
_lastCursorVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddViewToRender(IView view)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_viewsToRender.Add(view);
|
||||
action();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,10 @@ namespace TerminalUI;
|
||||
|
||||
public interface IApplicationContext
|
||||
{
|
||||
IEventLoop EventLoop { get; init; }
|
||||
IRenderEngine RenderEngine { get; }
|
||||
bool IsRunning { get; set; }
|
||||
IConsoleDriver ConsoleDriver { get; init; }
|
||||
ILoggerFactory? LoggerFactory { get; init; }
|
||||
char EmptyCharacter { get; init; }
|
||||
IFocusManager FocusManager { get; init; }
|
||||
IConsoleDriver ConsoleDriver { get; }
|
||||
ILoggerFactory? LoggerFactory { get; }
|
||||
char EmptyCharacter { get; }
|
||||
IFocusManager FocusManager { get; }
|
||||
}
|
||||
@@ -1,11 +1,7 @@
|
||||
using TerminalUI.Controls;
|
||||
|
||||
namespace TerminalUI;
|
||||
namespace TerminalUI;
|
||||
|
||||
public interface IEventLoop
|
||||
{
|
||||
void Render();
|
||||
void AddViewToRender(IView view);
|
||||
void Run();
|
||||
void RequestRerender();
|
||||
void AddToPermanentQueue(Action action);
|
||||
}
|
||||
11
src/Library/TerminalUI/IRenderEngine.cs
Normal file
11
src/Library/TerminalUI/IRenderEngine.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using TerminalUI.Controls;
|
||||
|
||||
namespace TerminalUI;
|
||||
|
||||
public interface IRenderEngine
|
||||
{
|
||||
void RequestRerender(IView view);
|
||||
void VisibilityChanged(IView view);
|
||||
void AddViewToPermanentRenderGroup(IView view);
|
||||
void Run();
|
||||
}
|
||||
141
src/Library/TerminalUI/RenderEngine.cs
Normal file
141
src/Library/TerminalUI/RenderEngine.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
using TerminalUI.Controls;
|
||||
using TerminalUI.Models;
|
||||
using TerminalUI.Traits;
|
||||
|
||||
namespace TerminalUI;
|
||||
|
||||
public class RenderEngine : IRenderEngine
|
||||
{
|
||||
private readonly IApplicationContext _applicationContext;
|
||||
private readonly IEventLoop _eventLoop;
|
||||
private readonly object _lock = new();
|
||||
private readonly List<IView> _permanentViewsToRender = new();
|
||||
private readonly List<IView> _forcedTemporaryViewsToRender = new();
|
||||
private bool _rerenderRequested = true;
|
||||
private bool _lastCursorVisible;
|
||||
|
||||
public RenderEngine(IApplicationContext applicationContext, IEventLoop eventLoop)
|
||||
{
|
||||
_applicationContext = applicationContext;
|
||||
_eventLoop = eventLoop;
|
||||
|
||||
_eventLoop.AddToPermanentQueue(Render);
|
||||
}
|
||||
|
||||
public void RequestRerender(IView view) => RequestRerender();
|
||||
|
||||
public void VisibilityChanged(IView view)
|
||||
{
|
||||
IVisibilityChangeHandler? visibilityChangeHandler = null;
|
||||
var parent = view.VisualParent;
|
||||
while (parent?.VisualParent != null)
|
||||
{
|
||||
if (parent is IVisibilityChangeHandler v)
|
||||
{
|
||||
visibilityChangeHandler = v;
|
||||
break;
|
||||
}
|
||||
|
||||
parent = parent.VisualParent;
|
||||
}
|
||||
|
||||
if (visibilityChangeHandler is null)
|
||||
{
|
||||
AddViewToForcedTemporaryRenderGroup(parent ?? view);
|
||||
}
|
||||
else
|
||||
{
|
||||
visibilityChangeHandler.ChildVisibilityChanged(view);
|
||||
}
|
||||
}
|
||||
|
||||
public void Run() => _eventLoop.Run();
|
||||
|
||||
public void RequestRerender()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_rerenderRequested = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void Render()
|
||||
{
|
||||
List<IView> permanentViewsToRender;
|
||||
List<IView> forcedTemporaryViewsToRender;
|
||||
lock (_lock)
|
||||
{
|
||||
if (!_rerenderRequested) return;
|
||||
_rerenderRequested = false;
|
||||
permanentViewsToRender = _permanentViewsToRender.ToList();
|
||||
forcedTemporaryViewsToRender = _forcedTemporaryViewsToRender.ToList();
|
||||
}
|
||||
|
||||
var driver = _applicationContext.ConsoleDriver;
|
||||
var initialPosition = new Position(0, 0);
|
||||
var size = driver.GetWindowSize();
|
||||
|
||||
RenderViews(
|
||||
forcedTemporaryViewsToRender,
|
||||
new RenderContext(
|
||||
driver,
|
||||
true,
|
||||
null,
|
||||
null
|
||||
),
|
||||
initialPosition,
|
||||
size);
|
||||
|
||||
RenderViews(
|
||||
permanentViewsToRender,
|
||||
new RenderContext(
|
||||
driver,
|
||||
false,
|
||||
null,
|
||||
null
|
||||
),
|
||||
initialPosition,
|
||||
size);
|
||||
|
||||
if (_applicationContext.FocusManager.Focused is { } focused)
|
||||
{
|
||||
focused.SetCursorPosition(driver);
|
||||
if (!_lastCursorVisible)
|
||||
{
|
||||
driver.SetCursorVisible(true);
|
||||
_lastCursorVisible = true;
|
||||
}
|
||||
}
|
||||
else if (_lastCursorVisible)
|
||||
{
|
||||
driver.SetCursorVisible(false);
|
||||
_lastCursorVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void RenderViews(List<IView> views, RenderContext renderContext, Position position, Size size)
|
||||
{
|
||||
foreach (var view in views)
|
||||
{
|
||||
view.Attached = true;
|
||||
view.GetRequestedSize();
|
||||
view.Render(renderContext, position, size);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddViewToPermanentRenderGroup(IView view)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_permanentViewsToRender.Add(view);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddViewToForcedTemporaryRenderGroup(IView view)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_forcedTemporaryViewsToRender.Add(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using TerminalUI.Controls;
|
||||
|
||||
namespace TerminalUI.Traits;
|
||||
|
||||
public interface IVisibilityChangeHandler
|
||||
{
|
||||
void ChildVisibilityChanged(IView child);
|
||||
}
|
||||
Reference in New Issue
Block a user