Add enum for cursor affinity; rename constructor to new_with_affinity
This commit is contained in:
parent
da842ec10d
commit
c6cf57e213
2 changed files with 61 additions and 21 deletions
|
|
@ -21,17 +21,17 @@ pub struct Cursor {
|
||||||
pub index: usize,
|
pub index: usize,
|
||||||
/// Whether to associate the cursor with the run before it (false) or the run after it (true)
|
/// Whether to associate the cursor with the run before it (false) or the run after it (true)
|
||||||
/// if placed at the boundary between two runs
|
/// if placed at the boundary between two runs
|
||||||
pub affinity: bool,
|
pub affinity: Affinity,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cursor {
|
impl Cursor {
|
||||||
/// Create a new cursor
|
/// Create a new cursor
|
||||||
pub const fn new(line: usize, index: usize) -> Self {
|
pub const fn new(line: usize, index: usize) -> Self {
|
||||||
Self::new_affinity(line, index, false)
|
Self::new_with_affinity(line, index, Affinity::Before)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new cursor, specifying the affinity
|
/// Create a new cursor, specifying the affinity
|
||||||
pub const fn new_affinity(line: usize, index: usize, affinity: bool) -> Self {
|
pub const fn new_with_affinity(line: usize, index: usize, affinity: Affinity) -> Self {
|
||||||
Self {
|
Self {
|
||||||
line,
|
line,
|
||||||
index,
|
index,
|
||||||
|
|
@ -40,6 +40,44 @@ impl Cursor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
pub enum Affinity {
|
||||||
|
Before,
|
||||||
|
After,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Affinity {
|
||||||
|
pub fn before(&self) -> bool {
|
||||||
|
*self == Self::Before
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn after(&self) -> bool {
|
||||||
|
*self == Self::After
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_before(before: bool) -> Self {
|
||||||
|
if before {
|
||||||
|
Self::Before
|
||||||
|
} else {
|
||||||
|
Self::After
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_after(after: bool) -> Self {
|
||||||
|
if after {
|
||||||
|
Self::After
|
||||||
|
} else {
|
||||||
|
Self::Before
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Affinity {
|
||||||
|
fn default() -> Self {
|
||||||
|
Affinity::Before
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct LayoutCursor {
|
pub struct LayoutCursor {
|
||||||
pub line: usize,
|
pub line: usize,
|
||||||
pub layout: usize,
|
pub layout: usize,
|
||||||
|
|
@ -113,17 +151,17 @@ impl<'a> LayoutRun<'a> {
|
||||||
|
|
||||||
fn cursor_from_glyph_left(&self, glyph: &LayoutGlyph) -> Cursor {
|
fn cursor_from_glyph_left(&self, glyph: &LayoutGlyph) -> Cursor {
|
||||||
if self.rtl {
|
if self.rtl {
|
||||||
Cursor::new_affinity(self.line_i, glyph.end, false)
|
Cursor::new_with_affinity(self.line_i, glyph.end, Affinity::Before)
|
||||||
} else {
|
} else {
|
||||||
Cursor::new_affinity(self.line_i, glyph.start, true)
|
Cursor::new_with_affinity(self.line_i, glyph.start, Affinity::After)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor_from_glyph_right(&self, glyph: &LayoutGlyph) -> Cursor {
|
fn cursor_from_glyph_right(&self, glyph: &LayoutGlyph) -> Cursor {
|
||||||
if self.rtl {
|
if self.rtl {
|
||||||
Cursor::new_affinity(self.line_i, glyph.start, true)
|
Cursor::new_with_affinity(self.line_i, glyph.start, Affinity::After)
|
||||||
} else {
|
} else {
|
||||||
Cursor::new_affinity(self.line_i, glyph.end, false)
|
Cursor::new_with_affinity(self.line_i, glyph.end, Affinity::Before)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -398,8 +436,10 @@ impl<'a> Buffer<'a> {
|
||||||
let layout = line.layout_opt().as_ref().expect("layout not found");
|
let layout = line.layout_opt().as_ref().expect("layout not found");
|
||||||
for (layout_i, layout_line) in layout.iter().enumerate() {
|
for (layout_i, layout_line) in layout.iter().enumerate() {
|
||||||
for (glyph_i, glyph) in layout_line.glyphs.iter().enumerate() {
|
for (glyph_i, glyph) in layout_line.glyphs.iter().enumerate() {
|
||||||
let cursor_end = Cursor::new_affinity(cursor.line, glyph.end, false);
|
let cursor_end =
|
||||||
let cursor_start = Cursor::new_affinity(cursor.line, glyph.start, true);
|
Cursor::new_with_affinity(cursor.line, glyph.end, Affinity::Before);
|
||||||
|
let cursor_start =
|
||||||
|
Cursor::new_with_affinity(cursor.line, glyph.start, Affinity::After);
|
||||||
let (cursor_left, cursor_right) = if glyph.level.is_ltr() {
|
let (cursor_left, cursor_right) = if glyph.level.is_ltr() {
|
||||||
(cursor_start, cursor_end)
|
(cursor_start, cursor_end)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -557,7 +597,7 @@ impl<'a> Buffer<'a> {
|
||||||
} else if y >= line_y - font_size && y < line_y - font_size + line_height {
|
} else if y >= line_y - font_size && y < line_y - font_size + line_height {
|
||||||
let mut new_cursor_glyph = run.glyphs.len();
|
let mut new_cursor_glyph = run.glyphs.len();
|
||||||
let mut new_cursor_char = 0;
|
let mut new_cursor_char = 0;
|
||||||
let mut new_cursor_affinity = true;
|
let mut new_cursor_affinity = Affinity::After;
|
||||||
|
|
||||||
let mut first_glyph = true;
|
let mut first_glyph = true;
|
||||||
|
|
||||||
|
|
@ -584,7 +624,7 @@ impl<'a> Buffer<'a> {
|
||||||
if right_half != glyph.level.is_rtl() {
|
if right_half != glyph.level.is_rtl() {
|
||||||
// If clicking on last half of glyph, move cursor past glyph
|
// If clicking on last half of glyph, move cursor past glyph
|
||||||
new_cursor_char += egc.len();
|
new_cursor_char += egc.len();
|
||||||
new_cursor_affinity = false;
|
new_cursor_affinity = Affinity::Before;
|
||||||
}
|
}
|
||||||
break 'hit;
|
break 'hit;
|
||||||
}
|
}
|
||||||
|
|
@ -595,7 +635,7 @@ impl<'a> Buffer<'a> {
|
||||||
if right_half != glyph.level.is_rtl() {
|
if right_half != glyph.level.is_rtl() {
|
||||||
// If clicking on last half of glyph, move cursor past glyph
|
// If clicking on last half of glyph, move cursor past glyph
|
||||||
new_cursor_char = cluster.len();
|
new_cursor_char = cluster.len();
|
||||||
new_cursor_affinity = false;
|
new_cursor_affinity = Affinity::Before;
|
||||||
}
|
}
|
||||||
break 'hit;
|
break 'hit;
|
||||||
}
|
}
|
||||||
|
|
@ -613,7 +653,7 @@ impl<'a> Buffer<'a> {
|
||||||
if let Some(glyph) = run.glyphs.last() {
|
if let Some(glyph) = run.glyphs.last() {
|
||||||
// Position at end of line
|
// Position at end of line
|
||||||
new_cursor.index = glyph.end;
|
new_cursor.index = glyph.end;
|
||||||
new_cursor.affinity = false;
|
new_cursor.affinity = Affinity::Before;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
#[cfg(feature = "swash")]
|
#[cfg(feature = "swash")]
|
||||||
use crate::Color;
|
use crate::Color;
|
||||||
use crate::{Action, AttrsList, Buffer, BufferLine, Cursor, Edit, LayoutCursor};
|
use crate::{Action, Affinity, AttrsList, Buffer, BufferLine, Cursor, Edit, LayoutCursor};
|
||||||
|
|
||||||
/// A wrapper of [`Buffer`] for easy editing
|
/// A wrapper of [`Buffer`] for easy editing
|
||||||
pub struct Editor<'a> {
|
pub struct Editor<'a> {
|
||||||
|
|
@ -45,11 +45,11 @@ impl<'a> Editor<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let (new_index, new_affinity) = match layout_line.glyphs.get(cursor.glyph) {
|
let (new_index, new_affinity) = match layout_line.glyphs.get(cursor.glyph) {
|
||||||
Some(glyph) => (glyph.start, true),
|
Some(glyph) => (glyph.start, Affinity::After),
|
||||||
None => match layout_line.glyphs.last() {
|
None => match layout_line.glyphs.last() {
|
||||||
Some(glyph) => (glyph.end, false),
|
Some(glyph) => (glyph.end, Affinity::Before),
|
||||||
//TODO: is this correct?
|
//TODO: is this correct?
|
||||||
None => (0, true),
|
None => (0, Affinity::After),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -294,12 +294,12 @@ impl<'a> Edit<'a> for Editor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.cursor.index = prev_index;
|
self.cursor.index = prev_index;
|
||||||
self.cursor.affinity = true;
|
self.cursor.affinity = Affinity::After;
|
||||||
self.buffer.set_redraw(true);
|
self.buffer.set_redraw(true);
|
||||||
} else if self.cursor.line > 0 {
|
} else if self.cursor.line > 0 {
|
||||||
self.cursor.line -= 1;
|
self.cursor.line -= 1;
|
||||||
self.cursor.index = self.buffer.lines[self.cursor.line].text().len();
|
self.cursor.index = self.buffer.lines[self.cursor.line].text().len();
|
||||||
self.cursor.affinity = true;
|
self.cursor.affinity = Affinity::After;
|
||||||
self.buffer.set_redraw(true);
|
self.buffer.set_redraw(true);
|
||||||
}
|
}
|
||||||
self.cursor_x_opt = None;
|
self.cursor_x_opt = None;
|
||||||
|
|
@ -310,7 +310,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
||||||
for (i, c) in line.text().grapheme_indices(true) {
|
for (i, c) in line.text().grapheme_indices(true) {
|
||||||
if i == self.cursor.index {
|
if i == self.cursor.index {
|
||||||
self.cursor.index += c.len();
|
self.cursor.index += c.len();
|
||||||
self.cursor.affinity = false;
|
self.cursor.affinity = Affinity::Before;
|
||||||
self.buffer.set_redraw(true);
|
self.buffer.set_redraw(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -318,7 +318,7 @@ impl<'a> Edit<'a> for Editor<'a> {
|
||||||
} else if self.cursor.line + 1 < self.buffer.lines.len() {
|
} else if self.cursor.line + 1 < self.buffer.lines.len() {
|
||||||
self.cursor.line += 1;
|
self.cursor.line += 1;
|
||||||
self.cursor.index = 0;
|
self.cursor.index = 0;
|
||||||
self.cursor.affinity = false;
|
self.cursor.affinity = Affinity::Before;
|
||||||
self.buffer.set_redraw(true);
|
self.buffer.set_redraw(true);
|
||||||
}
|
}
|
||||||
self.cursor_x_opt = None;
|
self.cursor_x_opt = None;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue