use crate::action_task::{ActionTask, CatchUnwind};
use ferroui_base::threading::{Dispatcher, DispatcherPriority};
use ferroui_base::{
ferro_class, ferro_class_info, ferro_properties, instantiate, BoxedValue, FerroObjectImpl, FerroObjectImplExt,
FerroProperty, FerroPropertyChangedEventArgs, Ref, StyledElementImpl, StyledProperty,
};
use ferroui_xaml_interactivity::{Interaction, StyledElementBehaviorImpl, StyledElementTrigger};
use std::rc::Rc;
#[repr(C)]
pub struct TaskCompletedTrigger {
base: StyledElementTrigger,
}
ferro_class!(TaskCompletedTrigger: StyledElementTrigger);
ferro_class_info!(TaskCompletedTrigger { new: TaskCompletedTrigger::new });
ferroui_base::ferro_impl_classes!(TaskCompletedTrigger: StyledElementImpl, StyledElementBehaviorImpl);
ferro_properties! {
impl TaskCompletedTrigger {
pub fn task_property() -> StyledProperty<Option<ActionTask>> {
FerroProperty::register::<TaskCompletedTrigger, _>("Task", None)
}
}
}
ferroui_base::ferro_overrides! {
impl FerroObjectImpl for TaskCompletedTrigger {
fn on_property_changed(this: &Self, change: &FerroPropertyChangedEventArgs<'_>) {
Self::parent_on_property_changed(this, change);
if change.property() == Self::task_property().as_property() {
this.on_task_changed(change.get_new_value::<Option<ActionTask>>());
}
}
}
}
impl TaskCompletedTrigger {
pub fn construct() -> Self {
Self { base: StyledElementTrigger::construct() }
}
pub fn new() -> Ref<Self> {
instantiate(Self::construct())
}
pub fn task(&self) -> Option<ActionTask> {
self.get_value(Self::task_property())
}
pub fn set_task(&self, value: Option<ActionTask>) {
self.set_value(Self::task_property(), value)
}
fn on_task_changed(&self, task: Option<ActionTask>) {
let Some(task) = task else {
return;
};
let trigger: Ref<TaskCompletedTrigger> = self.to_ref();
drop(ActionTask::spawn(async move {
let _ = CatchUnwind::new(task).await;
Dispatcher::ui_thread().post_local(
move || {
let sender = trigger
.associated_object()
.map(|associated_object| Rc::new(associated_object) as BoxedValue);
Interaction::execute_actions(sender.as_ref(), trigger.actions().as_ref(), None);
},
DispatcherPriority::DEFAULT,
);
}));
}
}