use kas::prelude::*;
use kas::text;
use kas::text::format::FormattableText;
use kas::theme::TextClass;
impl_scope! {
#[widget]
pub struct Text<A, T: Default + FormattableText + 'static> {
core: widget_core!(),
class: TextClass,
label: text::Text<T>,
label_fn: Box<dyn Fn(&ConfigCx, &A) -> T>,
}
impl Default for Self where for<'a> &'a A: Into<T> {
fn default() -> Self {
Text {
core: Default::default(),
class: TextClass::Label(true),
label: text::Text::new(T::default()),
label_fn: Box::new(|_, data| data.into()),
}
}
}
impl Self {
#[inline]
pub fn new(label_fn: impl Fn(&ConfigCx, &A) -> T + 'static) -> Self {
Text {
core: Default::default(),
class: TextClass::Label(true),
label: text::Text::new(T::default()),
label_fn: Box::new(label_fn),
}
}
#[inline]
pub fn class(&self) -> TextClass {
self.class
}
#[inline]
pub fn set_class(&mut self, class: TextClass) {
self.class = class;
}
#[inline]
pub fn with_class(mut self, class: TextClass) -> Self {
self.class = class;
self
}
#[inline]
pub fn wrap(&self) -> bool {
self.class.multi_line()
}
#[inline]
pub fn set_wrap(&mut self, wrap: bool) {
self.class = TextClass::Label(wrap);
}
#[inline]
pub fn with_wrap(mut self, wrap: bool) -> Self {
self.class = TextClass::Label(wrap);
self
}
#[inline]
pub fn text(&self) -> &text::Text<T> {
&self.label
}
}
impl Layout for Self {
#[inline]
fn size_rules(&mut self, sizer: SizeCx, mut axis: AxisInfo) -> SizeRules {
axis.set_default_align_hv(Align::Default, Align::Center);
sizer.text_rules(&mut self.label, self.class, axis)
}
fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect) {
self.core.rect = rect;
cx.text_set_size(&mut self.label, self.class, rect.size, None);
}
#[cfg(feature = "min_spec")]
default fn draw(&mut self, mut draw: DrawCx) {
draw.text_effects(self.rect(), &self.label, self.class);
}
#[cfg(not(feature = "min_spec"))]
fn draw(&mut self, mut draw: DrawCx) {
draw.text_effects(self.rect(), &self.label, self.class);
}
}
impl Events for Self {
type Data = A;
fn update(&mut self, cx: &mut ConfigCx, data: &A) {
let text = (self.label_fn)(cx, data);
if text.as_str() == self.label.as_str() {
return;
}
self.label.set_text(text);
if self.label.env().bounds.1.is_finite() {
match self.label.try_prepare() {
Ok(true) => *cx |= Action::RESIZE,
_ => cx.redraw(self.id()),
}
}
}
}
}
#[cfg(feature = "min_spec")]
impl<'a, A> Layout for Text<A, &'a str> {
fn draw(&mut self, mut draw: DrawCx) {
draw.text(self.rect(), &self.label, self.class);
}
}
#[cfg(feature = "min_spec")]
impl<A> Layout for StringText<A> {
fn draw(&mut self, mut draw: DrawCx) {
draw.text(self.rect(), &self.label, self.class);
}
}
pub type StrText<A> = Text<A, &'static str>;
pub type StringText<A> = Text<A, String>;
#[macro_export]
macro_rules! format_data {
($data:ident, $($arg:tt)*) => {
$crate::Text::new(move |_, $data| format!($($arg)*))
};
($data:ident : $data_ty:ty , $($arg:tt)*) => {
$crate::Text::new(move |_, $data : $data_ty| format!($($arg)*))
};
}
#[macro_export]
macro_rules! format_value {
($($arg:tt)*) => {
$crate::Text::new(move |_, data| format!($($arg)*, data))
};
}