LavaUI docs

struct VisualLayout

Swift

struct VisualLayout

Where each visual row begins and ends, in character offsets over the whole buffer.

With wrapping, a visual row is no longer a logical line, and every mapping — caret, hit test, selection, vertical movement — has to use this rather than newline positions.

Sources/LavaText/SoftWrap.swift:115

Constructors

init(rows: [Range<Int>])

Not documented.

Sources/LavaText/SoftWrap.swift:118

Properties

var count: Int { get }

Not documented.

Sources/LavaText/SoftWrap.swift:278

var rows: [Range<Int>]

Not documented.

Sources/LavaText/SoftWrap.swift:116

Methods

func column(ofOffset offset: Int, affinity: CaretAffinity = .downstream) -> Int

Not documented.

Sources/LavaText/SoftWrap.swift:336

static func lineIndex(_ text: String, includingBytes: Bool = true) -> LineIndex

The same scan, also reporting where each line sits in bytes.

Character offsets are what the row table is stated in. Byte offsets are what a cheap comparison of two buffers produces, and what slicing one line out of the buffer wants — and a wrapping editor needs both on every edit, so it asks for them together rather than scanning twice. Everything else asks for logicalRows and does not pay for the second array, which on a 200,000-line log is not a rounding error.

Sources/LavaText/SoftWrap.swift:145

static func logical(_ text: String) -> VisualLayout

One row per logical line — the no-wrapping case.

Sources/LavaText/SoftWrap.swift:123

static func logicalRows(_ text: String) -> [Range<Int>]

Row boundaries for logical(_:), exposed separately so a caller (an editor leaf with wrapping off) can cache the result via TextEditingState.setVisualRows instead of recomputing this O(length) scan on every layout access — which, left uncached, is what a large buffer felt: every caret draw, hit test, and gutter row rescanned the whole document.

Sources/LavaText/SoftWrap.swift:133

func offset(row: Int, column: Int) -> Int

Offset at row/column, clamped to that row.

Sources/LavaText/SoftWrap.swift:342

func rowIndex(ofOffset offset: Int, affinity: CaretAffinity = .downstream) -> Int

Row containing offset.

At a soft-wrap boundary one offset is both the end of a row and the start of the next, and there is no way to pick from the offset alone — which is why carets carry an affinity. Upstream keeps the caret on the row that ended (where a clamped vertical move should stay); downstream puts it on the row that starts (where a click or Home should land).

Sources/LavaText/SoftWrap.swift:287