ferroui_controls/primitives/
tab_strip.rs1use super::{
2 SelectingItemsControl, SelectingItemsControlImpl, SelectingItemsControlImplExt, TabStripItem, TemplatedControlImpl,
3};
4use crate::generators::RecycleKey;
5use crate::templates::{FuncTemplate, ITemplateOf};
6use crate::{Control, ControlImpl, ItemsControl, ItemsControlImpl, Panel, SelectionMode, WrapPanel};
7use ferroui_base::input::{
8 FocusChangedEventArgs, InputElement, InputElementImpl, NavigationMethod, PointerEventArgs, PointerUpdateKind,
9};
10use ferroui_base::interactivity::{IRoutedEventArgs, InteractiveImpl};
11use ferroui_base::layout::{LayoutableImpl, Orientation};
12use ferroui_base::{
13 ferro_class, ferro_impl_classes, instantiate, BoxedValue, FerroObjectImpl, Ref,
14 StyledElementImpl, Visual, VisualImpl,
15};
16use std::rc::Rc;
17
18#[repr(C)]
21pub struct TabStrip {
22 base: SelectingItemsControl,
23}
24
25ferro_class!(TabStrip: SelectingItemsControl);
26ferroui_base::ferro_class_info!(TabStrip { new: TabStrip::new });
27ferro_impl_classes!(
28 TabStrip: StyledElementImpl,
29 VisualImpl,
30 LayoutableImpl,
31 InteractiveImpl,
32 InputElementImpl,
33 ControlImpl,
34 TemplatedControlImpl
35);
36
37ferroui_base::ferro_impl_classes!(TabStrip: FerroObjectImpl);
38
39impl ItemsControlImpl for TabStrip {
40 fn create_container_for_item_override(
41 _this: &Self,
42 _item: &Option<BoxedValue>,
43 _index: i32,
44 _recycle_key: Option<RecycleKey>,
45 ) -> Ref<Control> {
46 TabStripItem::new().upcast()
47 }
48
49 fn needs_container_override(this: &Self, item: &Option<BoxedValue>, _index: i32) -> (bool, Option<RecycleKey>) {
50 this.needs_container::<TabStripItem>(item)
51 }
52}
53
54impl SelectingItemsControlImpl for TabStrip {
55 fn should_trigger_selection(this: &Self, selectable: &Visual, e: &PointerEventArgs) -> bool {
56 matches!(
57 e.properties().pointer_update_kind,
58 PointerUpdateKind::LeftButtonPressed | PointerUpdateKind::LeftButtonReleased
59 ) && Self::parent_should_trigger_selection(this, selectable, e)
60 }
61
62 fn update_selection_from_event(this: &Self, container: &Ref<Control>, event_args: &dyn IRoutedEventArgs) -> bool {
63 if let Some(focus) = event_args.downcast_ref::<FocusChangedEventArgs>() {
64 if focus.navigation_method != NavigationMethod::Directional {
65 return false;
66 }
67 }
68
69 Self::parent_update_selection_from_event(this, container, event_args)
70 }
71}
72
73impl TabStrip {
74 fn static_constructor() {
75 let default_panel: Rc<dyn ITemplateOf<Option<Ref<Panel>>>> = FuncTemplate::new(|| {
77 let panel = WrapPanel::new();
78 panel.set_orientation(Orientation::Horizontal);
79 Some(panel.upcast::<Panel>())
80 });
81
82 SelectingItemsControl::selection_mode_property()
83 .override_default_value::<TabStrip>(SelectionMode::ALWAYS_SELECTED);
84 InputElement::focusable_property().override_default_value::<TabStrip>(false);
85 ItemsControl::items_panel_property().override_default_value::<TabStrip>(default_panel);
86 }
87
88 pub fn construct() -> Self {
90 Self { base: SelectingItemsControl::construct() }
91 }
92
93 pub fn new() -> Ref<Self> {
94 instantiate(Self::construct())
95 }
96}