1use std::convert::TryFrom;
20use std::sync::{Arc, LazyLock, RwLock};
21use key_vec::KeyVec;
22use log;
23use derive_more::{From, TryInto};
24
25use crate::prelude::*;
26
27pub mod controller;
28pub mod model;
29pub mod view;
30pub use self::controller::Controller;
31pub use self::model::Model;
32pub use self::view::View;
33
34pub static POINTER : LazyLock <Arc <RwLock <input::Pointer>>> = LazyLock::new (||
36 Arc::new (RwLock::new (input::Pointer::default())));
37
38#[derive(Debug)]
40pub struct Interface <A=application::Default, P=presentation::Headless> where
41 A : Application,
42 P : Presentation
43{
44 pub presentation : P,
45 elements : Tree <Element>,
46 focused_id : NodeId,
47 input_buffer : Option <Vec <Input>>,
48 action_buffer : Option <Vec <(NodeId, Action)>>,
49 display_buffer : Vec <(NodeId, Display)>,
50 event_buffer : Vec <(NodeId, Event)>,
51 _phantom : std::marker::PhantomData <A>
52}
53
54#[derive(Clone, Debug)]
60pub struct Element {
61 pub name : String,
62 pub controller : Controller,
63 pub model : Model,
64 pub view : View
65}
66
67#[derive(From, TryInto)]
69pub enum Action {
70 Create (Tree <Element>, CreateOrder),
71 ModifyController (Box <dyn FnOnce (&mut Controller)>),
72 ModifyModel (Box <dyn FnOnce (&mut Model)>),
73 ModifyView (Box <dyn FnOnce (&mut View)>),
74 SubmitCallback (application::CallbackId),
80 Focus,
86 Enable,
89 Disable,
92 Destroy,
98 ReleaseButtons
103}
104
105#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
107pub enum CreateOrder {
108 #[default]
109 Append,
110 Prepend,
111 NthSibling (u32)
112}
113
114impl <A, P> Interface <A, P> where
115 A : Application,
116 P : Presentation
117{
118 pub fn with_root (mut root : Element) -> Self {
119 log::trace!("with_root...");
120 root.focus();
121 let elements = TreeBuilder::new().with_root (Node::new (root.clone())).build();
122 let focused_id = elements.root_node_id().unwrap().clone();
123 let presentation = P::with_root (root.view, focused_id.clone());
124 let input_buffer = Some (vec![]);
125 let action_buffer = Some (vec![]);
126 let display_buffer = vec![];
127 let event_buffer = vec![];
128 log::trace!("...with_root");
129 Interface {
130 elements, focused_id, presentation, input_buffer, display_buffer, action_buffer,
131 event_buffer, _phantom: std::marker::PhantomData
132 }
133 }
134
135 #[inline]
139 #[must_use]
140 #[expect(mismatched_lifetime_syntaxes)]
141 pub fn action (&mut self, node_id : &NodeId, action : Action)
142 -> std::vec::Drain <(NodeId, Event)>
143 {
144 self.handle_action (action, node_id);
145 self.event_buffer.drain(..)
146 }
147
148 #[inline]
152 #[must_use]
153 #[expect(mismatched_lifetime_syntaxes)]
154 pub fn actions (&mut self, actions : Vec <(NodeId, Action)>)
155 -> std::vec::Drain <(NodeId, Event)>
156 {
157 for (node_id, action) in actions.into_iter() {
158 self.handle_action (action, &node_id);
159 }
160 self.event_buffer.drain(..)
161 }
162
163 #[must_use]
165 #[expect(mismatched_lifetime_syntaxes)]
166 pub fn update (&mut self) -> std::vec::Drain <(NodeId, Event)> {
167 log::trace!("update...");
168 let mut action_buffer = self.action_buffer.take().unwrap();
170 let mut input_buffer = self.input_buffer.take().unwrap();
171 debug_assert!(action_buffer.is_empty());
172 debug_assert!(input_buffer.is_empty());
173 self.presentation.get_input (&mut input_buffer);
174 #[expect(clippy::iter_with_drain)]
175 for input in input_buffer.drain(..) {
176 log::trace!("input: {input:?}");
177 if let Input::Pointer (pointer) = &input {
179 *POINTER.write().unwrap() = pointer.clone()
180 }
181 let focused_id = self.focused_element_id().clone();
182 let focused = self.focused_element();
183 let button_release = match focused.controller.handle_input::<A> (
185 input, &self.elements, &focused_id, &mut action_buffer
186 ) {
187 Ok (result) => result,
188 Err (mut input) => {
189 debug_assert!(action_buffer.is_empty());
191 let mut button_release = None;
192 let input_mask = (&input).into();
193 if !focused.controller.bubble_trap.intersects (input_mask) {
194 for ancestor_id in self.elements.ancestor_ids (&focused_id).unwrap() {
195 let ancestor = self.get_element (ancestor_id);
196 input = match ancestor.controller.handle_input::<A> (
197 input, &self.elements, ancestor_id, &mut action_buffer
198 ) {
199 Err (input) =>
200 if ancestor.controller.bubble_trap.intersects (input_mask) {
201 break
202 } else {
203 input
204 }
205 Ok (result) => {
206 button_release = result;
207 break
208 }
209 };
210 }
211 }
212 button_release
213 }
214 };
215 for (node_id, action) in action_buffer.drain(..) {
217 self.handle_action (action, &node_id);
218 }
219 if let Some (button_release) = button_release {
224 match button_release {
225 ButtonRelease::Insert (input, controls) =>
226 for (control, node_id) in controls {
227 let element = self.get_element_mut (&node_id);
228 element.controller.release_button_insert (input, control);
229 }
230 ButtonRelease::Remove (input, node_id) => {
231 let element = self.get_element_mut (&node_id);
232 element.controller.release_button_remove (input);
233 }
234 }
235 }
236 }
237 debug_assert!(action_buffer.is_empty());
238 debug_assert!(input_buffer.is_empty());
239 self.action_buffer = Some (action_buffer);
240 self.input_buffer = Some (input_buffer);
241
242 log::trace!("...update");
243 self.event_buffer.drain(..)
245 }
246
247 #[inline]
249 pub fn display (&mut self) {
250 log::trace!("display...");
251 self.presentation.display_view (&self.elements, self.display_buffer.drain(..));
252 log::trace!("...display");
253 }
254
255 #[inline]
256 pub const fn elements (&self) -> &Tree <Element> {
257 &self.elements
258 }
259
260 #[inline]
261 pub fn root (&self) -> &Element {
262 self.root_node().data()
263 }
264
265 pub fn root_node (&self) -> &Node <Element> {
266 self.elements.get (self.root_id()).unwrap()
267 }
268
269 #[inline]
270 pub fn root_id (&self) -> &NodeId {
271 self.elements.root_node_id().unwrap()
272 }
273
274 #[inline]
275 pub fn get_element (&self, node_id : &NodeId) -> &Element {
276 self.elements.get_element (node_id)
277 }
278
279 #[inline]
280 pub fn get_element_mut (&mut self, node_id : &NodeId) -> &mut Element {
281 self.elements.get_element_mut (node_id)
282 }
283
284 #[inline]
285 pub const fn focused_element_id (&self) -> &NodeId {
286 &self.focused_id
287 }
288
289 #[inline]
290 pub fn focused_element (&self) -> &Element {
291 self.get_element (&self.focused_id)
292 }
293
294 #[inline]
295 pub fn focused_element_mut (&mut self) -> &mut Element {
296 let focused_id = self.focused_id.clone();
297 self.get_element_mut (&focused_id)
298 }
299
300 #[inline]
301 pub fn print_elements_tree (&self) {
302 let mut s = String::new();
303 self.elements.write_formatted (&mut s).unwrap();
304 println!("elements:\n{s}");
305 }
306
307 #[inline]
308 pub fn print_elements_tree_names (&self) {
309 let mut s = String::new();
310 self.elements.write_formatted_names (&mut s).unwrap();
311 println!("elements:\n{s}");
312 }
313
314 pub fn keyboard_map (&self)
316 -> KeyVec <input::Button, Option <controls::button::Control <A::ButtonControls>>>
317 {
318 use strum::IntoEnumIterator;
319 let mut out = KeyVec::new();
320 let focused = self.focused_element();
321 let focused_id = self.focused_element_id();
322 for modifier_bits in 0..16u8 {
323 let modifiers = input::Modifiers::from_bits (modifier_bits).unwrap();
324 'keycodes: for keycode in input::button::Keycode::iter() {
325 let input = input::Button::from (keycode).with_modifiers (modifiers);
326 if let Ok (index) = focused.controller.input_map.buttons
327 .binary_search_by_key (&&input, |(b, _)| b)
328 {
329 let (b, control) = &focused.controller.input_map.buttons[index];
333 if b.modifiers.contains (input::Modifiers::ANY) {
334 }
336 out.insert (input, Some ((*control).into()));
337 } else {
338 let input_mask = (&Input::Button (input, input::button::State::Pressed)).into();
339 if !focused.controller.bubble_trap.intersects (input_mask) {
340 for ancestor_id in self.elements.ancestor_ids (focused_id).unwrap() {
341 let ancestor = self.get_element (ancestor_id);
342 if let Ok(index) = ancestor.controller.input_map.buttons
343 .binary_search_by_key (&&input, |(b, _)| b)
344 {
345 let (b, control) = &ancestor.controller.input_map.buttons[index];
346 if b.modifiers.contains (input::Modifiers::ANY) {
347 }
349 out.insert (input, Some ((*control).into()));
350 continue 'keycodes
351 }
352 }
353 }
354 out.insert (input, None);
355 }
356 }
357 }
358 out
359 }
360
361 pub fn create_singleton (&mut self,
363 parent_id : &NodeId,
364 element : Element,
365 order : CreateOrder
366 ) -> NodeId {
367 match self.action (parent_id, Action::create_singleton (element, order))
368 .next().unwrap()
369 {
370 (_, Event::Create (_, new_id, _)) => new_id,
371 _ => unreachable!()
372 }
373 }
374
375 fn handle_action (&mut self, action : Action, node_id : &NodeId) {
376 use controller::component::{Kind, Selection};
377 log::trace!("handle_action...");
378 log::trace!("action: {action:?}");
379 match action {
380 Action::Create (elements, order) => {
381 #[cfg(debug_assertions)]
382 for element in elements.traverse_level_order (elements.root_node_id().unwrap())
383 .unwrap()
384 {
385 debug_assert_eq!(&element.data().view.appearance,
387 element.data().controller.get_appearance());
388 }
389 self.splice_subtree (
390 &elements, elements.root_node_id().unwrap(), node_id, order);
391 }
392 Action::ModifyController (f) => {
393 let controller = &mut self.get_element_mut (node_id).controller;
394 f (controller);
395 }
396 Action::ModifyModel (f) => {
397 let model = {
398 let model = &mut self.get_element_mut (node_id).model;
399 f (model);
400 model.clone()
401 };
402 self.event_buffer.push ((node_id.clone(), Event::Update (model)));
403 }
404 Action::ModifyView (f) => {
405 let view = {
406 let view = &mut self.get_element_mut (node_id).view;
407 f (view);
408 view.clone()
410 };
411 self.display_buffer.push ((node_id.clone(), Display::Update (view.into())));
412 }
413 Action::SubmitCallback (callback_id) => {
414 let callback_id = Some (callback_id);
415 let model = Model {
416 callback_id, .. self.get_element (node_id).model.clone()
417 };
418 self.event_buffer.push ((node_id.clone(), Event::Submit (model)));
419 }
420 Action::Focus => {
421 let mut focus_id = Some (node_id.clone());
422 while let Some (id) = focus_id {
423 focus_id = self.change_focus (&id);
424 if self.get_element (&id).controller.focus_top {
426 self.elements.make_last_sibling (&id).unwrap();
427 self.display_buffer.push ((id.clone(), Display::Update (Update::FocusTop)));
428 }
429 let ancestor_ids = self.elements.ancestor_ids (&id).unwrap().cloned()
430 .collect::<Vec <_>>();
431 for ancestor_id in ancestor_ids {
432 if self.get_element (&ancestor_id).controller.focus_top {
433 self.elements.make_last_sibling (&ancestor_id).unwrap();
434 self.display_buffer
435 .push ((ancestor_id.clone(), Display::Update (Update::FocusTop)));
436 }
437 }
438 }
439 }
440 Action::Enable => {
441 let view = {
442 let element = self.get_element_mut (node_id);
443 element.controller.state.enable();
444 element.view.appearance = element.controller.get_appearance().clone();
445 element.view.clone()
446 };
447 self.display_buffer.push ((node_id.clone(), Display::Update (view.into())));
448 }
449 Action::Disable => {
450 let view = {
451 let element = self.get_element_mut (node_id);
452 element.controller.state.disable();
453 element.view.appearance = element.controller.get_appearance().clone();
454 element.view.clone()
455 };
456 self.display_buffer.push ((node_id.clone(), Display::Update (view.into())));
457 }
458 Action::Destroy => {
459 let parent_id = self.elements.get_parent_id (node_id).clone();
460 let focused = self.elements.get_element (node_id).controller.state
461 == State::Focused;
462 { let mut children_ids = self.elements.children_ids (&parent_id).unwrap();
464 let first_sibling_id = children_ids.next().unwrap().clone();
467 let first_sibling = self.elements.get_element (&first_sibling_id);
468 if let Ok (Widget (selection, _, _)) = Menu::try_from (first_sibling)
469 && selection.current.as_ref() == Some (node_id)
470 {
471 let mut select = None;
472 for sibling_id in children_ids {
473 if sibling_id == node_id {
474 continue
475 }
476 let sibling = self.elements.get_element (sibling_id);
477 if sibling.controller.state == State::Enabled
478 && Frame::try_from (sibling).is_ok()
479 {
480 select = Some (sibling_id.clone());
481 break
482 }
483 }
484 let deselect = Box::new (move |controller : &mut Controller|{
485 let selection = Selection::try_ref_mut (&mut controller.component)
486 .unwrap();
487 selection.current = select;
488 });
489 self.handle_action (Action::ModifyController (deselect), &first_sibling_id);
490 }
491 }
492 if focused {
493 let mut focus_id = Some (parent_id);
494 while let Some (id) = focus_id {
495 focus_id = self.change_focus (&id);
496 }
497 }
498 for node_id in self.elements.traverse_post_order_ids (node_id).unwrap() {
499 self.event_buffer.push ((node_id.clone(), Event::Destroy));
500 self.display_buffer.push ((node_id, Display::Destroy));
501 }
502 let _ = self.elements
503 .remove_node (node_id.clone(), tree::RemoveBehavior::DropChildren).unwrap();
504 }
505 Action::ReleaseButtons => {
506 use controller::controls::Control;
507 let release_buttons =
508 self.elements.get_element_mut (node_id).controller.release_buttons();
509 for control in release_buttons {
510 control.fun::<A::ButtonControls>().0 (
511 &None, &self.elements, node_id, self.action_buffer.as_mut().unwrap());
512 }
513 let mut action_buffer = self.action_buffer.take().unwrap();
514 #[expect(clippy::iter_with_drain)]
515 for (node_id, action) in action_buffer.drain(..) {
516 self.handle_action (action, &node_id);
517 }
518 self.action_buffer = Some (action_buffer);
519 }
520 }
521 log::trace!("...handle_action");
522 }
523
524 fn insert_child (&mut self,
526 parent_id : &NodeId,
527 child : Node <Element>,
528 order : CreateOrder
529 ) -> NodeId {
530 let child_model = child.data().model.clone();
531 let child_view = child.data().view.clone();
532 let child_id = self.elements.insert (
533 child, tree::InsertBehavior::UnderNode (parent_id)).unwrap();
534 match order {
535 CreateOrder::Append => {}
536 CreateOrder::Prepend => {
537 let _ = self.elements.make_first_sibling (&child_id).unwrap();
538 }
539 CreateOrder::NthSibling (n) =>
540 self.elements.make_nth_sibling (&child_id, n as usize).unwrap()
541 }
542 self.event_buffer.push ((parent_id.clone(),
543 Event::Create (child_model, child_id.clone(), order)));
544 self.display_buffer.push ((parent_id.clone(),
545 Display::Create (child_view, child_id.clone(), order)));
546 child_id
547 }
548
549 fn change_focus (&mut self, target_id : &NodeId) -> Option <NodeId> {
553 use controller::component::{Kind, Selection};
554 log::trace!("change_focus...");
555 let focused_id = self.focused_element_id().clone();
556 let focused_ancestors = self.elements.ancestor_ids (&focused_id).unwrap().cloned()
557 .collect::<Vec <NodeId>>();
558 let target_ancestors = self.elements.ancestor_ids (target_id).unwrap().cloned()
559 .collect::<Vec <NodeId>>();
560 let maybe_common_ancestor_id = focused_ancestors.iter().rev()
561 .zip (target_ancestors.iter().rev())
562 .filter_map (|(a, b)|
563 if a == b {
564 Some (a)
565 } else {
566 None
567 })
568 .cloned().enumerate().last();
569 let focused_ancestor_of_target = target_ancestors.contains (&focused_id);
570 let target_ancestor_of_focused = focused_ancestors.contains (target_id);
571 { let mut defocus = |defocus_id| {
573 let view = {
574 let mut actions = vec![];
576 let focused_node = self.elements.get (&defocus_id).unwrap();
577 if let Some (sub_child_id) = focused_node.children().first()
580 && let Ok (Widget (switch, _, _)) =
581 Button::try_get (&self.elements, sub_child_id)
582 && switch.state == switch::State::On && !switch.toggle
583 {
584 button::release (&None, &self.elements, &defocus_id, &mut actions);
585 }
586 for (node_id, action) in actions.into_iter() {
587 self.handle_action (action, &node_id);
588 }
589 let focused = self.elements.get_mut (&defocus_id).unwrap().data_mut();
590 focused.defocus();
591 let view = focused.view.clone();
592 focused.view.appearance.sound = None; view
594 };
595 self.display_buffer .push ((defocus_id, Display::Update (view.into())));
596 };
597 if !focused_ancestor_of_target {
599 defocus (focused_id);
600 }
601 if let Some ((_, common_ancestor_id)) = maybe_common_ancestor_id.as_ref() {
602 for ancestor_id in focused_ancestors.into_iter()
603 .take_while (|id| id != common_ancestor_id && id != target_id)
604 {
605 defocus (ancestor_id);
606 }
607 }
608 }
609 let refocus_id = {
610 let mut focus = |focus_id| {
612 if Frame::try_from (self.get_element (&focus_id)).is_ok() {
614 let parent_id = self.elements.get_parent_id (&focus_id);
616 let first_sibling_id =
617 self.elements.children_ids (parent_id).unwrap().next().unwrap().clone();
618 if first_sibling_id != focus_id {
619 let first_sibling = self.elements.get_element (&first_sibling_id);
620 if let Ok (Widget (selection, _, _)) = Menu::try_from (first_sibling)
621 && selection.current.as_ref() != Some (&focus_id)
622 {
623 let select_id = focus_id.clone();
624 let select = Box::new (move |controller : &mut Controller|{
625 let selection = Selection::try_ref_mut (&mut controller.component)
626 .unwrap();
627 selection.current = Some (select_id.clone());
628 });
629 self.handle_action (Action::ModifyController (select), &first_sibling_id);
630 }
631 }
632 }
633 let focus = self.get_element_mut (&focus_id);
634 focus.focus();
635 let view = focus.view.clone();
636 focus.view.appearance.sound = None; self.display_buffer.push ((focus_id.clone(), Display::Update (view.into())));
638 };
639 let depth = if let Some ((depth, _)) = maybe_common_ancestor_id {
640 depth + 1 + usize::from (focused_ancestor_of_target)
641 } else {
642 1
643 };
644 for ancestor_id in target_ancestors.into_iter().rev().skip (depth) {
645 focus (ancestor_id);
646 }
647 if !target_ancestor_of_focused {
650 focus (target_id.clone());
651 }
652 refocus (target_id, self.elements())
654 };
655 self.focused_id = target_id.clone();
656 log::trace!("...change_focus");
657 refocus_id
658 }
659
660 fn splice_subtree (&mut self,
663 other : &Tree <Element>,
664 other_id : &NodeId,
665 parent_id : &NodeId,
666 order : CreateOrder
667 ) -> NodeId {
668 let subtree_root = Node::new (other.get (other_id).unwrap().data().clone());
670 let subtree_id = self.insert_child (parent_id, subtree_root, order);
671 for child_id in other.children_ids (other_id).unwrap() {
672 self.splice_subtree (other, child_id, &subtree_id, CreateOrder::Append);
673 }
674 subtree_id
675 }
676
677 pub (crate) fn swap_presentation <P2 : Presentation> (self, f : impl FnOnce (P) -> P2)
682 -> Interface <A, P2>
683 {
684 let Interface {
685 elements, focused_id, presentation, input_buffer, display_buffer, action_buffer,
686 event_buffer, _phantom
687 } = self;
688 #[expect(clippy::used_underscore_binding)]
689 Interface {
690 presentation: f (presentation),
691 elements, focused_id, input_buffer, display_buffer, action_buffer, event_buffer,
692 _phantom
693 }
694 }
695}
696
697pub macro log_elements_tree ($interface:expr$(, $level:expr)?) {
702 let mut s = String::new();
703 $interface.elements.write_formatted (&mut s).unwrap();
704 $crate::interface::log_elements_string!(s$(, $level)?);
705}
706
707pub macro log_elements_tree_names ($interface:expr$(, $level:expr)?) {
712 let mut s = String::new();
713 $interface.elements.write_formatted_names (&mut s).unwrap();
714 $crate::interface::log_elements_string!(s$(, $level)?);
715}
716
717#[expect(unused_macros)]
718macro log_elements_string {
719 ($string:expr) => {
720 $crate::interface::log_elements_string!($string, $crate::log::Level::Debug);
721 },
722 ($string:expr, $level:expr) => {
723 $crate::log::log!($level, "elements:\n{}", $string);
724 }
725}
726
727impl Element {
728 pub fn new (name : String, controller : Controller, model : Model, mut view : View)
731 -> Self
732 {
733 view.appearance = controller.get_appearance().clone();
734 Element { name, controller, view, model }
735 }
736 pub fn focus (&mut self) {
737 self.controller.state.focus();
738 self.controller.update_view_focus (&mut self.view);
739 }
740 pub fn defocus (&mut self) {
741 self.controller.state.defocus();
742 self.controller.update_view_focus (&mut self.view);
743 }
744 pub fn disable (&mut self) {
745 self.controller.state.disable();
746 self.controller.update_view_focus (&mut self.view);
747 }
748}
749
750impl Default for Element {
751 fn default() -> Self {
752 Element::new (
753 "".to_string(), Controller::default(), Model::default(), View::default())
754 }
755}
756
757impl AsRef <Controller> for Element {
758 fn as_ref (&self) -> &Controller {
759 &self.controller
760 }
761}
762
763impl AsRef <Model> for Element {
764 fn as_ref (&self) -> &Model {
765 &self.model
766 }
767}
768
769impl AsRef <View> for Element {
770 fn as_ref (&self) -> &View {
771 &self.view
772 }
773}
774
775impl Action {
776 #[inline]
779 pub fn create_singleton (element : Element, order : CreateOrder) -> Self {
780 let subtree = TreeBuilder::new().with_root (Node::new (element)).build();
781 Action::Create (subtree, order)
782 }
783
784 #[inline]
786 pub fn set_view (view : View) -> Self {
787 Action::ModifyView (Box::new (|v| *v = view))
788 }
789
790 #[inline]
792 pub fn set_controller (controller : Controller) -> Self {
793 Action::ModifyController (Box::new (|c| *c = controller))
794 }
795
796 #[inline]
798 pub fn set_model (model : Model) -> Self {
799 Action::ModifyModel (Box::new (|m| *m = model))
800 }
801
802 #[inline]
804 pub fn set_view_component <V> (component : V) -> Self where
805 V : view::component::Kind + 'static
806 {
807 Action::ModifyView (Box::new (|v| v.component = component.into()))
808 }
809
810 #[inline]
813 pub fn update_view_component <V> (component : V) -> Self where
814 V : view::component::Kind + 'static
815 {
816 Action::ModifyView (Box::new (|v| {
817 let v = V::try_ref_mut (&mut v.component).unwrap();
818 *v = component;
819 }))
820 }
821
822 #[inline]
824 pub fn set_controller_component <C> (component : C) -> Self where
825 C : ControllerKind + 'static
826 {
827 Action::ModifyController (Box::new (|c| c.component = component.into()))
828 }
829
830 #[inline]
833 pub fn update_controller_component <C> (component : C) -> Self where
834 C : ControllerKind + 'static
835 {
836 Action::ModifyController (Box::new (|c| {
837 let c = C::try_ref_mut (&mut c.component).unwrap();
838 *c = component;
839 }))
840 }
841
842 #[inline]
844 pub fn set_model_component <M> (component : M) -> Self where
845 M : model::component::Kind + 'static
846 {
847 Action::ModifyModel (Box::new (|m| m.component = component.into()))
848 }
849
850 #[inline]
853 pub fn update_model_component <M> (component : M) -> Self where
854 M : model::component::Kind + 'static
855 {
856 Action::ModifyModel (Box::new (|m| {
857 let m = M::try_ref_mut (&mut m.component).unwrap();
858 *m = component;
859 }))
860 }
861}
862
863impl std::fmt::Debug for Action {
864 fn fmt (&self, f : &mut std::fmt::Formatter) -> Result <(), std::fmt::Error> {
865 match self {
866 Action::Create (subtree, order) =>
867 write!(f, "Create({subtree:?}, {order:?})"),
868 Action::ModifyController (closure) =>
869 write!(f, "ModifyController({:p})", &closure),
870 Action::ModifyModel (closure) =>
871 write!(f, "ModifyModel({:p})", &closure),
872 Action::ModifyView (closure) =>
873 write!(f, "ModifyView({:p})", &closure),
874 Action::SubmitCallback (callback_id) =>
875 write!(f, "SubmitCallback({callback_id:?})"),
876 Action::Focus => write!(f, "Focus"),
877 Action::Enable => write!(f, "Enable"),
878 Action::Disable => write!(f, "Disable"),
879 Action::Destroy => write!(f, "Destroy"),
880 Action::ReleaseButtons => write!(f, "ReleaseButtons")
881 }
882 }
883}