Skip to main content

ferroui_xaml_interactions_custom/file_upload/
button_upload_file_behavior.rs

1//! Port of `FileUpload/ButtonUploadFileBehavior.cs`.
2
3use crate::UploadFileBehaviorBase;
4use ferroui_base::interactivity::{IRoutedEventArgs, Interactive, RoutedEventArgs, RoutedEventHandlerToken};
5use ferroui_base::{
6    ferro_class, ferro_class_info, instantiate, BoxedValue, FerroObject, FerroObjectImpl, Ref, StyledElementImpl,
7    WeakRef,
8};
9use ferroui_controls::Button;
10use ferroui_xaml_interactivity::{StyledElementBehaviorImpl, StyledElementBehaviorImplExt};
11use std::cell::RefCell;
12use std::rc::Rc;
13
14/// Upload file behavior for [`Button`]: a click uploads the file.
15#[repr(C)]
16pub struct ButtonUploadFileBehavior {
17    base: UploadFileBehaviorBase,
18    // The button the click handler is attached to (`button.Click += OnClick`).
19    click: RefCell<Option<(WeakRef<Button>, RoutedEventHandlerToken)>>,
20}
21
22ferro_class!(ButtonUploadFileBehavior: UploadFileBehaviorBase);
23ferro_class_info!(ButtonUploadFileBehavior { new: ButtonUploadFileBehavior::new });
24ferroui_base::ferro_impl_classes!(ButtonUploadFileBehavior: FerroObjectImpl, StyledElementImpl);
25
26ferroui_base::ferro_overrides! {
27    impl StyledElementBehaviorImpl for ButtonUploadFileBehavior {
28        fn on_attached_to_visual_tree(this: &Self) {
29            Self::parent_on_attached_to_visual_tree(this);
30
31            if let Some(button) = this.associated_object_as::<Button>() {
32                this.remove_click_handler();
33                let behavior = this.to_ref().downgrade();
34                let token = button.click(move |sender: &Interactive, e: &RoutedEventArgs| {
35                    if let Some(behavior) = behavior.upgrade() {
36                        behavior.on_click(sender, e);
37                    }
38                });
39                *this.click.borrow_mut() = Some((button.downgrade(), token));
40            }
41        }
42
43        fn on_detached_from_visual_tree(this: &Self) {
44            Self::parent_on_detached_from_visual_tree(this);
45
46            this.remove_click_handler();
47        }
48    }
49}
50
51impl ButtonUploadFileBehavior {
52    /// Creates the class data; see [`ferroui_base::FerroObject::construct`].
53    pub fn construct() -> Self {
54        Self { base: UploadFileBehaviorBase::construct(), click: RefCell::new(None) }
55    }
56
57    /// Creates a behavior.
58    pub fn new() -> Ref<Self> {
59        instantiate(Self::construct())
60    }
61
62    fn remove_click_handler(&self) {
63        let click = self.click.borrow_mut().take();
64        if let Some((button, token)) = click {
65            if let Some(button) = button.upgrade() {
66                button.remove_handler(Button::click_event(), token);
67            }
68        }
69    }
70
71    fn on_click(&self, sender: &Interactive, e: &RoutedEventArgs) {
72        let sender: Ref<FerroObject> = sender.to_ref().upcast();
73        let sender: BoxedValue = Rc::new(sender);
74        let parameter: BoxedValue = Rc::new(IRoutedEventArgs::share(e));
75        self.execute(Some(&sender), Some(&parameter));
76    }
77}