Skip to main content

ferroui_controls/automation/peers/
toggle_button_automation_peer.rs

1use super::{
2    AutomationControlType, AutomationPeer, AutomationPeerImpl, ContentControlAutomationPeer, ControlAutomationPeer,
3    ControlAutomationPeerImpl,
4};
5use crate::automation::provider::{IToggleProvider, ProviderAdapter, ToggleState};
6use crate::automation::{ElementNotEnabledException, TogglePatternIdentifiers};
7use crate::primitives::ToggleButton;
8use ferroui_base::{ferro_class, instantiate, BoxedValue, FerroObjectImpl, FerroObjectImplExt, Ref};
9use std::rc::Rc;
10
11/// An automation peer which represents a [`ToggleButton`].
12#[repr(C)]
13pub struct ToggleButtonAutomationPeer {
14    base: ContentControlAutomationPeer,
15}
16
17ferro_class!(ToggleButtonAutomationPeer: ContentControlAutomationPeer);
18ferroui_base::ferro_class_info!(ToggleButtonAutomationPeer { interfaces: [Rc<dyn IToggleProvider> => ProviderAdapter::as_toggle_provider] });
19
20impl FerroObjectImpl for ToggleButtonAutomationPeer {
21    fn constructed(this: &Self) {
22        Self::parent_constructed(this);
23
24        let weak = this.to_ref().downgrade();
25        this.owner().property_changed(move |e| {
26            if e.property() == ToggleButton::is_checked_property().as_property() {
27                let Some(this) = weak.upgrade() else { return };
28                let (old_value, new_value) = e.get_old_and_new_value::<Option<bool>>();
29                this.raise_property_changed_event(
30                    TogglePatternIdentifiers::toggle_state_property(),
31                    Some(Rc::new(Self::to_state(old_value)) as BoxedValue),
32                    Some(Rc::new(Self::to_state(new_value)) as BoxedValue),
33                );
34            }
35        });
36    }
37}
38
39impl ControlAutomationPeerImpl for ToggleButtonAutomationPeer {}
40
41impl AutomationPeerImpl for ToggleButtonAutomationPeer {
42    fn get_automation_control_type_core(_this: &Self) -> AutomationControlType {
43        AutomationControlType::Button
44    }
45
46    fn is_content_element_core(_this: &Self) -> bool {
47        true
48    }
49
50    fn is_control_element_core(_this: &Self) -> bool {
51        true
52    }
53}
54
55impl IToggleProvider for ProviderAdapter<ToggleButtonAutomationPeer> {
56    fn peer(&self) -> Ref<AutomationPeer> {
57        self.0.clone().upcast()
58    }
59
60    fn toggle_state(&self) -> ToggleState {
61        self.0.toggle_state()
62    }
63
64    fn toggle(&self) -> Result<(), ElementNotEnabledException> {
65        self.0.toggle()
66    }
67}
68
69impl ToggleButtonAutomationPeer {
70    /// Creates the class data; see [`ferroui_base::FerroObject::construct`].
71    pub fn construct(owner: &ToggleButton) -> Self {
72        Self { base: ContentControlAutomationPeer::construct(owner) }
73    }
74
75    /// Initializes a new peer of `owner`.
76    pub fn new(owner: &ToggleButton) -> Ref<Self> {
77        instantiate(Self::construct(owner))
78    }
79
80    /// Gets the owning toggle button.
81    pub fn owner(&self) -> Ref<ToggleButton> {
82        ControlAutomationPeer::owner(self).cast().expect("The owner of the peer is a toggle button.")
83    }
84
85    fn to_state(value: Option<bool>) -> ToggleState {
86        match value {
87            Some(true) => ToggleState::On,
88            Some(false) => ToggleState::Off,
89            None => ToggleState::Indeterminate,
90        }
91    }
92
93    /// The toggle state of the button (the toggle provider contract).
94    pub fn toggle_state(&self) -> ToggleState {
95        Self::to_state(self.owner().is_checked())
96    }
97
98    /// Cycles through the toggle states of the button (the toggle provider
99    /// contract).
100    pub fn toggle(&self) -> Result<(), ElementNotEnabledException> {
101        self.ensure_enabled()?;
102        self.owner().perform_click();
103        Ok(())
104    }
105}