use masonry::core::ArcStr;
use masonry::parley::style::{FontStack, FontWeight};
use masonry::widgets;
use super::{Label, label};
use crate::core::{MessageContext, Mut, ViewMarker, ViewPathTracker};
use crate::{MessageResult, Pod, TextAlign, View, ViewCtx, ViewId};
pub fn variable_label(text: impl Into<ArcStr>) -> VariableLabel {
VariableLabel {
label: label(text),
target_weight: FontWeight::NORMAL,
over_millis: 0.,
}
}
#[must_use = "View values do nothing unless provided to Xilem."]
pub struct VariableLabel {
label: Label,
target_weight: FontWeight,
over_millis: f32,
}
impl VariableLabel {
pub fn target_weight(mut self, weight: f32, over_millis: f32) -> Self {
assert!(weight.is_finite(), "Invalid target weight {weight}.");
self.target_weight = FontWeight::new(weight);
self.over_millis = over_millis;
self
}
pub fn font(mut self, font: impl Into<FontStack<'static>>) -> Self {
self.label = self.label.font(font);
self
}
pub fn text_alignment(mut self, text_alignment: TextAlign) -> Self {
self.label = self.label.text_alignment(text_alignment);
self
}
#[doc(alias = "font_size")]
pub fn text_size(mut self, text_size: f32) -> Self {
self.label = self.label.text_size(text_size);
self
}
}
impl ViewMarker for VariableLabel {}
impl<State, Action> View<State, Action, ViewCtx> for VariableLabel {
type Element = Pod<widgets::VariableLabel>;
type ViewState = ();
fn build(&self, ctx: &mut ViewCtx, app_state: &mut State) -> (Self::Element, Self::ViewState) {
let (label, ()) = ctx.with_id(ViewId::new(0), |ctx| {
View::<State, Action, _>::build(&self.label, ctx, app_state)
});
let widget_pod = ctx.create_pod(
widgets::VariableLabel::from_label(label.new_widget)
.with_initial_weight(self.target_weight.value()),
);
(widget_pod, ())
}
fn rebuild(
&self,
prev: &Self,
(): &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'_, Self::Element>,
app_state: &mut State,
) {
ctx.with_id(ViewId::new(0), |ctx| {
View::<State, Action, _>::rebuild(
&self.label,
&prev.label,
&mut (),
ctx,
widgets::VariableLabel::label_mut(&mut element),
app_state,
);
});
if prev.target_weight != self.target_weight {
widgets::VariableLabel::set_target_weight(
&mut element,
self.target_weight.value(),
self.over_millis,
);
}
}
fn teardown(
&self,
(): &mut Self::ViewState,
ctx: &mut ViewCtx,
mut element: Mut<'_, Self::Element>,
) {
ctx.with_id(ViewId::new(0), |ctx| {
View::<State, Action, _>::teardown(
&self.label,
&mut (),
ctx,
widgets::VariableLabel::label_mut(&mut element),
);
});
}
fn message(
&self,
(): &mut Self::ViewState,
message: &mut MessageContext,
mut element: Mut<'_, Self::Element>,
app_state: &mut State,
) -> MessageResult<Action> {
if let Some(first) = message.take_first() {
assert_eq!(first.routing_id(), 0);
self.label.message(
&mut (),
message,
widgets::VariableLabel::label_mut(&mut element),
app_state,
)
} else {
tracing::error!(
?message,
"Message arrived in VariableLabel::message, but VariableLabel doesn't consume any messages, this is a bug"
);
MessageResult::Stale
}
}
}