diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-10-26 20:37:52 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-10-26 20:37:52 +0800 |
| commit | 2e6dc81391c5dbb787cfd793ad5823904b3b9c94 (patch) | |
| tree | 6c6de805790d75f1b3844d3d65c955f8ec832bf5 /ricochet/src/tui/layout.hh | |
| parent | 2063bf09fa8828c602ca1726a1188f0c95ae8adb (diff) | |
| download | rcc-project-2e6dc81391c5dbb787cfd793ad5823904b3b9c94.tar.gz rcc-project-2e6dc81391c5dbb787cfd793ad5823904b3b9c94.tar.xz | |
feat(tui): add document navigation and text selection
Diffstat (limited to 'ricochet/src/tui/layout.hh')
| -rw-r--r-- | ricochet/src/tui/layout.hh | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/ricochet/src/tui/layout.hh b/ricochet/src/tui/layout.hh index 5feb0cd..7e02e76 100644 --- a/ricochet/src/tui/layout.hh +++ b/ricochet/src/tui/layout.hh @@ -31,6 +31,8 @@ namespace ricochet::tui::detail { +class DocumentText; + using HitTarget = std::variant<LinkId, ControlId>; struct LayoutPoint @@ -46,6 +48,22 @@ struct LayoutHit std::optional<HitTarget> target {}; }; +struct ScrollWindow +{ + BlockId block {}; + std::int64_t left { 0 }; + std::int64_t width { 0 }; + std::int64_t offset { 0 }; + std::int64_t maximum { 0 }; +}; + +enum class WordMotion : std::uint8_t +{ + Next, + Previous, + End +}; + struct LayoutGlyph { LayoutPoint position {}; @@ -63,6 +81,10 @@ struct LayoutGlyph bool decoration { false }; bool line_break { false }; bool fill { false }; + bool word_start { false }; + bool word_end { false }; + // Inner-to-outer windows allow a code block inside a table to be revealed. + std::vector<ScrollWindow> scrolls {}; }; struct LayoutData @@ -88,11 +110,40 @@ public: std::size_t rows() const; std::optional<LayoutPoint> locate( const DisplayPosition& position ) const; std::optional<LayoutHit> hit( LayoutPoint point ) const; - void append_frame( Frame& frame, std::size_t first_row, CellPoint origin, ScreenSize viewport ) const; + DisplayPosition first() const; + DisplayPosition last() const; + DisplayPosition adjacent( const DisplayPosition& position, int direction ) const; + DisplayPosition word( const DisplayPosition& position, WordMotion motion ) const; + DisplayPosition on_row( LayoutPoint point ) const; + DisplayPosition line_edge( const DisplayPosition& position, bool end ) const; + DocumentRange unit( const DisplayPosition& position ) const; + std::optional<HitTarget> target( const DisplayPosition& position ) const; + std::optional<LayoutPoint> cursor_cell( const DisplayPosition& position ) const; + std::vector<HorizontalScroll> reveal( const DisplayPosition& position ) const; + std::vector<HorizontalScroll> pan( const DisplayPosition& position, int direction ) const; + void append_frame( Frame& frame, + std::size_t first_row, + CellPoint origin, + ScreenSize viewport, + const DocumentText& content, + std::optional<DocumentRange> selection, + const DisplayPosition& cursor, + std::optional<HitTarget> focus = {} ) const; private: + struct ReadingPosition + { + std::size_t index { 0 }; + bool at_start { true }; + }; + ReadingPosition reading_position( const DisplayPosition& position ) const; + std::size_t nearest_stop( LayoutPoint point ) const; + const LayoutGlyph& cursor_glyph( const DisplayPosition& position ) const; + DisplayPosition stop( std::size_t index ) const; + int columns_; LayoutData data_; + std::vector<std::size_t> stops_ {}; }; } // namespace ricochet::tui::detail |
