use crate::prelude::*; use cosmic_text::{Attrs, Family, Metrics}; use std::marker::Sized; pub struct TextBuilder { pub content: String, pub attrs: TextAttrs, pub hint: H, pub output: O, } impl TextBuilder { pub fn size(mut self, size: impl UiNum) -> Self { self.attrs.font_size = size.to_f32(); self.attrs.line_height = self.attrs.font_size * LINE_HEIGHT_MULT; self } pub fn color(mut self, color: UiColor) -> Self { self.attrs.color = color; self } pub fn family(mut self, family: Family<'static>) -> Self { self.attrs.family = family; self } pub fn line_height(mut self, height: f32) -> Self { self.attrs.line_height = height; self } pub fn text_align(mut self, align: impl Into) -> Self { self.attrs.align = align.into(); self } pub fn center_text(mut self) -> Self { self.attrs.align = Align::CENTER; self } pub fn wrap(mut self, wrap: bool) -> Self { self.attrs.wrap = wrap; self } pub fn editable(self, single_line: bool) -> TextBuilder { TextBuilder { content: self.content, attrs: self.attrs, hint: self.hint, output: TextEditOutput { single_line }, } } } impl TextBuilder { pub fn hint, Tag>(self, hint: W) -> TextBuilder { TextBuilder { content: self.content, attrs: self.attrs, hint: move |ui: &mut Ui| Some(hint.add(ui).any()), output: self.output, } } } pub trait TextBuilderOutput: Sized { type Output; fn run(ui: &mut Ui, builder: TextBuilder) -> Self::Output; } pub struct TextOutput; impl TextBuilderOutput for TextOutput { type Output = Text; fn run(ui: &mut Ui, builder: TextBuilder) -> Self::Output { let mut buf = TextBuffer::new_empty(Metrics::new( builder.attrs.font_size, builder.attrs.line_height, )); let hint = builder.hint.get(ui); let font_system = &mut ui.data.text.font_system; buf.set_text(font_system, &builder.content, &Attrs::new(), SHAPING, None); let mut text = Text { content: builder.content.into(), view: TextView::new(buf, builder.attrs, hint), }; text.content.changed = false; builder.attrs.apply(font_system, &mut text.view.buf, None); text } } pub struct TextEditOutput { single_line: bool, } impl TextBuilderOutput for TextEditOutput { type Output = TextEdit; fn run(ui: &mut Ui, builder: TextBuilder) -> Self::Output { let buf = TextBuffer::new_empty(Metrics::new( builder.attrs.font_size, builder.attrs.line_height, )); let mut text = TextEdit::new( TextView::new(buf, builder.attrs, builder.hint.get(ui)), builder.output.single_line, ); let font_system = &mut ui.data.text.font_system; text.buf .set_text(font_system, &builder.content, &Attrs::new(), SHAPING, None); builder.attrs.apply(font_system, &mut text.buf, None); text } } impl FnOnce<(&mut Ui,)> for TextBuilder { type Output = O::Output; extern "rust-call" fn call_once(self, args: (&mut Ui,)) -> Self::Output { O::run(args.0, self) } } pub fn wtext(content: impl Into) -> TextBuilder { TextBuilder { content: content.into(), attrs: TextAttrs::default(), hint: (), output: TextOutput, } }