1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::wrap::{self, Wrap};
use prototty_render::*;
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};

#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct RichTextPartOwned {
    pub text: String,
    pub style: Style,
}

impl RichTextPartOwned {
    pub fn new(text: String, style: Style) -> Self {
        Self { text, style }
    }
    pub fn as_rich_text_part(&self) -> RichTextPart {
        RichTextPart {
            text: self.text.as_str(),
            style: self.style,
        }
    }
}

#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Copy)]
pub struct RichTextPart<'a> {
    pub text: &'a str,
    pub style: Style,
}

impl<'a> RichTextPart<'a> {
    pub fn new(text: &'a str, style: Style) -> Self {
        Self { text, style }
    }
}

pub struct RichTextView<W: Wrap> {
    wrap: W,
}

impl Default for RichTextView<wrap::Word> {
    fn default() -> Self {
        Self::new(wrap::Word::new())
    }
}

impl<W: Wrap> RichTextView<W> {
    pub fn new(wrap: W) -> Self {
        Self { wrap }
    }
}

impl<'a, I, W> View<I> for RichTextView<W>
where
    I: IntoIterator<Item = RichTextPart<'a>>,
    W: Wrap,
{
    fn view<F: Frame, C: ColModify>(&mut self, parts: I, context: ViewContext<C>, frame: &mut F) {
        self.wrap.clear();
        for part in parts {
            for character in part.text.chars() {
                self.wrap.process_character(character, part.style, context, frame);
            }
        }
        self.wrap.flush(context, frame);
    }
}

#[derive(Default, Debug, Clone, Copy)]
pub struct RichTextViewSingleLine;

impl RichTextViewSingleLine {
    pub const fn new() -> Self {
        Self
    }
}

impl<'a, I> View<I> for RichTextViewSingleLine
where
    I: IntoIterator<Item = RichTextPart<'a>>,
{
    fn view<F: Frame, C: ColModify>(&mut self, parts: I, context: ViewContext<C>, frame: &mut F) {
        RichTextView::new(wrap::None::new()).view(parts, context, frame)
    }
}

pub struct RichStringView<W: Wrap> {
    wrap: W,
}

impl<W: Wrap> RichStringView<W> {
    pub fn new(wrap: W) -> Self {
        Self { wrap }
    }
}

impl<'a, W> View<RichTextPart<'a>> for RichStringView<W>
where
    W: Wrap,
{
    fn view<F: Frame, C: ColModify>(&mut self, part: RichTextPart<'a>, context: ViewContext<C>, frame: &mut F) {
        self.wrap.clear();
        let part: RichTextPart = part.into();
        for character in part.text.chars() {
            self.wrap.process_character(character, part.style, context, frame);
        }
        self.wrap.flush(context, frame);
    }
}

#[derive(Default, Debug, Clone, Copy)]
pub struct RichStringViewSingleLine;

impl RichStringViewSingleLine {
    pub fn new() -> Self {
        Self
    }
}

impl<'a> View<RichTextPart<'a>> for RichStringViewSingleLine {
    fn view<F: Frame, C: ColModify>(&mut self, part: RichTextPart<'a>, context: ViewContext<C>, frame: &mut F) {
        RichStringView::new(wrap::None::new()).view(part, context, frame);
    }
}