use crate::component::{Component, EventCx, LayoutCx, MeasureCx};
use crate::event::Event;
use crate::geom::{Rect, Size};
use crate::layout::Constraint;
use crate::render::RenderCx;
use crate::style::{Style, TextWrap};
pub struct Label {
text: String,
style: Style,
id: Option<String>,
class: Option<String>,
}
impl Label {
pub fn new(text: impl Into<String>) -> Self {
Self {
text: text.into(),
style: Style::default(),
id: None,
class: None,
}
}
pub fn style(mut self, style: Style) -> Self {
self.style = style;
self
}
pub fn id(mut self, id: impl Into<String>) -> Self {
self.id = Some(id.into());
self
}
pub fn class(mut self, class: impl Into<String>) -> Self {
self.class = Some(class.into());
self
}
}
impl Component for Label {
fn render(&self, cx: &mut RenderCx) {
let segments: Vec<&str> = self.text.split('\n').collect();
for (i, seg) in segments.iter().enumerate() {
if i > 0 {
cx.cursor.y = cx.cursor.y.saturating_add(1);
cx.cursor.x = cx.rect.x;
}
match cx.wrap {
TextWrap::None => {
let tw: u16 = seg.chars().map(|c| unicode_width::UnicodeWidthChar::width(c).unwrap_or(0) as u16).sum();
cx.cursor.x = cx.cursor.x.saturating_add(cx.align_offset(tw));
cx.text(seg);
}
TextWrap::Char => cx.line(seg),
}
}
}
fn measure(&self, constraint: Constraint, _cx: &mut MeasureCx) -> Size {
let max_w = constraint.max.width.max(1);
let mut line_width: u16 = 0;
let mut lines: u16 = 1;
let mut total_w: u16 = 0;
for c in self.text.chars() {
if c == '\n' {
lines += 1;
total_w = total_w.max(line_width);
line_width = 0;
continue;
}
let w = unicode_width::UnicodeWidthChar::width(c).unwrap_or(0) as u16;
if line_width + w > max_w {
lines += 1;
total_w = total_w.max(line_width);
line_width = w;
} else {
line_width += w;
}
}
total_w = total_w.max(line_width);
Size {
width: max_w.min(total_w),
height: lines,
}
}
fn layout(&mut self, _rect: Rect, _cx: &mut LayoutCx) {
}
fn style(&self) -> Style {
self.style.clone()
}
fn id(&self) -> Option<&str> {
self.id.as_deref()
}
fn class(&self) -> Option<&str> {
self.class.as_deref()
}
fn focusable(&self) -> bool {
false
}
fn event(&mut self, _event: &Event, _cx: &mut EventCx) {}
}