use std::rc::Rc;
use teksilo_core::widget::Widget;
use teksilo_i18n::LocalizedString;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum StepStatus {
#[default]
Upcoming,
Active,
Complete,
Error,
Disabled,
Optional,
Skipped,
}
impl StepStatus {
pub fn is_optional(self) -> bool {
matches!(self, StepStatus::Optional)
}
}
pub(crate) type StepContentFactory = Rc<dyn Fn() -> Box<dyn Widget>>;
pub(crate) type StepValidator = Rc<dyn Fn() -> bool>;
#[derive(Clone)]
pub struct Step {
pub(crate) title: LocalizedString,
pub(crate) supporting_text: Option<LocalizedString>,
pub(crate) content_factory: Option<StepContentFactory>,
pub(crate) initial_status: StepStatus,
pub(crate) complete: Option<teksilo_core::signal::Prop<bool>>,
pub(crate) validate: Option<StepValidator>,
pub(crate) visible: Option<teksilo_core::signal::Prop<bool>>,
}
impl Step {
pub fn new(title: impl Into<LocalizedString>) -> Self {
Self {
title: title.into(),
supporting_text: None,
content_factory: None,
initial_status: StepStatus::Upcoming,
complete: None,
validate: None,
visible: None,
}
}
pub fn content<W, F>(mut self, factory: F) -> Self
where
W: Widget + 'static,
F: Fn() -> W + 'static,
{
self.content_factory = Some(Rc::new(move || Box::new(factory()) as Box<dyn Widget>));
self
}
pub fn content_boxed(mut self, factory: impl Fn() -> Box<dyn Widget> + 'static) -> Self {
self.content_factory = Some(Rc::new(factory));
self
}
#[allow(dead_code)]
pub(crate) fn content_factory_rc(mut self, factory: StepContentFactory) -> Self {
self.content_factory = Some(factory);
self
}
pub fn supporting_text(mut self, text: impl Into<LocalizedString>) -> Self {
self.supporting_text = Some(text.into());
self
}
pub fn status(mut self, status: StepStatus) -> Self {
self.initial_status = status;
self
}
pub fn optional(mut self, optional: bool) -> Self {
if optional {
self.initial_status = StepStatus::Optional;
} else if self.initial_status == StepStatus::Optional {
self.initial_status = StepStatus::Upcoming;
}
self
}
pub fn complete_when(mut self, signal: impl Into<teksilo_core::signal::Prop<bool>>) -> Self {
self.complete = Some(signal.into());
self
}
pub fn validate_on_next(mut self, f: impl Fn() -> bool + 'static) -> Self {
self.validate = Some(Rc::new(f));
self
}
pub fn visible_when(mut self, visible: impl Into<teksilo_core::signal::Prop<bool>>) -> Self {
self.visible = Some(visible.into());
self
}
}
impl std::fmt::Debug for Step {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Step")
.field("title", &self.title)
.field("supporting_text", &self.supporting_text)
.field("initial_status", &self.initial_status)
.field("has_content", &self.content_factory.is_some())
.field("has_complete_gate", &self.complete.is_some())
.finish()
}
}