use ribir_core::{
class_names,
prelude::{anchor::Anchor, *},
};
use crate::prelude::*;
#[derive(Clone)]
pub struct BadgeColor(pub Color);
#[derive(Clone, Declare, PartialEq)]
pub struct Badge {
#[declare(default)]
pub content: Option<CowArc<str>>,
#[declare(default = Anchor::right_top(0., 0.))]
pub offset: Anchor,
}
#[derive(Clone, Declare, PartialEq)]
pub struct NumBadge {
#[declare(default)]
pub count: Option<u32>,
#[declare(default = 999u32)]
pub max_count: u32,
#[declare(default = Anchor::right_top(0., 0.))]
pub offset: Anchor,
}
class_names! {
BADGE_SMALL,
BADGE_LARGE,
}
impl<'a> ComposeChild<'a> for Badge {
type Child = Widget<'a>;
fn compose_child(this: impl StateWriter<Value = Self>, child: Self::Child) -> Widget<'a> {
stack! {
@ { child }
@ InParentLayout {
@Text {
visible: pipe!($read(this).content.is_some()),
x: pipe!($read(this).offset.x.clone().unwrap_or_default()),
y: pipe!($read(this).offset.y.clone().unwrap_or_default()),
text: pipe!($read(this).content.clone().unwrap_or_default()),
class: pipe! {
if $read(this).content.as_ref().map_or(true, |s| s.is_empty()) {
BADGE_SMALL
} else {
BADGE_LARGE
}
}
}
}
}
.into_widget()
}
}
impl<'a> ComposeChild<'a> for NumBadge {
type Child = Widget<'a>;
fn compose_child(this: impl StateWriter<Value = Self>, child: Self::Child) -> Widget<'a> {
badge! {
content: pipe!($read(this).count).map(move |v| {
v.map(|count| {
let max = $read(this).max_count;
if count > max {
format!("{}+", max).into()
} else {
count.to_string().into()
}
})
}),
offset: pipe!($read(this).offset.clone()),
@ { child }
}
.into_widget()
}
}
#[cfg(test)]
mod tests {
use ribir_core::test_helper::*;
use ribir_dev_helper::*;
use super::*;
widget_image_tests!(
badge,
WidgetTester::new(self::column! {
@Badge {
content: Some("".into()),
@Container { size: Size::new(40., 40.), background: Color::GRAY }
}
@Badge {
content: Some("error!".into()),
offset: Anchor::right(-14.),
@Container { size: Size::new(40., 40.)}
}
@NumBadge {
count: 1000,
max_count: 99_u32,
providers: [Provider::new(BadgeColor(Color::GREEN))],
@Container { size: Size::new(40., 40.), background: Color::GRAY }
}
})
.with_wnd_size(Size::new(200., 200.))
.with_comparison(0.0001),
);
}