Skip to main content

ferroui_controls/
list_box_item.rs

1use crate::i_selectable::{register_selectable, ISelectable};
2use crate::metadata::PseudoClassesAttribute;
3use crate::mixins::{PressedMixin, SelectableMixin};
4use crate::primitives::{SelectingItemsControl, TemplatedControlImpl};
5use crate::{ContentControl, ContentControlImpl, ControlImpl};
6use ferroui_base::input::{
7    InputElement, InputElementImpl, InputElementImplExt, KeyEventArgs, PointerPressedEventArgs,
8    PointerReleasedEventArgs,
9};
10use ferroui_base::interactivity::{IRoutedEventArgs, InteractiveImpl};
11use ferroui_base::layout::LayoutableImpl;
12use ferroui_base::{
13    ferro_class, ferro_impl_classes, ferro_property, instantiate, FerroObjectImpl, Ref,
14    StyledElementImpl, StyledProperty, VisualImpl,
15};
16
17/// A selectable item in a `ListBox`.
18#[repr(C)]
19pub struct ListBoxItem {
20    base: ContentControl,
21}
22
23ferro_class!(ListBoxItem: ContentControl);
24ferroui_base::ferro_class_info!(ListBoxItem { new: ListBoxItem::new });
25ferro_impl_classes!(
26    ListBoxItem: StyledElementImpl,
27    VisualImpl,
28    LayoutableImpl,
29    InteractiveImpl,
30    TemplatedControlImpl,
31    ContentControlImpl
32);
33
34ferroui_base::ferro_impl_classes!(ListBoxItem: FerroObjectImpl);
35
36impl InputElementImpl for ListBoxItem {
37    fn on_pointer_pressed(this: &Self, e: &PointerPressedEventArgs) {
38        Self::parent_on_pointer_pressed(this, e);
39        this.update_selection_from_event(e);
40    }
41
42    fn on_pointer_released(this: &Self, e: &PointerReleasedEventArgs) {
43        Self::parent_on_pointer_released(this, e);
44        this.update_selection_from_event(e);
45    }
46
47    fn on_key_down(this: &Self, e: &KeyEventArgs) {
48        Self::parent_on_key_down(this, e);
49        this.update_selection_from_event(e);
50    }
51}
52
53impl ControlImpl for ListBoxItem {
54    fn on_create_automation_peer(this: &Self) -> Ref<crate::automation::peers::AutomationPeer> {
55        crate::automation::peers::ListItemAutomationPeer::new(this).upcast()
56    }
57}
58
59impl ISelectable for ListBoxItem {
60    fn is_selected(&self) -> bool {
61        ListBoxItem::is_selected(self)
62    }
63
64    fn set_is_selected(&self, value: bool) {
65        ListBoxItem::set_is_selected(self, value)
66    }
67}
68
69impl ListBoxItem {
70    /// The pseudoclasses set by the class.
71    pub const PSEUDO_CLASSES: PseudoClassesAttribute = PseudoClassesAttribute::new(&[":pressed", ":selected"]);
72}
73
74ferroui_base::ferro_properties! { impl ListBoxItem {
75    ferro_property!(
76        /// Defines the `IsSelected` property.
77        pub fn is_selected_property() -> StyledProperty<bool> {
78            SelectingItemsControl::is_selected_property().add_owner::<ListBoxItem>()
79        }
80    );
81} }
82
83impl ListBoxItem {
84    pub(crate) fn static_constructor() {
85        register_selectable::<ListBoxItem>();
86        SelectableMixin::attach::<ListBoxItem>(Self::is_selected_property());
87        PressedMixin::attach::<ListBoxItem>();
88        InputElement::focusable_property().override_default_value::<ListBoxItem>(true);
89        crate::automation::AutomationProperties::is_offscreen_behavior_property()
90            .override_default_value::<ListBoxItem>(crate::automation::IsOffscreenBehavior::FromClip);
91        crate::platform::PlatformFeedback::feedback_type_property()
92            .override_default_value::<ListBoxItem>(crate::platform::FeedbackType::Auto);
93    }
94
95    /// Creates the class data; see [`ferroui_base::FerroObject::construct`].
96    pub fn construct() -> Self {
97        Self { base: ContentControl::construct() }
98    }
99
100    pub fn new() -> Ref<Self> {
101        instantiate(Self::construct())
102    }
103
104    /// Gets or sets the selection state of the item.
105    pub fn is_selected(&self) -> bool {
106        self.get_value(Self::is_selected_property())
107    }
108
109    pub fn set_is_selected(&self, value: bool) {
110        self.set_value(Self::is_selected_property(), value)
111    }
112
113    /// Updates the selection of the owning selecting items control from an
114    /// event raised on this container.
115    pub fn update_selection_from_event(&self, e: &dyn IRoutedEventArgs) -> bool {
116        let this = self.to_ref().upcast();
117        match SelectingItemsControl::selecting_items_control_from_item_container(&this) {
118            Some(owner) => owner.update_selection_from_event(&this, e),
119            None => false,
120        }
121    }
122}