1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
use std::cell::RefCell; use std::ops::Deref; use std::rc::Rc; use crate::ToggleButton; use fui_core::{EventSubscription, ObservableCollection, StyledControl}; pub trait RadioElement { fn is_checked(&self) -> bool; fn set_is_checked(&mut self, is_checked: bool); fn on_checked(&self, f: Box<dyn Fn()>) -> EventSubscription; } impl RadioElement for StyledControl<ToggleButton> { fn is_checked(&self) -> bool { self.data.is_checked.get() } fn set_is_checked(&mut self, is_checked: bool) { self.data.is_checked.set(is_checked) } fn on_checked(&self, f: Box<dyn Fn()>) -> EventSubscription { self.data.is_checked.on_changed(move |is_checked| { if is_checked { f(); } }) } } pub struct RadioController<R> where R: 'static + RadioElement, { elements: Rc<RefCell<dyn ObservableCollection<Rc<RefCell<R>>>>>, subscriptions: Rc<RefCell<Vec<EventSubscription>>>, } impl<R> RadioController<R> where R: 'static + RadioElement, { pub fn new<E>(elements: E) -> Self where E: 'static + ObservableCollection<Rc<RefCell<R>>>, { let mut subscriptions = Vec::new(); let elements: Rc<RefCell<dyn ObservableCollection<Rc<RefCell<R>>>>> = Rc::new(RefCell::new(elements)); for radio_element in elements.borrow_mut().deref() { let elements_clone = elements.clone(); let radio_element_clone = radio_element.clone(); subscriptions.push(radio_element.borrow().on_checked(Box::new(move || { for el in elements_clone.borrow_mut().deref() { if !Rc::ptr_eq(&el, &radio_element_clone) { el.borrow_mut().set_is_checked(false); } } }))); } let is_checked = elements .borrow_mut() .into_iter() .fold(false, |acc, el| acc || el.borrow().is_checked()); if !is_checked { if let Some(el) = elements.borrow_mut().into_iter().next() { el.borrow_mut().set_is_checked(true); } } let subscriptions = Rc::new(RefCell::new(subscriptions)); let subscriptions_clone = subscriptions.clone(); let elements_clone = elements.clone(); elements .borrow_mut() .on_changed(Box::new(move |args| match args { fui_core::ObservableChangedEventArgs::Insert { index, value: radio_element, } => { if elements_clone.borrow().len() == 0 { radio_element.borrow_mut().set_is_checked(true); } let elements_clone = elements_clone.clone(); let radio_element_clone = radio_element.clone(); let subscription = radio_element.borrow().on_checked(Box::new(move || { for el in elements_clone.borrow_mut().deref() { if !Rc::ptr_eq(&el, &radio_element_clone) { el.borrow_mut().set_is_checked(false); } } })); subscriptions_clone.borrow_mut().insert(index, subscription); } fui_core::ObservableChangedEventArgs::Remove { index } => { subscriptions_clone.borrow_mut().remove(index); } })); RadioController { elements, subscriptions, } } }