Class LineScrollTextBuffer
A fixed-capacity ring buffer for storing logical text lines with line-based scrolling support. Designed for terminal/console-style text output where each stored entry is a logical line that may wrap into multiple visual (display) lines.
Inherited Members
Namespace: Scylla.Core.Util.UI
Assembly: ScyllaCore.dll
Syntax
public sealed class LineScrollTextBuffer
Remarks
A logical line is what is stored in the buffer (one entry per AddLine(string) call). A visual line is a rendered row on screen; a single logical line can produce multiple visual lines when its text wraps within the available display width.
Per-line wrap counts and a parallel cumulative visual-line array are maintained so that O(log n) binary search can be used to locate the visible window for any scroll position.
The scroll offset convention is: 0 means the newest content is visible (bottom of the buffer); higher values scroll toward older content (toward the top). Use MaxScrollOffset to find the upper limit.
Use GetWindow() as the primary entry point for rendering. It returns a LineScrollWindow snapshot that contains the visible VisualLine array plus overflow state for precise layout positioning.
Constructors
LineScrollTextBuffer(int, int)
Creates a new LineScrollTextBuffer with the specified capacity.
Declaration
public LineScrollTextBuffer(int capacity = 1000, int windowSize = 20)
Parameters
| Type | Name | Description |
|---|---|---|
| int | capacity | Maximum number of logical lines to store. |
| int | windowSize | Number of visible lines in the view window. |
Fields
DEFAULT_CAPACITY
Default buffer capacity (number of logical lines).
Declaration
public const int DEFAULT_CAPACITY = 1000
Field Value
| Type | Description |
|---|---|
| int |
DEFAULT_WINDOW_SIZE
Default number of visible lines in the window.
Declaration
public const int DEFAULT_WINDOW_SIZE = 20
Field Value
| Type | Description |
|---|---|
| int |
MAX_CAPACITY
Maximum allowed buffer capacity.
Declaration
public const int MAX_CAPACITY = 100000
Field Value
| Type | Description |
|---|---|
| int |
MIN_CAPACITY
Minimum allowed buffer capacity.
Declaration
public const int MIN_CAPACITY = 1
Field Value
| Type | Description |
|---|---|
| int |
MIN_WINDOW_SIZE
Minimum allowed window size.
Declaration
public const int MIN_WINDOW_SIZE = 1
Field Value
| Type | Description |
|---|---|
| int |
Properties
AutoScroll
Gets whether auto-scroll is enabled (automatically scroll to bottom on new content).
Declaration
public bool AutoScroll { get; set; }
Property Value
| Type | Description |
|---|---|
| bool |
BottomVisualLineOverflow
Gets the number of extra visual rows at the bottom of the content window that are hidden because the current scroll offset places them below the visible area. This occurs when ScrollOffset is greater than zero and the newest visible logical line has more wrapped rows than are shown.
Declaration
public int BottomVisualLineOverflow { get; }
Property Value
| Type | Description |
|---|---|
| int |
Remarks
This value is set by GetWindow() and consumed by
LineScrollTextArea to clip or hide the excess rows that the newest
logical line would otherwise render below the bottom of the visible area.
Capacity
Gets the fixed capacity of this buffer (maximum number of logical lines).
Declaration
public int Capacity { get; }
Property Value
| Type | Description |
|---|---|
| int |
DisplayWidth
Gets the current display width used for wrap calculations.
Declaration
public float DisplayWidth { get; }
Property Value
| Type | Description |
|---|---|
| float |
Font
Gets the current font used for wrap calculations.
Declaration
public TMP_FontAsset Font { get; }
Property Value
| Type | Description |
|---|---|
| TMP_FontAsset |
FontSize
Gets the current font size used for wrap calculations.
Declaration
public float FontSize { get; }
Property Value
| Type | Description |
|---|---|
| float |
IsAtBottom
Gets whether the view is currently at the bottom (showing newest content).
Declaration
public bool IsAtBottom { get; }
Property Value
| Type | Description |
|---|---|
| bool |
IsAtTop
Gets whether the view is currently at the top (showing oldest content).
Declaration
public bool IsAtTop { get; }
Property Value
| Type | Description |
|---|---|
| bool |
IsEmpty
Gets whether the buffer is empty.
Declaration
public bool IsEmpty { get; }
Property Value
| Type | Description |
|---|---|
| bool |
IsMonospace
Gets whether this buffer is configured for monospace font optimization.
Declaration
public bool IsMonospace { get; }
Property Value
| Type | Description |
|---|---|
| bool |
LineCount
Gets the current number of logical lines in the buffer.
Declaration
public int LineCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
MaxScrollOffset
Gets the maximum scroll offset, computed as the total number of visual lines minus the window size, clamped to a minimum of 0. A value of 0 means all content fits within the window.
Declaration
public int MaxScrollOffset { get; }
Property Value
| Type | Description |
|---|---|
| int |
NeedsRefresh
Gets whether wrap calculation is needed before getting a window.
Declaration
public bool NeedsRefresh { get; }
Property Value
| Type | Description |
|---|---|
| bool |
ScrollOffset
Gets the current scroll offset (number of visual lines from the bottom). 0 means at the bottom (newest content), higher values scroll up toward older content.
Declaration
public int ScrollOffset { get; }
Property Value
| Type | Description |
|---|---|
| int |
TopVisualLineOverflow
Gets the number of extra visual rows at the top of the content window that should be clipped from the oldest included logical line. This occurs when the oldest logical line needed to fill the window has more wrapped rows than the space remaining at the top.
Declaration
public int TopVisualLineOverflow { get; }
Property Value
| Type | Description |
|---|---|
| int |
Remarks
This value is set by GetWindow() and consumed by
LineScrollTextArea to shift the TMP text component vertically so
that the correct visual row appears flush at the top of the visible area,
even when the first logical line contributes more wrapped rows than needed.
TotalVisualLineCount
Gets the total number of visual lines (after wrapping) across all logical lines.
Declaration
public int TotalVisualLineCount { get; }
Property Value
| Type | Description |
|---|---|
| int |
WindowSize
Gets or sets the number of logical lines returned in each GetWindow() call
(before overflow is applied). The value is clamped to a minimum of MIN_WINDOW_SIZE.
Changing this property does not trigger an immediate recalculation; the new value takes
effect on the next GetWindow() call.
Declaration
public int WindowSize { get; set; }
Property Value
| Type | Description |
|---|---|
| int |
Methods
AddLine(string)
Adds a line of text to the buffer. The wrap count is calculated and cached immediately so that subsequent calls to GetWindow() can skip re-measuring this line.
Declaration
public void AddLine(string text)
Parameters
| Type | Name | Description |
|---|---|---|
| string | text | The text to add. |
Remarks
Wrap count is computed on the calling thread using the display metrics known at
the time of the call, so RecalculateWrapCache will find the cache entry
valid and skip re-measuring it. If no display metrics have been set yet, the
wrap count defaults to 1 (one visual line per logical line) and will be
recalculated once SetDisplayMetrics(float, TMP_FontAsset, float) is called.
AddLines(IEnumerable<string>)
Adds multiple lines of text to the buffer.
A null collection is silently ignored. Events are fired per line,
but the auto-scroll reset is performed only once after all lines have been added.
Declaration
public void AddLines(IEnumerable<string> lines)
Parameters
| Type | Name | Description |
|---|---|---|
| IEnumerable<string> | lines | The lines to add. May be |
Clear()
Clears all lines from the buffer.
Declaration
public void Clear()
CreateBuilder()
Creates a new builder for configuring a LineScrollTextBuffer.
Declaration
public static LineScrollTextBuffer.Builder CreateBuilder()
Returns
| Type | Description |
|---|---|
| LineScrollTextBuffer.Builder | A new builder instance. |
GetLine(int)
Gets a logical line by index. Index 0 is the oldest line.
Declaration
public LineScrollTextBuffer.LogicalLine GetLine(int index)
Parameters
| Type | Name | Description |
|---|---|---|
| int | index | The line index (0 = oldest). |
Returns
| Type | Description |
|---|---|
| LineScrollTextBuffer.LogicalLine | The logical line at the specified index. |
Exceptions
| Type | Condition |
|---|---|
| ArgumentOutOfRangeException | Thrown when index is out of range. |
GetVisibleText()
Gets the combined text of all visible lines, separated by newlines.
Declaration
public string GetVisibleText()
Returns
| Type | Description |
|---|---|
| string | The combined visible text. |
GetWindow()
Gets a LineScrollWindow snapshot of the currently visible content. This is the primary entry point for rendering.
Declaration
public LineScrollWindow GetWindow()
Returns
| Type | Description |
|---|---|
| LineScrollWindow | A LineScrollWindow containing the visible VisualLine array ordered oldest-to-newest, plus current scroll state. Returns Empty when the buffer is empty. |
Remarks
The algorithm proceeds as follows:
- Ensure the wrap cache is current.
- Perform a binary search on the cumulative visual-line array to find the newest logical line that is at least partially visible given the current ScrollOffset.
- Walk backward through older lines, accumulating logical lines until enough visual rows are collected to fill WindowSize.
- Compute TopVisualLineOverflow and BottomVisualLineOverflow to describe how many rows of the boundary logical lines fall outside the visible area.
When no display metrics are set, falls back to GetWindowSimple which
treats 1 visual line as 1 logical line and uses direct index arithmetic.
InvalidateWrapCache()
Forces a full recalculation of all wrap caches on the next GetWindow() call. All cached per-line wrap counts will be recomputed from the current display metrics. Useful after external layout changes that affect the available display width.
Declaration
public void InvalidateWrapCache()
ScrollDown(int)
Scrolls down by the specified number of visual lines, moving toward newer content.
Decreases ScrollOffset by lines,
clamped to a minimum of 0.
Declaration
public void ScrollDown(int lines = 1)
Parameters
| Type | Name | Description |
|---|---|---|
| int | lines | Number of visual lines to scroll down. Values less than 1 are ignored. |
ScrollToBottom()
Scrolls to the bottom (newest content).
Declaration
public void ScrollToBottom()
ScrollToTop()
Scrolls to the top (oldest content).
Declaration
public void ScrollToTop()
ScrollUp(int)
Scrolls up by the specified number of visual lines, moving toward older content.
Increases ScrollOffset by lines,
clamped to MaxScrollOffset.
Declaration
public void ScrollUp(int lines = 1)
Parameters
| Type | Name | Description |
|---|---|---|
| int | lines | Number of visual lines to scroll up. Values less than 1 are ignored. |
SetDisplayMetrics(float, TMP_FontAsset, float)
Sets the display metrics used for visual line wrap calculation. Changing any metric invalidates the wrap cache; cached wrap counts are rebuilt lazily on the next GetWindow() call.
Declaration
public void SetDisplayMetrics(float displayWidth, TMP_FontAsset font, float fontSize)
Parameters
| Type | Name | Description |
|---|---|---|
| float | displayWidth | The available width for text display in pixels. |
| TMP_FontAsset | font | The TMP font asset. |
| float | fontSize | The font size in points. |
SetEventPublishing(bool)
Enables or disables event publishing.
Declaration
public void SetEventPublishing(bool enabled)
Parameters
| Type | Name | Description |
|---|---|---|
| bool | enabled | Whether to publish events. |
SetMeasurementComponent(TMP_Text)
Sets the TMP component used for accurate visual wrap count measurement.
Declaration
public void SetMeasurementComponent(TMP_Text measurementComponent)
Parameters
| Type | Name | Description |
|---|---|---|
| TMP_Text | measurementComponent | The TMP component to use for measurement via |
SetScrollOffset(int)
Sets the scroll offset directly.
Declaration
public void SetScrollOffset(int offset)
Parameters
| Type | Name | Description |
|---|---|---|
| int | offset | The scroll offset (clamped to valid range). |
TryGetLine(int, out LogicalLine)
Attempts to get a logical line by index.
Declaration
public bool TryGetLine(int index, out LineScrollTextBuffer.LogicalLine line)
Parameters
| Type | Name | Description |
|---|---|---|
| int | index | The line index (0 = oldest). |
| LineScrollTextBuffer.LogicalLine | line | The line if found. |
Returns
| Type | Description |
|---|---|
| bool | True if the line was found. |
WriteVisibleTextTo(StringBuilder)
Writes the combined visible text to a StringBuilder. No string allocation occurs if the caller reuses the same StringBuilder instance across calls.
Declaration
public void WriteVisibleTextTo(StringBuilder sb)
Parameters
| Type | Name | Description |
|---|---|---|
| StringBuilder | sb | The StringBuilder to write to. |