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}