summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/src/renderer/null.rs12
-rw-r--r--core/src/text/editor.rs6
-rw-r--r--graphics/src/text/editor.rs41
-rw-r--r--widget/src/text_editor.rs48
4 files changed, 107 insertions, 0 deletions
diff --git a/core/src/renderer/null.rs b/core/src/renderer/null.rs
index e714e492..01a52c7a 100644
--- a/core/src/renderer/null.rs
+++ b/core/src/renderer/null.rs
@@ -125,6 +125,18 @@ impl text::Editor for () {
text::editor::Cursor::Caret(Point::ORIGIN)
}
+ fn selection(&self) -> Option<String> {
+ None
+ }
+
+ fn line(&self, _index: usize) -> Option<&str> {
+ None
+ }
+
+ fn line_count(&self) -> usize {
+ 0
+ }
+
fn perform(&mut self, _action: text::editor::Action) {}
fn bounds(&self) -> Size {
diff --git a/core/src/text/editor.rs b/core/src/text/editor.rs
index 56cda3ef..5532fac5 100644
--- a/core/src/text/editor.rs
+++ b/core/src/text/editor.rs
@@ -9,6 +9,12 @@ pub trait Editor: Sized + Default {
fn cursor(&self) -> Cursor;
+ fn selection(&self) -> Option<String>;
+
+ fn line(&self, index: usize) -> Option<&str>;
+
+ fn line_count(&self) -> usize;
+
fn perform(&mut self, action: Action);
/// Returns the current boundaries of the [`Editor`].
diff --git a/graphics/src/text/editor.rs b/graphics/src/text/editor.rs
index 07a2d72a..1e375a25 100644
--- a/graphics/src/text/editor.rs
+++ b/graphics/src/text/editor.rs
@@ -69,6 +69,47 @@ impl editor::Editor for Editor {
})))
}
+ fn line(&self, index: usize) -> Option<&str> {
+ self.buffer()
+ .lines
+ .get(index)
+ .map(cosmic_text::BufferLine::text)
+ }
+
+ fn line_count(&self) -> usize {
+ self.buffer().lines.len()
+ }
+
+ fn selection(&self) -> Option<String> {
+ let internal = self.internal();
+
+ let cursor = internal.editor.cursor();
+ let selection = internal.editor.select_opt()?;
+
+ let (start, end) = if cursor < selection {
+ (cursor, selection)
+ } else {
+ (selection, cursor)
+ };
+
+ Some(
+ internal.editor.buffer().lines[start.line..=end.line]
+ .iter()
+ .enumerate()
+ .map(|(i, line)| {
+ if i == 0 {
+ &line.text()[start.index..]
+ } else if i == end.line - start.line {
+ &line.text()[..end.index]
+ } else {
+ line.text()
+ }
+ })
+ .collect::<Vec<_>>()
+ .join("\n"),
+ )
+ }
+
fn cursor(&self) -> editor::Cursor {
let internal = self.internal();
diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs
index 114d35ef..ec7a6d1d 100644
--- a/widget/src/text_editor.rs
+++ b/widget/src/text_editor.rs
@@ -100,6 +100,54 @@ where
internal.editor.perform(action);
internal.is_dirty = true;
}
+
+ pub fn line_count(&self) -> usize {
+ self.0.borrow().editor.line_count()
+ }
+
+ pub fn line(
+ &self,
+ index: usize,
+ ) -> Option<impl std::ops::Deref<Target = str> + '_> {
+ std::cell::Ref::filter_map(self.0.borrow(), |internal| {
+ internal.editor.line(index)
+ })
+ .ok()
+ }
+
+ pub fn lines(
+ &self,
+ ) -> impl Iterator<Item = impl std::ops::Deref<Target = str> + '_> {
+ struct Lines<'a, Renderer: text::Renderer> {
+ internal: std::cell::Ref<'a, Internal<Renderer>>,
+ current: usize,
+ }
+
+ impl<'a, Renderer: text::Renderer> Iterator for Lines<'a, Renderer> {
+ type Item = std::cell::Ref<'a, str>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let line = std::cell::Ref::filter_map(
+ std::cell::Ref::clone(&self.internal),
+ |internal| internal.editor.line(self.current),
+ )
+ .ok()?;
+
+ self.current += 1;
+
+ Some(line)
+ }
+ }
+
+ Lines {
+ internal: self.0.borrow(),
+ current: 0,
+ }
+ }
+
+ pub fn selection(&self) -> Option<String> {
+ self.0.borrow().editor.selection()
+ }
}
impl<Renderer> Default for Content<Renderer>