ferroui_controls/calendar/
calendar_button.rs1use super::{Calendar, DateTimeHelper};
10use crate::primitives::{TemplateAppliedEventArgs, TemplatedControlImpl};
11use crate::{Button, ButtonImpl, ContentControl, ContentControlImpl, ControlImpl};
12use ferroui_base::input::{
13 InputElementImpl, InputElementImplExt, MouseButton, PointerPressedEventArgs, PointerReleasedEventArgs,
14};
15use ferroui_base::interactivity::InteractiveImpl;
16use ferroui_base::layout::LayoutableImpl;
17use ferroui_base::reactive::{Disposable, IDisposable};
18use ferroui_base::utilities::HandlerList;
19use ferroui_base::{
20 ferro_class, ferro_class_info, ferro_impl_classes, instantiate, BoxedValue, FerroObjectImpl, FerroObjectImplExt,
21 Ref, StyledElementImpl, VisualImpl, WeakRef,
22};
23use std::cell::{Cell, RefCell};
24use std::rc::Rc;
25
26#[repr(C)]
28pub struct CalendarButton {
29 base: Button,
30
31 is_calendar_button_focused: Cell<bool>,
33
34 is_inactive: Cell<bool>,
36
37 is_selected: Cell<bool>,
39
40 owner: RefCell<Option<WeakRef<Calendar>>>,
42
43 calendar_left_mouse_button_down: HandlerList<dyn Fn(&CalendarButton, &PointerPressedEventArgs)>,
44 calendar_left_mouse_button_up: HandlerList<dyn Fn(&CalendarButton, &PointerReleasedEventArgs)>,
45}
46
47ferro_class!(CalendarButton: Button);
48
49ferro_class_info!(CalendarButton {
50 new: CalendarButton::new,
51 markup: {
52 attributes: [PseudoClasses(":selected", ":inactive", ":btnfocused")],
53 },
54});
55
56ferro_impl_classes!(
57 CalendarButton: StyledElementImpl,
58 VisualImpl,
59 LayoutableImpl,
60 InteractiveImpl,
61 ControlImpl,
62 ContentControlImpl,
63 ButtonImpl
64);
65
66impl FerroObjectImpl for CalendarButton {
67 fn constructed(this: &Self) {
68 Self::parent_constructed(this);
69
70 let content: BoxedValue = Rc::new(DateTimeHelper::get_current_date_format().abbreviated_month_names()[0].clone());
71 this.set_current_value(ContentControl::content_property(), Some(content));
72 }
73}
74
75impl InputElementImpl for CalendarButton {
76 fn on_pointer_pressed(this: &Self, e: &PointerPressedEventArgs) {
85 Self::parent_on_pointer_pressed(this, e);
86
87 if e.get_current_point(Some(this)).properties.is_left_button_pressed {
88 for (_, handler) in this.calendar_left_mouse_button_down.snapshot().iter() {
89 handler(this, e);
90 }
91 }
92 }
93
94 fn on_pointer_released(this: &Self, e: &PointerReleasedEventArgs) {
103 Self::parent_on_pointer_released(this, e);
104
105 if e.initial_press_mouse_button() == MouseButton::Left {
106 for (_, handler) in this.calendar_left_mouse_button_up.snapshot().iter() {
107 handler(this, e);
108 }
109 }
110 }
111}
112
113impl TemplatedControlImpl for CalendarButton {
114 fn on_apply_template(this: &Self, _e: &TemplateAppliedEventArgs) {
117 this.set_pseudo_classes();
118 }
119}
120
121impl CalendarButton {
122 pub fn construct() -> Self {
124 Self {
125 base: Button::construct(),
126 is_calendar_button_focused: Cell::new(false),
127 is_inactive: Cell::new(false),
128 is_selected: Cell::new(false),
129 owner: RefCell::new(None),
130 calendar_left_mouse_button_down: HandlerList::new(),
131 calendar_left_mouse_button_up: HandlerList::new(),
132 }
133 }
134
135 pub fn new() -> Ref<Self> {
137 instantiate(Self::construct())
138 }
139
140 #[allow(dead_code)] pub(crate) fn owner(&self) -> Option<Ref<Calendar>> {
143 self.owner.borrow().as_ref().and_then(WeakRef::upgrade)
144 }
145
146 pub(crate) fn set_owner(&self, value: Option<&Ref<Calendar>>) {
148 *self.owner.borrow_mut() = value.map(Ref::downgrade);
149 }
150
151 pub(crate) fn is_calendar_button_focused(&self) -> bool {
153 self.is_calendar_button_focused.get()
154 }
155
156 pub(crate) fn set_is_calendar_button_focused(&self, value: bool) {
158 if self.is_calendar_button_focused.get() != value {
159 self.is_calendar_button_focused.set(value);
160 self.set_pseudo_classes();
161 }
162 }
163
164 pub(crate) fn is_inactive(&self) -> bool {
166 self.is_inactive.get()
167 }
168
169 pub(crate) fn set_is_inactive(&self, value: bool) {
171 if self.is_inactive.get() != value {
172 self.is_inactive.set(value);
173 self.set_pseudo_classes();
174 }
175 }
176
177 pub(crate) fn is_selected(&self) -> bool {
179 self.is_selected.get()
180 }
181
182 pub(crate) fn set_is_selected(&self, value: bool) {
184 if self.is_selected.get() != value {
185 self.is_selected.set(value);
186 self.set_pseudo_classes();
187 }
188 }
189
190 fn set_pseudo_classes(&self) {
192 self.pseudo_classes().set(":selected", self.is_selected());
193 self.pseudo_classes().set(":inactive", self.is_inactive());
194 self.pseudo_classes().set(":btnfocused", self.is_calendar_button_focused() && self.is_enabled());
195 }
196
197 pub fn calendar_left_mouse_button_down(
201 &self,
202 handler: impl Fn(&CalendarButton, &PointerPressedEventArgs) + 'static,
203 ) -> Rc<dyn IDisposable> {
204 let token = self.calendar_left_mouse_button_down.add(Rc::new(handler));
205 let weak = self.to_ref().downgrade();
206 Disposable::create(move || {
207 if let Some(this) = weak.upgrade() {
208 this.calendar_left_mouse_button_down.remove(token);
209 }
210 })
211 }
212
213 pub fn calendar_left_mouse_button_up(
218 &self,
219 handler: impl Fn(&CalendarButton, &PointerReleasedEventArgs) + 'static,
220 ) -> Rc<dyn IDisposable> {
221 let token = self.calendar_left_mouse_button_up.add(Rc::new(handler));
222 let weak = self.to_ref().downgrade();
223 Disposable::create(move || {
224 if let Some(this) = weak.upgrade() {
225 this.calendar_left_mouse_button_up.remove(token);
226 }
227 })
228 }
229}