diff --git a/dotnet/samples/02-agents/Harness/ConsoleReactiveComponents/ListSelection.cs b/dotnet/samples/02-agents/Harness/ConsoleReactiveComponents/ListSelection.cs index 8a0c8b982e..eedc76a145 100644 --- a/dotnet/samples/02-agents/Harness/ConsoleReactiveComponents/ListSelection.cs +++ b/dotnet/samples/02-agents/Harness/ConsoleReactiveComponents/ListSelection.cs @@ -39,7 +39,7 @@ public class ListSelection : ConsoleReactiveComponent /// A component that renders a list of pre-rendered string items vertically. /// Designed for rendering dynamic items in a non-scroll region that may be -/// re-rendered on each update. If the component's +/// re-rendered on each update. If the component's /// exceeds the number of output lines, leftover lines are erased. /// public class TextPanel : ConsoleReactiveComponent @@ -51,18 +51,18 @@ public class TextPanel : ConsoleReactiveComponent currentRow) + if (props.Height > currentRow) { - for (int i = currentRow; i < this.Height; i++) + for (int i = currentRow; i < props.Height; i++) { - Console.Write(AnsiEscapes.MoveAndEraseLine(this.Y + i)); + Console.Write(AnsiEscapes.MoveAndEraseLine(props.Y + i)); } } } diff --git a/dotnet/samples/02-agents/Harness/ConsoleReactiveComponents/TextScrollPanel.cs b/dotnet/samples/02-agents/Harness/ConsoleReactiveComponents/TextScrollPanel.cs index f0b156cd5a..15147b0fd0 100644 --- a/dotnet/samples/02-agents/Harness/ConsoleReactiveComponents/TextScrollPanel.cs +++ b/dotnet/samples/02-agents/Harness/ConsoleReactiveComponents/TextScrollPanel.cs @@ -52,7 +52,7 @@ public class TextScrollPanel : ConsoleReactiveComponent public record TopBottomRuleProps : ConsoleReactiveProps { - /// Gets the width of the horizontal rules in characters. - public int Width { get; init; } - /// Gets the foreground color of the horizontal rules. If null, the default terminal color is used. public ConsoleColor? Color { get; init; } } @@ -32,7 +29,7 @@ public class TopBottomRule : ConsoleReactiveComponent -/// Abstract base class for all console UI components. Provides layout properties -/// (position and size) and a method for drawing to the console. +/// Abstract base class for all console UI components. Provides access to layout +/// through and a method for drawing to the console. /// Derive from instead of this class directly. /// public abstract class ConsoleReactiveComponent @@ -13,20 +13,21 @@ public abstract class ConsoleReactiveComponent { } - /// Gets or sets the 1-based column position of the component. - public int X { get; set; } - - /// Gets or sets the 1-based row position of the component. - public int Y { get; set; } - - /// Gets or sets the width of the component in columns. - public int Width { get; set; } - - /// Gets or sets the height of the component in rows. - public int Height { get; set; } + /// + /// Gets or sets the component's props as the base type. + /// Used by parent components to set layout (X, Y, Width, Height) on children without + /// knowing the concrete props type. + /// + public abstract ConsoleReactiveProps? BaseProps { get; set; } /// Renders the component to the console at its current position. public abstract void Render(); + + /// + /// Invalidates the component's cached render state, causing the next call + /// to proceed even if props and state have not changed. Use after a screen erase to force repaint. + /// + public abstract void Invalidate(); } /// @@ -46,6 +47,13 @@ public abstract class ConsoleReactiveComponent : ConsoleReactive /// Gets or sets the component's props (external configuration). public TProps? Props { get; set; } + /// + public override ConsoleReactiveProps? BaseProps + { + get => this.Props; + set => this.Props = (TProps?)value; + } + /// Gets or sets the component's internal state. protected TState? State { get; set; } @@ -73,8 +81,8 @@ public abstract class ConsoleReactiveComponent : ConsoleReactive return; } - if (ReferenceEquals(this.Props, this._lastRenderedProps) - && ReferenceEquals(this.State, this._lastRenderedState)) + if (EqualityComparer.Default.Equals(this.Props, this._lastRenderedProps) + && EqualityComparer.Default.Equals(this.State, this._lastRenderedState)) { return; } @@ -86,6 +94,16 @@ public abstract class ConsoleReactiveComponent : ConsoleReactive } } + /// + public override void Invalidate() + { + lock (this._renderLock) + { + this._lastRenderedProps = default; + this._lastRenderedState = default; + } + } + /// /// Called by to perform the actual rendering. Override this in derived classes. /// @@ -95,11 +113,23 @@ public abstract class ConsoleReactiveComponent : ConsoleReactive } /// -/// Base record for component props. Provides an optional collection -/// for composing child components. +/// Base record for component props. Provides layout properties (position and size) +/// and an optional collection for composing child components. /// public record ConsoleReactiveProps { + /// Gets the 1-based column position of the component. + public int X { get; init; } + + /// Gets the 1-based row position of the component. + public int Y { get; init; } + + /// Gets the width of the component in columns. + public int Width { get; init; } + + /// Gets the height of the component in rows. + public int Height { get; init; } + /// Gets the child components to render within this component. public IReadOnlyList Children { get; init; } = []; } diff --git a/dotnet/samples/02-agents/Harness/Harness_Shared_Console/Components/AgentModeAndHelp.cs b/dotnet/samples/02-agents/Harness/Harness_Shared_Console/Components/AgentModeAndHelp.cs index 97579992fd..2e1d86a413 100644 --- a/dotnet/samples/02-agents/Harness/Harness_Shared_Console/Components/AgentModeAndHelp.cs +++ b/dotnet/samples/02-agents/Harness/Harness_Shared_Console/Components/AgentModeAndHelp.cs @@ -43,7 +43,7 @@ public class AgentModeAndHelp : ConsoleReactiveComponent