salvation_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 to start of document
113 DocumentStart,
114 /// Move cursor to end of document
115 DocumentEnd,
116 /// Move cursor up one page
117 PageUp,
118 /// Move cursor down one page
119 PageDown,
120 /// Move cursor up or down by a number of pixels
121 Vertical(i32),
122 /// Move cursor to previous word boundary
123 PreviousWord,
124 /// Move cursor to next word boundary
125 NextWord,
126 /// Move cursor to next word boundary to the left
127 LeftWord,
128 /// Move cursor to next word boundary to the right
129 RightWord,
130 /// Move cursor to the start of the document
131 BufferStart,
132 /// Move cursor to the end of the document
133 BufferEnd,
134 /// Move cursor to specific line
135 GotoLine(usize),
136}
137
138/// Scroll position in [`Buffer`]
139#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
140pub struct Scroll {
141 /// Index of [`BufferLine`] in [`Buffer::lines`]. This will be adjusted as needed if layout is
142 /// out of bounds
143 pub line: usize,
144 /// Index of [`LayoutLine`] in [`BufferLine::layout`]. This will be adjusted as needed
145 /// if it is negative or exceeds the number of layout lines
146 pub layout: i32,
147}
148
149impl Scroll {
150 /// Create a new cursor
151 pub const fn new(line: usize, layout: i32) -> Self {
152 Self { line, layout }
153 }
154}