From 23aa69fe90f28bec87069d8d0a98a591eeb4f7e4 Mon Sep 17 00:00:00 2001 From: Samuel Guerra Date: Fri, 16 Oct 2020 15:02:02 -0300 Subject: [PATCH] More documentation work. --- .vscode/spellright.dict | 1 + src/core/text.rs | 87 ++++++++++++++++++++++++++--------------- src/core/window.rs | 7 +++- src/widgets/view_.rs | 2 +- 4 files changed, 64 insertions(+), 33 deletions(-) diff --git a/.vscode/spellright.dict b/.vscode/spellright.dict index 7df672ea8..75b95ede0 100644 --- a/.vscode/spellright.dict +++ b/.vscode/spellright.dict @@ -53,3 +53,4 @@ twid qwid hkna nlck +seg diff --git a/src/core/text.rs b/src/core/text.rs index e5b3c45ab..c7e8c9abf 100644 --- a/src/core/text.rs +++ b/src/core/text.rs @@ -617,41 +617,38 @@ impl_from_and_into_var! { } } +/// The type of a [text segment](SegmentedText). #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub enum TextSegmentKind { - /// A sequence of characters that are not space. + /// A sequence of characters that cannot be separated by a line-break. Word, - /// A sequence of spaces. + /// A sequence of characters that all have the `White_Space` Unicode property, except the [`Tab`](Self::Tab) and + ///[`LineBreak`](Self::LineBreak) characters.. Space, - /// A sequence of tabs. + /// A sequence of `U+0009 TABULAR` characters. Tab, - /// A sequence of line-breaks. - HardBreak, -} -impl TextSegmentKind { - pub fn from_char(c: char) -> Self { - if c.is_whitespace() { - if c == ' ' { - TextSegmentKind::Space - } else if c == '\n' { - TextSegmentKind::HardBreak - } else if c == '\t' { - TextSegmentKind::Tab - } else { - TextSegmentKind::Space - } - } else { - TextSegmentKind::Word - } - } + /// A single line-break, `\n` or `\r\n`. + LineBreak, } +/// Represents a single text segment in a [`SegmentedText`]. +#[derive(Clone, Debug)] pub struct TextSegment { + /// Segment kind. pub kind: TextSegmentKind, /// Exclusive end index on the source text. + /// + /// The segment range starts from the `end` of the previous segment, or `0`, e.g: `prev_seg.end..self.end`. pub end: usize, } +/// A string segmented in sequences of words, spaces, tabs and separated line breaks. +/// +/// Each segment is tagged with a [`TextSegmentKind`] and is represented as +/// an offset from the last segment. +/// +/// Line-break segments must be applied and a line-break can be inserted in between the other segment kinds +/// for wrapping the text. pub struct SegmentedText<'a> { text: &'a str, segs: Vec, @@ -675,7 +672,7 @@ impl<'a> SegmentedText<'a> { }) } segs.push(TextSegment { - kind: TextSegmentKind::HardBreak, + kind: TextSegmentKind::LineBreak, end: offset, }) } else { @@ -685,15 +682,45 @@ impl<'a> SegmentedText<'a> { }) } } - if !text.ends_with('\n'){ + if !text.ends_with('\n') { if let Some(seg) = segs.last_mut() { seg.kind = TextSegmentKind::Word; - } + } } SegmentedText { text, segs } } - /// Iterate over segments. + /// The raw segments. + #[inline] + pub fn segs(&self) -> &[TextSegment] { + &self.segs + } + + /// Drops self taking the raw segments. + #[inline] + pub fn into_segs(self) -> Vec { + self.segs + } + + /// Segments iterator. + /// + /// # Example + /// + /// ``` + /// # use zero_ui::core::text::SegmentedText; + /// for (sub_str, segment_kind) in SegmentedText::new("Foo bar!\nBaz.").iter() { + /// println!("s: {:?} is a `{:?}`", sub_str, segment_kind); + /// } + /// ``` + /// Prints + /// ```text + /// "Foo" is a `Word` + /// " " is a `Space` + /// "bar!" is a `Word` + /// "\n" is a `HardBreak` + /// "Baz." is a `Word` + /// ``` + #[inline] pub fn iter(&'a self) -> SegmentedTextIter<'a> { SegmentedTextIter { text: self.text, @@ -703,6 +730,9 @@ impl<'a> SegmentedText<'a> { } } +/// Segmented text iterator. +/// +/// This `struct` is created by the [`SegmentedText::iter`] method. pub struct SegmentedTextIter<'a> { text: &'a str, start: usize, @@ -738,8 +768,3 @@ mod tests { } } } - -/// Count line-breaks in a [`TextSegment`] of kind [`TextSegmentKind::LineBreak`]. -fn count_line_breaks(line_break_seg: &str) -> usize { - line_break_seg.bytes().filter(|&b| b == b"\n"[0]).count() -} diff --git a/src/core/window.rs b/src/core/window.rs index 749e61696..004c924fa 100644 --- a/src/core/window.rs +++ b/src/core/window.rs @@ -1079,7 +1079,12 @@ impl OpenWindow { } fn monitor_layout_ctx(&self) -> LayoutContext { - let monitor = self.gl_ctx.borrow().window().current_monitor().expect("did not find current monitor"); + let monitor = self + .gl_ctx + .borrow() + .window() + .current_monitor() + .expect("did not find current monitor"); let size = monitor.size(); let scale = monitor.scale_factor() as f32; let size = LayoutSize::new(size.width as f32 * scale, size.height as f32 * scale); diff --git a/src/widgets/view_.rs b/src/widgets/view_.rs index 051e887ce..d3ad21543 100644 --- a/src/widgets/view_.rs +++ b/src/widgets/view_.rs @@ -60,7 +60,7 @@ impl, P: FnMut(&V, &mut WidgetContext) -> View /// # Example /// ``` /// use zero_ui::{ -/// core::{color::{rgb, rgba}, types::ToText, var::Var, UiNode}, +/// core::{color::{rgb, rgba}, text::ToText, var::Var, UiNode}, /// properties::text_theme::{text_color, font_size}, /// widgets::{text::text, view, View}, /// };