cosmic_text/
cursor.rs

1/// Current cursor location
2#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
3pub struct Cursor {
4    /// Index of [`BufferLine`] in [`Buffer::lines`]
5    pub line: usize,
6    /// First-byte-index of glyph at cursor (will insert behind this glyph)
7    pub index: usize,
8    /// Whether to associate the cursor with the run before it or the run after it if placed at the
9    /// boundary between two runs
10    pub affinity: Affinity,
11}
12
13impl Cursor {
14    /// Create a new cursor
15    pub const fn new(line: usize, index: usize) -> Self {
16        Self::new_with_affinity(line, index, Affinity::Before)
17    }
18
19    /// Create a new cursor, specifying the affinity
20    pub const fn new_with_affinity(line: usize, index: usize, affinity: Affinity) -> Self {
21        Self {
22            line,
23            index,
24            affinity,
25        }
26    }
27}
28
29/// Whether to associate cursors placed at a boundary between runs with the run before or after it.
30#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
31pub enum Affinity {
32    #[default]
33    Before,
34    After,
35}
36
37impl Affinity {
38    pub fn before(&self) -> bool {
39        *self == Self::Before
40    }
41
42    pub fn after(&self) -> bool {
43        *self == Self::After
44    }
45
46    pub fn from_before(before: bool) -> Self {
47        if before {
48            Self::Before
49        } else {
50            Self::After
51        }
52    }
53
54    pub fn from_after(after: bool) -> Self {
55        if after {
56            Self::After
57        } else {
58            Self::Before
59        }
60    }
61}
62
63/// The position of a cursor within a [`Buffer`].
64#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
65pub struct LayoutCursor {
66    /// Index of [`BufferLine`] in [`Buffer::lines`]
67    pub line: usize,
68    /// Index of [`LayoutLine`] in [`BufferLine::layout`]
69    pub layout: usize,
70    /// Index of [`LayoutGlyph`] in [`LayoutLine::glyphs`]
71    pub glyph: usize,
72}
73
74impl LayoutCursor {
75    /// Create a new [`LayoutCursor`]
76    pub const fn new(line: usize, layout: usize, glyph: usize) -> Self {
77        Self {
78            line,
79            layout,
80            glyph,
81        }
82    }
83}
84
85/// A motion to perform on a [`Cursor`]
86#[derive(Clone, Copy, Debug, Eq, PartialEq)]
87pub enum Motion {
88    /// Apply specific [`LayoutCursor`]
89    LayoutCursor(LayoutCursor),
90    /// Move cursor to previous character ([`Self::Left`] in LTR, [`Self::Right`] in RTL)
91    Previous,
92    /// Move cursor to next character ([`Self::Right`] in LTR, [`Self::Left`] in RTL)
93    Next,
94    /// Move cursor left
95    Left,
96    /// Move cursor right
97    Right,
98    /// Move cursor up
99    Up,
100    /// Move cursor down
101    Down,
102    /// Move cursor to start of line
103    Home,
104    /// Move cursor to start of line, skipping whitespace
105    SoftHome,
106    /// Move cursor to end of line
107    End,
108    /// Move cursor to start of paragraph
109    ParagraphStart,
110    /// Move cursor to end of paragraph
111    ParagraphEnd,
112    /// Move cursor up one page
113    PageUp,
114    /// Move cursor down one page
115    PageDown,
116    /// Move cursor up or down by a number of pixels
117    Vertical(i32),
118    /// Move cursor to previous word boundary
119    PreviousWord,
120    /// Move cursor to next word boundary
121    NextWord,
122    /// Move cursor to next word boundary to the left
123    LeftWord,
124    /// Move cursor to next word boundary to the right
125    RightWord,
126    /// Move cursor to the start of the document
127    BufferStart,
128    /// Move cursor to the end of the document
129    BufferEnd,
130    /// Move cursor to specific line
131    GotoLine(usize),
132}
133
134/// Scroll position in [`Buffer`]
135#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
136pub struct Scroll {
137    /// Index of [`BufferLine`] in [`Buffer::lines`]. This will be adjusted as needed if layout is
138    /// out of bounds
139    pub line: usize,
140    /// Pixel offset from the start of the [`BufferLine`]. This will be adjusted as needed
141    /// if it is negative or exceeds the height of the [`BufferLine::layout`] lines.
142    pub vertical: f32,
143    /// The horizontal position of scroll in fractional pixels
144    pub horizontal: f32,
145}
146
147impl Scroll {
148    /// Create a new scroll
149    pub const fn new(line: usize, vertical: f32, horizontal: f32) -> Self {
150        Self {
151            line,
152            vertical,
153            horizontal,
154        }
155    }
156}