use derive_builder::Builder;
use tessera_ui::{Color, ComputedData, DimensionValue, Dp, Px, accesskit::Role, tessera};
use crate::pipelines::{TextCommand, TextConstraint, TextData};
#[derive(Debug, Default, Builder, Clone)]
#[builder(pattern = "owned")]
pub struct TextArgs {
#[builder(setter(into))]
pub text: String,
#[builder(default = "Color::BLACK")]
pub color: Color,
#[builder(default = "Dp(25.0)")]
pub size: Dp,
#[builder(default, setter(strip_option))]
pub line_height: Option<Dp>,
#[builder(default, setter(strip_option, into))]
pub accessibility_label: Option<String>,
#[builder(default, setter(strip_option, into))]
pub accessibility_description: Option<String>,
}
impl From<String> for TextArgs {
fn from(val: String) -> Self {
TextArgsBuilder::default().text(val).build().unwrap()
}
}
impl From<&str> for TextArgs {
fn from(val: &str) -> Self {
TextArgsBuilder::default()
.text(val.to_string())
.build()
.unwrap()
}
}
#[tessera]
pub fn text(args: impl Into<TextArgs>) {
let text_args: TextArgs = args.into();
let accessibility_label = text_args.accessibility_label.clone();
let accessibility_description = text_args.accessibility_description.clone();
let text_for_accessibility = text_args.text.clone();
input_handler(Box::new(move |input| {
let mut builder = input.accessibility().role(Role::Label);
if let Some(label) = accessibility_label.as_ref() {
builder = builder.label(label.clone());
} else if !text_for_accessibility.is_empty() {
builder = builder.label(text_for_accessibility.clone());
}
if let Some(description) = accessibility_description.as_ref() {
builder = builder.description(description.clone());
}
builder.commit();
}));
measure(Box::new(move |input| {
let max_width: Option<Px> = match input.parent_constraint.width {
DimensionValue::Fixed(w) => Some(w),
DimensionValue::Wrap { max, .. } => max, DimensionValue::Fill { max, .. } => max, };
let max_height: Option<Px> = match input.parent_constraint.height {
DimensionValue::Fixed(h) => Some(h),
DimensionValue::Wrap { max, .. } => max, DimensionValue::Fill { max, .. } => max, };
let line_height = text_args.line_height.unwrap_or(Dp(text_args.size.0 * 1.2));
let text_data = TextData::new(
text_args.text.clone(),
text_args.color,
text_args.size.to_pixels_f32(),
line_height.to_pixels_f32(),
TextConstraint {
max_width: max_width.map(|px| px.to_f32()),
max_height: max_height.map(|px| px.to_f32()),
},
);
let size = text_data.size;
let drawable = TextCommand { data: text_data };
input.metadata_mut().push_draw_command(drawable);
Ok(ComputedData {
width: size[0].into(),
height: size[1].into(),
})
}));
}