diff --git a/examples/editor-test/src/main.rs b/examples/editor-test/src/main.rs index ff1e84a..24af48c 100644 --- a/examples/editor-test/src/main.rs +++ b/examples/editor-test/src/main.rs @@ -3,6 +3,7 @@ use cosmic_text::{FontSystem, SwashCache, TextAction, TextBuffer, TextMetrics}; use orbclient::{Color, EventOption, Renderer, Window, WindowFlag}; use std::{env, fs, process, thread, time::{Duration, Instant}}; +use unicode_segmentation::UnicodeSegmentation; fn redraw(window: &mut Window, buffer: &mut TextBuffer<'_>, swash_cache: &mut SwashCache) { let bg_color = Color::rgb(0x34, 0x34, 0x34); diff --git a/examples/syntax/src/main.rs b/examples/syntax/src/main.rs index b46799f..4d7f59a 100644 --- a/examples/syntax/src/main.rs +++ b/examples/syntax/src/main.rs @@ -81,9 +81,6 @@ fn main() { ); buffer.set_text(&text); - for line in buffer.lines.iter_mut() { - line.wrap_simple = true; - } let mut bg_color = orbclient::Color::rgb(0x00, 0x00, 0x00); let mut font_color = orbclient::Color::rgb(0xFF, 0xFF, 0xFF); @@ -190,10 +187,9 @@ fn main() { ); } - if attrs_list != line.attrs_list { - line.attrs_list = attrs_list; - line.reset(); - } + // Update line attributes. This operation only resets if the line changes + line.set_attrs_list(attrs_list); + line.set_wrap_simple(true); //TODO: efficiently do syntax highlighting without having to shape whole buffer line.shape(&font_system); diff --git a/src/buffer.rs b/src/buffer.rs index 7d1a5be..a0e665d 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -175,10 +175,10 @@ impl fmt::Display for TextMetrics { pub struct TextBufferLine<'a> { text: String, - pub attrs_list: AttrsList<'a>, + attrs_list: AttrsList<'a>, + wrap_simple: bool, shape_opt: Option, layout_opt: Option>, - pub wrap_simple: bool, } impl<'a> TextBufferLine<'a> { @@ -186,25 +186,78 @@ impl<'a> TextBufferLine<'a> { Self { text, attrs_list, + wrap_simple: false, shape_opt: None, layout_opt: None, - wrap_simple: false, } } + /// Get current text pub fn text(&self) -> &str { &self.text } + /// Set text + /// Will reset shape and layout if it differs from current text + /// Returns true if the line was reset + pub fn set_text + Into>(&mut self, text: T) -> bool { + if text.as_ref() != &self.text { + self.text = text.into(); + self.reset(); + true + } else { + false + } + } + + /// Get attributes list + pub fn attrs_list(&self) -> &AttrsList<'a> { + &self.attrs_list + } + + /// Set attributes list. + /// Will reset shape and layout if it differs from current attributes list + /// Returns true if the line was reset + pub fn set_attrs_list(&mut self, attrs_list: AttrsList<'a>) -> bool { + if attrs_list != self.attrs_list { + self.attrs_list = attrs_list; + self.reset(); + true + } else { + false + } + } + + /// Get simple wrapping setting (wrap by characters only) + pub fn wrap_simple(&self) -> bool { + self.wrap_simple + } + + /// Set simple wrapping setting (wrap by characters only) + /// Will reset shape and layout if it differs from current simple wrapping setting + /// Returns true if the line was reset + pub fn set_wrap_simple(&mut self, wrap_simple: bool) -> bool { + if wrap_simple != self.wrap_simple { + self.wrap_simple = wrap_simple; + self.reset(); + true + } else { + false + } + } + + /// Reset shaping and layout information pub fn reset(&mut self) { self.shape_opt = None; self.layout_opt = None; } + /// Check if shaping and layout information is cleared pub fn is_reset(&self) -> bool { self.shape_opt.is_none() } + /// Shape line, will cache results pub fn shape(&mut self, font_system: &'a FontSystem<'a>) -> &ShapeLine { if self.shape_opt.is_none() { self.shape_opt = Some(ShapeLine::new(font_system, &self.text, &self.attrs_list)); @@ -213,6 +266,7 @@ impl<'a> TextBufferLine<'a> { self.shape_opt.as_ref().unwrap() } + /// Layout line, will cache results pub fn layout(&mut self, font_system: &'a FontSystem<'a>, font_size: i32, width: i32) -> &[LayoutLine] { if self.layout_opt.is_none() { let mut layout = Vec::new();