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); } }