rat_focus/
focus.rs

1use crate::focus::core::FocusCore;
2use crate::{FocusFlag, HasFocus, Navigation};
3pub use core::FocusBuilder;
4use rat_event::{HandleEvent, MouseOnly, Outcome, Regular, ct_event};
5use ratatui::layout::Rect;
6use std::ops::Range;
7
8/// Focus deals with all focus-related issues.
9///
10/// It must be constructed at least after each render(), as it holds
11/// copies of the widget-areas for mouse-handling.
12///
13/// In practice, construct it, when you first need it.
14#[derive(Default, Debug, Clone)]
15pub struct Focus {
16    last: FocusCore,
17    core: FocusCore,
18}
19
20macro_rules! focus_debug {
21    ($log:expr, $($arg:tt)+) => {
22        if $log.get() {
23            log::log!(log::Level::Debug, $($arg)+);
24        }
25    }
26}
27
28impl Focus {
29    /// Dynamic change of the widget structure of a container widget.
30    ///
31    /// This is only necessary if your widget structure changes
32    /// during event-handling, and you need a programmatic
33    /// focus-change for the new structure.
34    ///
35    /// This resets the focus-flags of the removed container.
36    pub fn remove_container(&mut self, container: &'_ dyn HasFocus) {
37        focus_debug!(
38            self.core.log,
39            "focus remove container {:?} ",
40            container.focus().name()
41        );
42        let flag = container.focus();
43        if self.core.is_container(&flag) {
44            if let Some((cidx, _)) = self.core.container_index_of(&flag) {
45                self.core.remove_container(cidx).reset();
46                focus_debug!(self.core.log, "    -> removed");
47            } else {
48                focus_debug!(self.core.log, "    => container not found");
49            }
50        } else {
51            focus_debug!(self.core.log, "    => no container flag");
52        }
53    }
54
55    /// Dynamic change of the widget structure of a container.
56    ///
57    /// This is only necessary if your widget structure changes
58    /// during event-handling, and you need a programmatic
59    /// focus-change for the new structure.
60    ///
61    /// If the widget that currently has the focus is still
62    /// part of the widget structure it keeps the focus.
63    /// The focus-flags for all widgets that are no longer part
64    /// of the widget structure are reset.
65    pub fn update_container(&mut self, container: &'_ dyn HasFocus) {
66        focus_debug!(
67            self.core.log,
68            "focus update container {:?} ",
69            container.focus().name()
70        );
71        let flag = container.focus();
72        if self.core.is_container(&flag) {
73            if let Some((cidx, range)) = self.core.container_index_of(&flag) {
74                let removed = self.core.remove_container(cidx);
75
76                let mut b = FocusBuilder::new(Some(Focus {
77                    last: Default::default(),
78                    core: removed,
79                }));
80                b.widget(container);
81                let insert = b.build();
82
83                self.core.insert_container(range.start, cidx, insert.core);
84
85                focus_debug!(self.core.log, "    -> updated");
86            } else {
87                focus_debug!(self.core.log, "    => container not found");
88            }
89        } else {
90            focus_debug!(self.core.log, "    => no container flag");
91        }
92    }
93
94    /// Dynamic change of the widget structure of a container.
95    ///
96    /// This is only necessary if your widget structure changes
97    /// during event-handling, and you need a programmatic
98    /// focus-change.
99    ///
100    /// This removes the widgets of one container and inserts
101    /// the widgets of the other one in place.
102    ///
103    /// If the widget that currently has the focus is still
104    /// part of the widget structure it keeps the focus.
105    /// The focus-flags for all widgets that are no longer part
106    /// of the widget structure are reset.
107    pub fn replace_container(&mut self, container: &'_ dyn HasFocus, new: &'_ dyn HasFocus) {
108        focus_debug!(
109            self.core.log,
110            "focus replace container {:?} with {:?} ",
111            container.focus().name(),
112            new.focus().name()
113        );
114        let flag = container.focus();
115        if self.core.is_container(&flag) {
116            if let Some((cidx, range)) = self.core.container_index_of(&flag) {
117                let removed = self.core.remove_container(cidx);
118
119                let mut b = FocusBuilder::new(Some(Focus {
120                    last: Default::default(),
121                    core: removed,
122                }));
123                b.widget(new);
124                let insert = b.build();
125
126                self.core.insert_container(range.start, cidx, insert.core);
127
128                focus_debug!(self.core.log, "    -> replaced");
129            } else {
130                focus_debug!(self.core.log, "    => container not found");
131            }
132        } else {
133            focus_debug!(self.core.log, "    => no container flag");
134        }
135    }
136
137    /// Writes a log for each operation.
138    pub fn enable_log(&self) {
139        self.core.log.set(true);
140        self.last.log.set(true);
141    }
142
143    /// Writes a log for each operation.
144    pub fn disable_log(&self) {
145        self.core.log.set(false);
146        self.last.log.set(false);
147    }
148
149    /// Sets the focus to the widget.
150    ///
151    /// Sets the focus, but doesn't set lost or gained.
152    /// This can be used to prevent validation of the field.
153    #[inline]
154    pub fn focus_no_lost(&self, widget_state: &'_ dyn HasFocus) {
155        focus_debug!(
156            self.core.log,
157            "focus no_lost {:?}",
158            widget_state.focus().name()
159        );
160        let flag = widget_state.focus();
161        if self.core.is_widget(&flag) {
162            if let Some(n) = self.core.index_of(&flag) {
163                self.core.focus_idx(n, false);
164            } else {
165                focus_debug!(self.core.log, "    => widget not found");
166            }
167        } else if self.core.is_container(&flag) {
168            if let Some((_idx, range)) = self.core.container_index_of(&flag) {
169                self.core.focus_idx(range.start, false);
170                focus_debug!(self.core.log, "    -> focused");
171            } else {
172                focus_debug!(self.core.log, "    => container not found");
173            }
174        } else {
175            focus_debug!(self.core.log, "    => not a valid widget");
176        }
177    }
178
179    /// Sets the focus to the given widget.
180    ///
181    /// Sets the focus, gained and lost flags.
182    ///
183    /// If this ends up with the same widget as
184    /// before gained and lost flags are not set.
185    #[inline]
186    pub fn by_widget_id(&self, widget_id: usize) {
187        let widget_state = self.core.find_widget_id(widget_id);
188        focus_debug!(self.core.log, "focus {:?} -> {:?}", widget_id, widget_state);
189        let Some(widget_state) = widget_state else {
190            return;
191        };
192
193        let flag = widget_state.focus();
194        if self.core.is_widget(&flag) {
195            if let Some(n) = self.core.index_of(&flag) {
196                self.core.focus_idx(n, true);
197            } else {
198                focus_debug!(self.core.log, "    => widget not found");
199            }
200        } else if self.core.is_container(&flag) {
201            if let Some((_idx, range)) = self.core.container_index_of(&flag) {
202                self.core.focus_idx(range.start, true);
203                focus_debug!(self.core.log, "    -> focused");
204            } else {
205                focus_debug!(self.core.log, "    => container not found");
206            }
207        } else {
208            focus_debug!(self.core.log, "    => not a valid widget");
209        }
210    }
211
212    /// Sets the focus to the given widget.
213    ///
214    /// Sets the focus, gained and lost flags.
215    ///
216    /// If this ends up with the same widget as
217    /// before gained and lost flags are not set.
218    #[inline]
219    pub fn focus(&self, widget_state: &'_ dyn HasFocus) {
220        focus_debug!(self.core.log, "focus {:?}", widget_state.focus().name());
221        let flag = widget_state.focus();
222        if self.core.is_widget(&flag) {
223            if let Some(n) = self.core.index_of(&flag) {
224                self.core.focus_idx(n, true);
225            } else {
226                focus_debug!(self.core.log, "    => widget not found");
227            }
228        } else if self.core.is_container(&flag) {
229            if let Some((_idx, range)) = self.core.container_index_of(&flag) {
230                self.core.focus_idx(range.start, true);
231                focus_debug!(self.core.log, "    -> focused");
232            } else {
233                focus_debug!(self.core.log, "    => container not found");
234            }
235        } else {
236            focus_debug!(self.core.log, "    => not a valid widget");
237        }
238    }
239
240    /// Expels the focus from the given widget regardless of
241    /// the current state.
242    #[inline]
243    pub fn expel_focus(&self, widget_state: &'_ dyn HasFocus) {
244        focus_debug!(
245            self.core.log,
246            "expel from widget {:?}",
247            widget_state.focus().name()
248        );
249        let flag = widget_state.focus();
250        if self.core.is_widget(&flag) {
251            if self.core.index_of(&flag).is_some() {
252                if widget_state.is_focused() {
253                    self.core.next();
254                    if widget_state.is_focused() {
255                        focus_debug!(self.core.log, "    -> no other focus, cleared");
256                        flag.clear();
257                    } else {
258                        focus_debug!(self.core.log, "    -> expelled");
259                    }
260                } else {
261                    focus_debug!(self.core.log, "    => widget not focused");
262                }
263            } else {
264                focus_debug!(self.core.log, "    => widget not found");
265            }
266        } else if self.core.is_container(&flag) {
267            if flag.is_focused() {
268                self.core.expel_container(flag);
269            } else {
270                focus_debug!(self.core.log, "    => container not focused");
271            }
272        } else {
273            focus_debug!(self.core.log, "    => not a valid widget");
274        }
275    }
276
277    /// Returns the focused widget as FocusFlag.
278    ///
279    /// This is mainly for debugging purposes.
280    /// For control-flow [crate::match_focus] or [crate::on_gained] or [crate::on_lost]
281    /// will be nicer.
282    #[inline(always)]
283    pub fn focused(&self) -> Option<FocusFlag> {
284        self.core.focused()
285    }
286
287    /// Returns the debug name of the focused widget.
288    ///
289    /// This is mainly for debugging purposes.
290    #[inline(always)]
291    pub fn focused_name(&self) -> Option<String> {
292        self.core.focused().map(|v| v.name().to_string())
293    }
294
295    /// Returns the navigation flag for the focused widget.
296    #[inline(always)]
297    pub fn navigation(&self) -> Option<Navigation> {
298        self.core.navigation()
299    }
300
301    /// Returns the widget that lost the focus as FocusFlag.
302    ///
303    /// This is mainly for debugging purposes.
304    /// For control-flow [crate::match_focus] or [crate::on_gained] or [crate::on_lost]
305    /// will be nicer.
306    #[inline(always)]
307    pub fn lost_focus(&self) -> Option<FocusFlag> {
308        self.core.lost_focus()
309    }
310
311    /// Returns the widget that gained the focus as FocusFlag.
312    ///
313    /// This is mainly for debugging purposes.
314    /// For control-flow [crate::match_focus] or [crate::on_gained] or [crate::on_lost]
315    /// will be nicer.
316    #[inline(always)]
317    pub fn gained_focus(&self) -> Option<FocusFlag> {
318        self.core.gained_focus()
319    }
320
321    /// Reset lost + gained flags.
322    /// This is done automatically in `HandleEvent::handle()` for every event.
323    #[inline(always)]
324    pub fn reset_lost_gained(&self) {
325        self.core.reset_lost_gained();
326    }
327
328    /// Change to focus to the given position.
329    #[inline(always)]
330    pub fn focus_at(&self, col: u16, row: u16) -> bool {
331        focus_debug!(self.core.log, "focus at {},{}", col, row);
332        match self.navigation() {
333            Some(Navigation::Lock) => {
334                focus_debug!(self.core.log, "    -> locked");
335                false
336            }
337            _ => self.core.focus_at(col, row),
338        }
339    }
340
341    /// Set the initial state for all widgets.
342    ///
343    /// This ensures that there is only one focused widget.
344    /// The first widget in the list gets the focus.
345    #[inline(always)]
346    pub fn first(&self) {
347        focus_debug!(self.core.log, "focus first");
348        self.core.first();
349    }
350
351    /// Focus the first widget of a given container.
352    /// It the given HasFocus is a widget it will get the focus.
353    ///
354    /// The first navigable widget in the container gets the focus.
355    #[inline]
356    pub fn first_in(&self, container: &'_ dyn HasFocus) {
357        focus_debug!(
358            self.core.log,
359            "focus first in container {:?} ",
360            container.focus().name()
361        );
362        let flag = container.focus();
363        if self.core.is_container(&flag) {
364            self.core.first_container(&flag);
365        } else if self.core.is_widget(&flag) {
366            if let Some(n) = self.core.index_of(&flag) {
367                self.core.focus_idx(n, true);
368            } else {
369                focus_debug!(self.core.log, "    => widget not found");
370            }
371        } else {
372            focus_debug!(self.core.log, "    -> not a container");
373        }
374    }
375
376    /// Clear the focus for all widgets.
377    ///
378    /// When navigating after this focus will restart somewhere,
379    /// most probably the very first widget.
380    #[inline(always)]
381    pub fn none(&self) {
382        focus_debug!(self.core.log, "focus none");
383        self.core.none();
384        focus_debug!(self.core.log, "    -> done");
385    }
386
387    /// Focus the next widget in the cycle.
388    ///
389    /// Sets the focus, gained and lost flags. If this ends up with
390    /// the same widget as before focus, gained and lost flag are all set.
391    ///
392    /// If no field has the focus the first one gets it.
393    #[inline]
394    pub fn next(&self) -> bool {
395        match self.navigation() {
396            None => {
397                self.first();
398                true
399            }
400            Some(Navigation::Leave | Navigation::ReachLeaveBack | Navigation::Regular) => {
401                focus_debug!(
402                    self.core.log,
403                    "next after {:?}",
404                    self.core
405                        .focused()
406                        .map(|v| v.name().to_string())
407                        .unwrap_or("None".into())
408                );
409                self.core.next()
410            }
411            v => {
412                focus_debug!(
413                    self.core.log,
414                    "next after {:?}, but navigation says {:?}",
415                    self.core
416                        .focused()
417                        .map(|v| v.name().to_string())
418                        .unwrap_or("None".into()),
419                    v
420                );
421                false
422            }
423        }
424    }
425
426    /// Focus the previous widget in the cycle.
427    ///
428    /// Sets the focus and lost flags. If this ends up with the same widget as
429    /// before it returns *true* and sets the focus, gained and lost flag.
430    ///
431    /// If no field has the focus the first one gets it.
432    #[inline]
433    pub fn prev(&self) -> bool {
434        match self.navigation() {
435            None => {
436                self.first();
437                true
438            }
439            Some(Navigation::Leave | Navigation::ReachLeaveFront | Navigation::Regular) => {
440                focus_debug!(
441                    self.core.log,
442                    "prev before {:?}",
443                    self.core
444                        .focused()
445                        .map(|v| v.name().to_string())
446                        .unwrap_or("None".into())
447                );
448                self.core.prev()
449            }
450            v => {
451                focus_debug!(
452                    self.core.log,
453                    "prev before {:?}, but navigation says {:?}",
454                    self.core
455                        .focused()
456                        .map(|v| v.name().to_string())
457                        .unwrap_or("None".into()),
458                    v
459                );
460                false
461            }
462        }
463    }
464
465    /// Focus the next widget in the cycle.
466    /// Applies some extra force to this action and allows leaving
467    /// widgets that have Navigation::(Mouse, ReachLeafFront, Reach).
468    ///
469    /// Sets the focus, gained and lost flags. If this ends up with
470    /// the same widget as before focus, gained and lost flag are all set.
471    ///
472    /// If no field has the focus the first one gets it.
473    #[inline]
474    pub fn next_force(&self) -> bool {
475        match self.navigation() {
476            None => {
477                self.first();
478                true
479            }
480            Some(
481                Navigation::Leave
482                | Navigation::Reach
483                | Navigation::ReachLeaveFront
484                | Navigation::ReachLeaveBack
485                | Navigation::Regular,
486            ) => {
487                focus_debug!(
488                    self.core.log,
489                    "force next after {:?}",
490                    self.core.focused().map(|v| v.name().to_string())
491                );
492                self.core.next()
493            }
494            v => {
495                focus_debug!(
496                    self.core.log,
497                    "force next after {:?}, but navigation says {:?}",
498                    self.core.focused().map(|v| v.name().to_string()),
499                    v
500                );
501                false
502            }
503        }
504    }
505
506    /// Focus the previous widget in the cycle.
507    ///
508    /// Applies some extra force to this action and allows leaving
509    /// widgets that have Navigation::(Mouse, ReachLeafBack, Reach).
510    ///
511    /// Sets the focus and lost flags. If this ends up with the same widget as
512    /// before it returns *true* and sets the focus, gained and lost flag.
513    ///
514    /// If no field has the focus the first one gets it.
515    #[inline]
516    pub fn prev_force(&self) -> bool {
517        match self.navigation() {
518            None => {
519                self.first();
520                true
521            }
522            Some(
523                Navigation::Leave
524                | Navigation::Reach
525                | Navigation::ReachLeaveFront
526                | Navigation::ReachLeaveBack
527                | Navigation::Regular,
528            ) => {
529                focus_debug!(
530                    self.core.log,
531                    "force prev before {:?}",
532                    self.core.focused().map(|v| v.name().to_string())
533                );
534                self.core.prev()
535            }
536            v => {
537                focus_debug!(
538                    self.core.log,
539                    "force prev before {:?}, but navigation says {:?}",
540                    self.core.focused().map(|v| v.name().to_string()),
541                    v
542                );
543                false
544            }
545        }
546    }
547
548    /// Debug destructuring.
549    #[allow(clippy::type_complexity)]
550    pub fn clone_destruct(
551        &self,
552    ) -> (
553        Vec<FocusFlag>,
554        Vec<bool>,
555        Vec<(Rect, u16)>,
556        Vec<Navigation>,
557        Vec<(FocusFlag, (Rect, u16), Range<usize>)>,
558    ) {
559        self.core.clone_destruct()
560    }
561}
562
563mod core {
564    use crate::{Focus, FocusFlag, HasFocus, Navigation};
565    use fxhash::FxBuildHasher;
566    use ratatui::layout::Rect;
567    use std::cell::Cell;
568    use std::collections::HashSet;
569    use std::ops::Range;
570
571    /// Builder for the Focus.
572    #[derive(Debug, Default)]
573    pub struct FocusBuilder {
574        last: FocusCore,
575
576        log: Cell<bool>,
577
578        // base z value.
579        // starting a container adds the z-value of the container
580        // to the z_base. closing the container subtracts from the
581        // z_base. any widgets added in between have a z-value
582        // of z_base + widget z-value.
583        //
584        // this enables clean stacking of containers/widgets.
585        z_base: u16,
586
587        // new core
588        focus_ids: HashSet<usize, FxBuildHasher>,
589        focus_flags: Vec<FocusFlag>,
590        duplicate: Vec<bool>,
591        areas: Vec<(Rect, u16)>,
592        navigable: Vec<Navigation>,
593        container_ids: HashSet<usize, FxBuildHasher>,
594        containers: Vec<(Container, Range<usize>)>,
595    }
596
597    impl FocusBuilder {
598        pub fn new(last: Option<Focus>) -> FocusBuilder {
599            if let Some(mut last) = last {
600                // clear any data but retain the allocation.
601                last.last.clear();
602
603                Self {
604                    last: last.core,
605                    log: Default::default(),
606                    z_base: 0,
607                    focus_ids: last.last.focus_ids,
608                    focus_flags: last.last.focus_flags,
609                    duplicate: last.last.duplicate,
610                    areas: last.last.areas,
611                    navigable: last.last.navigable,
612                    container_ids: last.last.container_ids,
613                    containers: last.last.containers,
614                }
615            } else {
616                Self {
617                    last: FocusCore::default(),
618                    log: Default::default(),
619                    z_base: Default::default(),
620                    focus_ids: Default::default(),
621                    focus_flags: Default::default(),
622                    duplicate: Default::default(),
623                    areas: Default::default(),
624                    navigable: Default::default(),
625                    container_ids: Default::default(),
626                    containers: Default::default(),
627                }
628            }
629        }
630
631        /// Shortcut for building the focus for a container
632        /// that implements [HasFocus]().
633        ///
634        /// This creates a fresh Focus.
635        ///
636        /// __See__
637        /// Use [rebuild](FocusBuilder::rebuild_for) if you want to ensure that widgets
638        /// that are no longer in the widget structure have their
639        /// focus flag reset properly. If you don't have
640        /// some logic to conditionally add widgets to the focus,
641        /// this function is probably fine.
642        pub fn build_for(container: &dyn HasFocus) -> Focus {
643            let mut b = FocusBuilder::new(None);
644            b.widget(container);
645            b.build()
646        }
647
648        /// Shortcut function for building the focus for a container
649        /// that implements [HasFocus]()
650        ///
651        /// This takes the old Focus and reuses most of its allocations.
652        /// It also ensures that any widgets no longer in the widget structure
653        /// have their focus-flags reset.
654        pub fn rebuild_for(container: &dyn HasFocus, old: Option<Focus>) -> Focus {
655            let mut b = FocusBuilder::new(old);
656            b.widget(container);
657            b.build()
658        }
659
660        /// Do some logging of the build.
661        pub fn enable_log(&self) {
662            self.log.set(true);
663        }
664
665        /// Do some logging of the build.
666        pub fn disable_log(&self) {
667            self.log.set(false);
668        }
669
670        /// Add a widget by calling its build function.
671        /// The build function of the HasFocus trait can
672        /// use builder to define its focus requirements.
673        ///
674        /// The widget is added to all open containers.
675        pub fn widget(&mut self, widget: &dyn HasFocus) -> &mut Self {
676            widget.build(self);
677            self
678        }
679
680        /// Add a widget by calling its build function.
681        /// The build function of the HasFocus trait can
682        /// use builder to define its focus requirements.
683        ///
684        /// This tries to override the default navigation
685        /// for the given widget. This will fail if the
686        /// widget is a container. It may also fail
687        /// for other reasons. Depends on the widget.
688        /// Enable log to check.
689        ///
690        /// The widget is added to all open containers.
691        #[allow(clippy::collapsible_else_if)]
692        pub fn widget_navigate(
693            &mut self,
694            widget: &dyn HasFocus,
695            navigation: Navigation,
696        ) -> &mut Self {
697            widget.build(self);
698
699            // override navigation for the widget
700            if let Some(idx) = self.focus_flags.iter().position(|v| *v == widget.focus()) {
701                focus_debug!(
702                    self.log,
703                    "override navigation for {:?} with {:?}",
704                    widget.focus(),
705                    navigation
706                );
707
708                self.navigable[idx] = navigation;
709            } else {
710                if self.container_ids.contains(&widget.focus().widget_id()) {
711                    focus_debug!(
712                        self.log,
713                        "FAIL to override navigation for {:?}. This is a container.",
714                        widget.focus(),
715                    );
716                } else {
717                    focus_debug!(
718                        self.log,
719                        "FAIL to override navigation for {:?}. Widget doesn't use this focus-flag",
720                        widget.focus(),
721                    );
722                }
723            }
724
725            self
726        }
727
728        /// Add a bunch of widget.
729        ///
730        /// The widget is added to all open containers.
731        #[inline]
732        pub fn widgets<const N: usize>(&mut self, widgets: [&dyn HasFocus; N]) -> &mut Self {
733            for widget in widgets {
734                widget.build(self);
735            }
736            self
737        }
738
739        /// Start a container widget. Must be matched with
740        /// the equivalent [end](Self::end). Uses focus(), area() and
741        /// z_area() of the given container. navigable() is
742        /// currently not used, just leave it at the default.
743        ///
744        /// __Attention__
745        ///
746        /// Use the returned value when calling [end](Self::end).
747        ///
748        /// __Panic__
749        ///
750        /// Panics if the same container-flag is added twice.
751        #[must_use]
752        pub fn start(&mut self, container: &dyn HasFocus) -> FocusFlag {
753            self.start_with_flags(container.focus(), container.area(), container.area_z())
754        }
755
756        /// End a container widget.
757        pub fn end(&mut self, tag: FocusFlag) {
758            focus_debug!(self.log, "end container {:?}", tag);
759            assert!(self.container_ids.contains(&tag.widget_id()));
760
761            for (c, r) in self.containers.iter_mut().rev() {
762                if c.container_flag != tag {
763                    if !c.complete {
764                        panic!("FocusBuilder: Unclosed container {:?}", c.container_flag);
765                    }
766                } else {
767                    r.end = self.focus_flags.len();
768                    c.complete = true;
769
770                    focus_debug!(self.log, "container range {:?}", r);
771
772                    self.z_base -= c.delta_z;
773
774                    break;
775                }
776            }
777        }
778
779        /// Directly add the given widget's flags. Doesn't call
780        /// build() instead it uses focus(), etc. and appends a single widget.
781        pub fn leaf_widget(&mut self, widget: &dyn HasFocus) -> &mut Self {
782            self.widget_with_flags(
783                widget.focus(),
784                widget.area(),
785                widget.area_z(),
786                widget.navigable(),
787            );
788            self
789        }
790
791        /// Manually add a widgets flags.
792        ///
793        /// This is intended to be used when __implementing__
794        /// HasFocus::build() for a widget.
795        ///
796        /// In all other situations it's better to use [widget()](FocusBuilder::widget).
797        ///
798        /// __Panic__
799        ///
800        /// Panics if the same focus-flag is added twice.
801        /// Except it is allowable to add the flag a second time with
802        /// Navigation::Mouse or Navigation::None
803        pub fn widget_with_flags(
804            &mut self,
805            focus: FocusFlag,
806            area: Rect,
807            area_z: u16,
808            navigable: Navigation,
809        ) {
810            let duplicate = self.focus_ids.contains(&focus.widget_id());
811
812            // there can be a second entry for the same focus-flag
813            // if it is only for mouse interactions.
814            if duplicate {
815                assert!(matches!(navigable, Navigation::Mouse | Navigation::None))
816            }
817
818            focus_debug!(self.log, "widget {:?}", focus);
819
820            self.focus_ids.insert(focus.widget_id());
821            self.focus_flags.push(focus);
822            self.duplicate.push(duplicate);
823            self.areas.push((area, self.z_base + area_z));
824            self.navigable.push(navigable);
825        }
826
827        /// Start a container widget. Must be matched with
828        /// the equivalent [end](Self::end).
829        ///
830        /// __Attention__
831        ///
832        /// If container_flag is None a dummy flag will be created and
833        /// returned. Use the returned value when calling [end](Self::end).
834        ///
835        /// __Panic__
836        ///
837        /// Panics if the same container-flag is added twice.
838        #[must_use]
839        pub fn start_with_flags(
840            &mut self,
841            container_flag: FocusFlag,
842            area: Rect,
843            area_z: u16,
844        ) -> FocusFlag {
845            focus_debug!(self.log, "start container {:?}", container_flag);
846
847            // no duplicates allowed for containers.
848            assert!(!self.container_ids.contains(&container_flag.widget_id()));
849
850            self.z_base += area_z;
851
852            let len = self.focus_flags.len();
853            self.container_ids.insert(container_flag.widget_id());
854            self.containers.push((
855                Container {
856                    container_flag: container_flag.clone(),
857                    area: (area, self.z_base),
858                    delta_z: area_z,
859                    complete: false,
860                },
861                len..len,
862            ));
863
864            container_flag
865        }
866
867        /// Build the final Focus.
868        ///
869        /// If the old Focus has been set with new(), all widgets
870        /// that are no longer part of the focus will be cleared().
871        pub fn build(mut self) -> Focus {
872            // cleanup outcasts.
873            for v in &self.last.focus_flags {
874                if !self.focus_ids.contains(&v.widget_id()) {
875                    v.clear();
876                }
877            }
878            for (v, _) in &self.last.containers {
879                let have_container = self
880                    .containers
881                    .iter()
882                    .any(|(c, _)| v.container_flag == c.container_flag);
883                if !have_container {
884                    v.container_flag.clear();
885                }
886            }
887            self.last.clear();
888
889            // check new tree.
890            for (c, _) in self.containers.iter_mut().rev() {
891                if !c.complete {
892                    panic!("FocusBuilder: Unclosed container {:?}", c.container_flag);
893                }
894            }
895
896            let log = self.last.log.get();
897
898            Focus {
899                last: self.last,
900                core: FocusCore {
901                    log: Cell::new(log),
902                    focus_ids: self.focus_ids,
903                    focus_flags: self.focus_flags,
904                    duplicate: self.duplicate,
905                    areas: self.areas,
906                    navigable: self.navigable,
907                    container_ids: self.container_ids,
908                    containers: self.containers,
909                },
910            }
911        }
912    }
913
914    /// Struct for the data of the focus-container itself.
915    #[derive(Debug, Clone)]
916    struct Container {
917        /// Summarizes all the contained FocusFlags.
918        /// If any of them has the focus set, this will be set too.
919        /// This can help if you build compound widgets.
920        container_flag: FocusFlag,
921        /// Area for the whole compound.
922        /// Contains the area and a z-value.
923        area: (Rect, u16),
924        /// Delta Z value compared to the enclosing container.
925        delta_z: u16,
926        /// Flag for construction.
927        complete: bool,
928    }
929
930    /// Focus core.
931    #[derive(Debug, Default, Clone)]
932    pub(super) struct FocusCore {
933        /// Focus logging
934        pub(super) log: Cell<bool>,
935
936        /// List of focus-ids.
937        focus_ids: HashSet<usize, FxBuildHasher>,
938        /// List of flags.
939        focus_flags: Vec<FocusFlag>,
940        /// Is the flag the primary flag, or just a duplicate
941        /// to allow for multiple areas.
942        duplicate: Vec<bool>,
943        /// Areas for each widget.
944        /// Contains the area and a z-value for the area.
945        areas: Vec<(Rect, u16)>,
946        /// Keyboard navigable
947        navigable: Vec<Navigation>,
948        /// List of focus-ids.
949        container_ids: HashSet<usize, FxBuildHasher>,
950        /// List of containers and their dependencies.
951        /// Range here is a range in the vecs above. The ranges are
952        /// all disjoint or completely contained within one other.
953        /// No criss-cross intersections.
954        containers: Vec<(Container, Range<usize>)>,
955    }
956
957    impl FocusCore {
958        /// Clear.
959        pub(super) fn clear(&mut self) {
960            self.focus_ids.clear();
961            self.focus_flags.clear();
962            self.duplicate.clear();
963            self.areas.clear();
964            self.navigable.clear();
965            self.container_ids.clear();
966            self.containers.clear();
967        }
968
969        /// Find the FocusFlag by widget_id
970        pub(super) fn find_widget_id(&self, widget_id: usize) -> Option<FocusFlag> {
971            self.focus_flags
972                .iter()
973                .find(|v| widget_id == v.widget_id())
974                .cloned()
975        }
976
977        /// Is a widget?
978        pub(super) fn is_widget(&self, focus_flag: &FocusFlag) -> bool {
979            self.focus_ids.contains(&focus_flag.widget_id())
980        }
981
982        /// Find the first occurrence of the given focus-flag.
983        pub(super) fn index_of(&self, focus_flag: &FocusFlag) -> Option<usize> {
984            self.focus_flags
985                .iter()
986                .enumerate()
987                .find(|(_, f)| *f == focus_flag)
988                .map(|(idx, _)| idx)
989        }
990
991        /// Is a container
992        pub(super) fn is_container(&self, focus_flag: &FocusFlag) -> bool {
993            self.container_ids.contains(&focus_flag.widget_id())
994        }
995
996        /// Find the given container-flag in the list of sub-containers.
997        pub(super) fn container_index_of(
998            &self,
999            container_flag: &FocusFlag,
1000        ) -> Option<(usize, Range<usize>)> {
1001            self.containers
1002                .iter()
1003                .enumerate()
1004                .find(|(_, (c, _))| &c.container_flag == container_flag)
1005                .map(|(idx, (_, range))| (idx, range.clone()))
1006        }
1007
1008        /// Append a container.
1009        ///
1010        /// * pos - position inside the focus-flags
1011        /// * cpos - position inside the sub-containers
1012        pub(super) fn insert_container(
1013            &mut self,
1014            idx: usize,
1015            cidx: usize,
1016            mut container: FocusCore,
1017        ) {
1018            for c in &self.focus_flags {
1019                for d in &container.focus_flags {
1020                    assert_ne!(c, d);
1021                }
1022            }
1023
1024            // range for the data of the added container.
1025            let start = idx;
1026            let end = idx + container.focus_flags.len();
1027
1028            self.focus_ids.extend(container.focus_ids.iter());
1029            self.focus_flags
1030                .splice(idx..idx, container.focus_flags.drain(..));
1031            self.duplicate
1032                .splice(idx..idx, container.duplicate.drain(..));
1033            self.areas.splice(idx..idx, container.areas.drain(..));
1034            self.navigable
1035                .splice(idx..idx, container.navigable.drain(..));
1036
1037            // expand current ranges
1038            for (_, r) in &mut self.containers {
1039                *r = Self::expand(start..end, r.clone());
1040            }
1041            // shift inserted ranges into place
1042            self.containers.splice(
1043                cidx..cidx,
1044                container
1045                    .containers
1046                    .drain(..)
1047                    .map(|(c, r)| (c, Self::shift(start, r))),
1048            );
1049            self.container_ids.extend(container.container_ids.iter());
1050        }
1051
1052        /// Remove everything for the given container.
1053        /// Return the extracted values as FocusCore.
1054        pub(super) fn remove_container(&mut self, cidx: usize) -> FocusCore {
1055            let crange = self.containers[cidx].1.clone();
1056
1057            // remove
1058            let focus_flags = self.focus_flags.drain(crange.clone()).collect::<Vec<_>>();
1059            let mut focus_ids = HashSet::<_, FxBuildHasher>::default();
1060            for f in focus_flags.iter() {
1061                self.focus_ids.remove(&f.widget_id());
1062                focus_ids.insert(f.widget_id());
1063            }
1064            let duplicate = self.duplicate.drain(crange.clone()).collect::<Vec<_>>();
1065            let areas = self.areas.drain(crange.clone()).collect::<Vec<_>>();
1066            let navigable = self.navigable.drain(crange.clone()).collect::<Vec<_>>();
1067            let sub_containers = self
1068                .containers
1069                .iter()
1070                .filter(|(_, r)| r.start >= crange.start && r.end <= crange.end)
1071                .cloned()
1072                .collect::<Vec<_>>();
1073            // remove the container and all sub-containers in the range.
1074            self.containers
1075                .retain(|(_, r)| !(r.start >= crange.start && r.end <= crange.end));
1076            let mut sub_container_ids: HashSet<usize, FxBuildHasher> = HashSet::default();
1077            for (sc, _) in sub_containers.iter() {
1078                self.container_ids.remove(&sc.container_flag.widget_id());
1079                sub_container_ids.insert(sc.container_flag.widget_id());
1080            }
1081
1082            // adjust the remaining sub-containers
1083            for (_, r) in &mut self.containers {
1084                *r = Self::shrink(crange.start..crange.end, r.clone());
1085            }
1086
1087            FocusCore {
1088                log: Cell::new(false),
1089                focus_ids,
1090                focus_flags,
1091                duplicate,
1092                areas,
1093                navigable,
1094                container_ids: sub_container_ids,
1095                containers: sub_containers,
1096            }
1097        }
1098
1099        // shift the ranges left by n
1100        fn shift(n: usize, range: Range<usize>) -> Range<usize> {
1101            range.start + n..range.end + n
1102        }
1103
1104        // expand the range caused by insert
1105        fn expand(insert: Range<usize>, mut range: Range<usize>) -> Range<usize> {
1106            let len = insert.end - insert.start;
1107
1108            if range.start >= insert.start {
1109                range.start += len;
1110            }
1111            if range.end > insert.start {
1112                range.end += len;
1113            }
1114            range
1115        }
1116
1117        // shrink the range caused by remove
1118        fn shrink(remove: Range<usize>, mut range: Range<usize>) -> Range<usize> {
1119            let len = remove.end - remove.start;
1120
1121            if range.start < remove.start {
1122                // leave
1123            } else if range.start >= remove.start && range.start <= remove.end {
1124                range.start = remove.start;
1125            } else {
1126                range.start -= len;
1127            }
1128
1129            if range.end < remove.start {
1130                // leave
1131            } else if range.end >= remove.start && range.end <= remove.end {
1132                range.end = remove.start;
1133            } else {
1134                range.end -= len;
1135            }
1136
1137            range
1138        }
1139
1140        /// Reset the flags for a new round.
1141        /// set_lost - copy the current focus to the lost flag.
1142        fn __start_change(&self, set_lost: bool) {
1143            for (f, duplicate) in self.focus_flags.iter().zip(self.duplicate.iter()) {
1144                if *duplicate {
1145                    // skip duplicates
1146                    continue;
1147                }
1148                if set_lost {
1149                    f.set_lost(f.get());
1150                } else {
1151                    f.set_lost(false);
1152                }
1153                f.set_gained(false);
1154                f.set(false);
1155            }
1156        }
1157
1158        /// Set the focus to this index. Doesn't touch
1159        /// other flags.
1160        fn __focus(&self, n: usize, set_lost: bool) -> bool {
1161            if let Some(f) = self.focus_flags.get(n) {
1162                focus_debug!(self.log, "    -> focus {}:{:?}", n, f.name());
1163                f.set(true);
1164                if set_lost {
1165                    if f.lost() {
1166                        // new focus same as old.
1167                        // reset lost + gained
1168                        f.set_lost(false);
1169                        f.set_gained(false);
1170                        false
1171                    } else {
1172                        f.set_gained(true);
1173                        true
1174                    }
1175                } else {
1176                    false
1177                }
1178            } else {
1179                false
1180            }
1181        }
1182
1183        /// Accumulate all container flags.
1184        fn __accumulate(&self) {
1185            for (f, r) in &self.containers {
1186                let mut any_gained = false;
1187                let mut any_lost = false;
1188                let mut any_focused = false;
1189
1190                for idx in r.clone() {
1191                    any_gained |= self.focus_flags[idx].gained();
1192                    any_lost |= self.focus_flags[idx].lost();
1193                    any_focused |= self.focus_flags[idx].get();
1194                }
1195
1196                f.container_flag.set(any_focused);
1197                f.container_flag.set_lost(any_lost && !any_gained);
1198                f.container_flag.set_gained(any_gained && !any_lost);
1199            }
1200        }
1201
1202        /// Reset all lost+gained+focus flags.
1203        pub(super) fn reset(&self) {
1204            for f in self.focus_flags.iter() {
1205                f.set(false);
1206                f.set_lost(false);
1207                f.set_gained(false);
1208            }
1209            for (f, _) in self.containers.iter() {
1210                f.container_flag.set(false);
1211                f.container_flag.set_gained(false);
1212                f.container_flag.set_lost(false);
1213            }
1214        }
1215
1216        /// Reset all lost+gained flags.
1217        pub(super) fn reset_lost_gained(&self) {
1218            for f in self.focus_flags.iter() {
1219                f.set_lost(false);
1220                f.set_gained(false);
1221            }
1222            for (f, _) in self.containers.iter() {
1223                f.container_flag.set_gained(false);
1224                f.container_flag.set_lost(false);
1225            }
1226        }
1227
1228        /// Set the initial focus.
1229        pub(super) fn first(&self) {
1230            if let Some(n) = self.first_navigable(0) {
1231                self.__start_change(true);
1232                self.__focus(n, true);
1233                self.__accumulate();
1234            } else {
1235                focus_debug!(self.log, "    -> no navigable widget");
1236            }
1237        }
1238
1239        /// Clear the focus.
1240        pub(super) fn none(&self) {
1241            self.__start_change(true);
1242            self.__accumulate();
1243        }
1244
1245        /// Set the initial focus.
1246        pub(super) fn first_container(&self, container: &FocusFlag) {
1247            if let Some((_idx, range)) = self.container_index_of(container) {
1248                if let Some(n) = self.first_navigable(range.start) {
1249                    if n < range.end {
1250                        self.__start_change(true);
1251                        self.__focus(n, true);
1252                        self.__accumulate();
1253                    } else {
1254                        focus_debug!(self.log, "    -> no navigable widget for container");
1255                    }
1256                } else {
1257                    focus_debug!(self.log, "    -> no navigable widget");
1258                }
1259            } else {
1260                focus_debug!(self.log, "    => container not found");
1261            }
1262        }
1263
1264        /// Set the focus at the given index.
1265        pub(super) fn focus_idx(&self, n: usize, set_lost: bool) {
1266            self.__start_change(set_lost);
1267            self.__focus(n, set_lost);
1268            self.__accumulate();
1269        }
1270
1271        /// Set the focus at the given screen position.
1272        /// Traverses the list to find the matching widget.
1273        /// Checks the area and the z-areas.
1274        pub(super) fn focus_at(&self, col: u16, row: u16) -> bool {
1275            let pos = (col, row).into();
1276
1277            enum ZOrder {
1278                Widget(usize),
1279                Container(usize),
1280            }
1281
1282            // find any matching areas
1283            let mut z_order: Option<(ZOrder, u16)> = None;
1284            // search containers first. the widgets inside have the same z and are
1285            // more specific, so they should override.
1286            for (idx, (sub, _)) in self.containers.iter().enumerate() {
1287                if sub.area.0.contains(pos) {
1288                    focus_debug!(
1289                        self.log,
1290                        "    container area-match {:?}",
1291                        sub.container_flag.name()
1292                    );
1293
1294                    z_order = if let Some(zz) = z_order {
1295                        if zz.1 <= sub.area.1 {
1296                            Some((ZOrder::Container(idx), sub.area.1))
1297                        } else {
1298                            Some(zz)
1299                        }
1300                    } else {
1301                        Some((ZOrder::Container(idx), sub.area.1))
1302                    };
1303                }
1304            }
1305            // search widgets
1306            for (idx, area) in self.areas.iter().enumerate() {
1307                if area.0.contains(pos) {
1308                    focus_debug!(
1309                        self.log,
1310                        "    area-match {:?}",
1311                        self.focus_flags[idx].name()
1312                    );
1313
1314                    z_order = if let Some(zz) = z_order {
1315                        if zz.1 <= area.1 {
1316                            Some((ZOrder::Widget(idx), area.1))
1317                        } else {
1318                            Some(zz)
1319                        }
1320                    } else {
1321                        Some((ZOrder::Widget(idx), area.1))
1322                    };
1323                }
1324            }
1325
1326            // process in order, last is on top if more than one.
1327            if let Some((idx, _)) = z_order {
1328                match idx {
1329                    ZOrder::Widget(idx) => {
1330                        if self.navigable[idx] != Navigation::None {
1331                            self.__start_change(true);
1332                            let r = self.__focus(idx, true);
1333                            self.__accumulate();
1334                            return r;
1335                        } else {
1336                            focus_debug!(
1337                                self.log,
1338                                "    -> not mouse reachable {:?}",
1339                                self.focus_flags[idx].name()
1340                            );
1341                            return false;
1342                        }
1343                    }
1344                    ZOrder::Container(idx) => {
1345                        let range = &self.containers[idx].1;
1346                        if let Some(n) = self.first_navigable(range.start) {
1347                            self.__start_change(true);
1348                            let r = self.__focus(n, true);
1349                            self.__accumulate();
1350                            return r;
1351                        }
1352                    }
1353                }
1354            }
1355
1356            // last is on top
1357            focus_debug!(self.log, "    -> no widget at pos");
1358
1359            false
1360        }
1361
1362        /// Expel focus from the given container.
1363        pub(super) fn expel_container(&self, flag: FocusFlag) -> bool {
1364            if let Some((_idx, range)) = self.container_index_of(&flag) {
1365                self.__start_change(true);
1366                let n = self.next_navigable(range.end);
1367                self.__focus(n, true);
1368                self.__accumulate();
1369
1370                // still focused?
1371                if flag.is_focused() {
1372                    focus_debug!(self.log, "    -> focus not usable. cleared");
1373                    self.none();
1374                } else {
1375                    focus_debug!(self.log, "    -> expelled.");
1376                }
1377                true
1378            } else {
1379                focus_debug!(self.log, "    => container not found");
1380                false
1381            }
1382        }
1383
1384        /// Focus next.
1385        pub(super) fn next(&self) -> bool {
1386            self.__start_change(true);
1387            for (n, p) in self.focus_flags.iter().enumerate() {
1388                if p.lost() {
1389                    let n = self.next_navigable(n);
1390                    self.__focus(n, true);
1391                    self.__accumulate();
1392                    return true;
1393                }
1394            }
1395            if let Some(n) = self.first_navigable(0) {
1396                focus_debug!(
1397                    self.log,
1398                    "    use first_navigable {}:{:?}",
1399                    n,
1400                    self.focus_flags[n].name()
1401                );
1402                self.__focus(n, true);
1403                self.__accumulate();
1404                return true;
1405            }
1406            focus_debug!(self.log, "    -> no next");
1407            false
1408        }
1409
1410        /// Focus prev.
1411        pub(super) fn prev(&self) -> bool {
1412            self.__start_change(true);
1413            for (i, p) in self.focus_flags.iter().enumerate() {
1414                if p.lost() {
1415                    let n = self.prev_navigable(i);
1416                    self.__focus(n, true);
1417                    self.__accumulate();
1418                    return true;
1419                }
1420            }
1421            if let Some(n) = self.first_navigable(0) {
1422                focus_debug!(
1423                    self.log,
1424                    "    use first_navigable {}:{:?}",
1425                    n,
1426                    self.focus_flags[n].name()
1427                );
1428                self.__focus(n, true);
1429                self.__accumulate();
1430                return true;
1431            }
1432            focus_debug!(self.log, "    -> no prev");
1433            false
1434        }
1435
1436        /// Returns the navigation flag for the focused widget.
1437        pub(super) fn navigation(&self) -> Option<Navigation> {
1438            self.focus_flags
1439                .iter()
1440                .enumerate()
1441                .find(|(_, v)| v.get())
1442                .map(|(i, _)| self.navigable[i])
1443        }
1444
1445        /// Currently focused.
1446        pub(super) fn focused(&self) -> Option<FocusFlag> {
1447            self.focus_flags.iter().find(|v| v.get()).cloned()
1448        }
1449
1450        /// Last lost focus.
1451        pub(super) fn lost_focus(&self) -> Option<FocusFlag> {
1452            self.focus_flags.iter().find(|v| v.lost()).cloned()
1453        }
1454
1455        /// Current gained focus.
1456        pub(super) fn gained_focus(&self) -> Option<FocusFlag> {
1457            self.focus_flags.iter().find(|v| v.gained()).cloned()
1458        }
1459
1460        /// First navigable flag starting at n.
1461        fn first_navigable(&self, start: usize) -> Option<usize> {
1462            focus_debug!(
1463                self.log,
1464                "first navigable, start at {}:{:?} ",
1465                start,
1466                if start < self.focus_flags.len() {
1467                    self.focus_flags[start].name()
1468                } else {
1469                    "beginning"
1470                }
1471            );
1472            for n in start..self.focus_flags.len() {
1473                if matches!(
1474                    self.navigable[n],
1475                    Navigation::Reach
1476                        | Navigation::ReachLeaveBack
1477                        | Navigation::ReachLeaveFront
1478                        | Navigation::Regular
1479                ) {
1480                    focus_debug!(self.log, "    -> {}:{:?}", n, self.focus_flags[n].name());
1481                    return Some(n);
1482                }
1483            }
1484            focus_debug!(self.log, "    -> no first");
1485            None
1486        }
1487
1488        /// Next navigable flag, starting at start.
1489        fn next_navigable(&self, start: usize) -> usize {
1490            focus_debug!(
1491                self.log,
1492                "next navigable after {}:{:?}",
1493                start,
1494                if start < self.focus_flags.len() {
1495                    self.focus_flags[start].name()
1496                } else {
1497                    "last"
1498                }
1499            );
1500
1501            let mut n = start;
1502            loop {
1503                n = if n + 1 < self.focus_flags.len() {
1504                    n + 1
1505                } else {
1506                    0
1507                };
1508                if matches!(
1509                    self.navigable[n],
1510                    Navigation::Reach
1511                        | Navigation::ReachLeaveBack
1512                        | Navigation::ReachLeaveFront
1513                        | Navigation::Regular
1514                ) {
1515                    focus_debug!(self.log, "    -> {}:{:?}", n, self.focus_flags[n].name());
1516                    return n;
1517                }
1518                if n == start {
1519                    focus_debug!(self.log, "    -> {}:end at start", n);
1520                    return n;
1521                }
1522            }
1523        }
1524
1525        /// Previous navigable flag, starting at start.
1526        fn prev_navigable(&self, start: usize) -> usize {
1527            focus_debug!(
1528                self.log,
1529                "prev navigable before {}:{:?}",
1530                start,
1531                self.focus_flags[start].name()
1532            );
1533
1534            let mut n = start;
1535            loop {
1536                n = if n > 0 {
1537                    n - 1
1538                } else {
1539                    self.focus_flags.len() - 1
1540                };
1541                if matches!(
1542                    self.navigable[n],
1543                    Navigation::Reach
1544                        | Navigation::ReachLeaveBack
1545                        | Navigation::ReachLeaveFront
1546                        | Navigation::Regular
1547                ) {
1548                    focus_debug!(self.log, "    -> {}:{:?}", n, self.focus_flags[n].name());
1549                    return n;
1550                }
1551                if n == start {
1552                    focus_debug!(self.log, "    -> {}:end at start", n);
1553                    return n;
1554                }
1555            }
1556        }
1557
1558        /// Debug destructuring.
1559        #[allow(clippy::type_complexity)]
1560        pub(super) fn clone_destruct(
1561            &self,
1562        ) -> (
1563            Vec<FocusFlag>,
1564            Vec<bool>,
1565            Vec<(Rect, u16)>,
1566            Vec<Navigation>,
1567            Vec<(FocusFlag, (Rect, u16), Range<usize>)>,
1568        ) {
1569            (
1570                self.focus_flags.clone(),
1571                self.duplicate.clone(),
1572                self.areas.clone(),
1573                self.navigable.clone(),
1574                self.containers
1575                    .iter()
1576                    .map(|(v, w)| (v.container_flag.clone(), v.area, w.clone()))
1577                    .collect::<Vec<_>>(),
1578            )
1579        }
1580    }
1581
1582    #[cfg(test)]
1583    mod test {
1584        use crate::focus::core::FocusCore;
1585        use crate::{FocusBuilder, FocusFlag, HasFocus};
1586        use ratatui::layout::Rect;
1587
1588        #[test]
1589        fn test_change() {
1590            assert_eq!(FocusCore::shift(0, 1..1), 1..1);
1591            assert_eq!(FocusCore::shift(1, 1..1), 2..2);
1592
1593            assert_eq!(FocusCore::expand(3..4, 0..1), 0..1);
1594            assert_eq!(FocusCore::expand(3..4, 1..2), 1..2);
1595            assert_eq!(FocusCore::expand(3..4, 2..3), 2..3);
1596            assert_eq!(FocusCore::expand(3..4, 3..4), 4..5);
1597            assert_eq!(FocusCore::expand(3..4, 4..5), 5..6);
1598
1599            assert_eq!(FocusCore::expand(3..3, 0..1), 0..1);
1600            assert_eq!(FocusCore::expand(3..3, 1..2), 1..2);
1601            assert_eq!(FocusCore::expand(3..3, 2..3), 2..3);
1602            assert_eq!(FocusCore::expand(3..3, 3..4), 3..4);
1603            assert_eq!(FocusCore::expand(3..3, 4..5), 4..5);
1604
1605            assert_eq!(FocusCore::shrink(3..4, 0..1), 0..1);
1606            assert_eq!(FocusCore::shrink(3..4, 2..3), 2..3);
1607            assert_eq!(FocusCore::shrink(3..4, 3..4), 3..3);
1608            assert_eq!(FocusCore::shrink(3..4, 4..5), 3..4);
1609            assert_eq!(FocusCore::shrink(3..4, 5..6), 4..5);
1610
1611            assert_eq!(FocusCore::shrink(3..3, 0..1), 0..1);
1612            assert_eq!(FocusCore::shrink(3..3, 1..2), 1..2);
1613            assert_eq!(FocusCore::shrink(3..3, 2..3), 2..3);
1614            assert_eq!(FocusCore::shrink(3..3, 3..4), 3..4);
1615            assert_eq!(FocusCore::shrink(3..3, 4..5), 4..5);
1616        }
1617
1618        #[test]
1619        #[should_panic]
1620        fn test_double_insert() {
1621            let a = FocusFlag::named("a");
1622            let b = FocusFlag::named("b");
1623
1624            let mut fb = FocusBuilder::new(None);
1625            fb.widget(&a);
1626            fb.widget(&b);
1627            fb.widget(&a);
1628            fb.build();
1629        }
1630
1631        #[test]
1632        fn test_insert_remove() {
1633            let a = FocusFlag::named("a");
1634            let b = FocusFlag::named("b");
1635            let c = FocusFlag::named("c");
1636            let d = FocusFlag::named("d");
1637            let e = FocusFlag::named("e");
1638            let f = FocusFlag::named("f");
1639            let g = FocusFlag::named("g");
1640            let h = FocusFlag::named("h");
1641            let i = FocusFlag::named("i");
1642
1643            let mut fb = FocusBuilder::new(None);
1644            fb.widget(&a);
1645            fb.widget(&b);
1646            fb.widget(&c);
1647            let ff = fb.build();
1648            assert_eq!(ff.core.focus_flags[0], a);
1649            assert_eq!(ff.core.focus_flags[1], b);
1650            assert_eq!(ff.core.focus_flags[2], c);
1651
1652            let cc = FocusFlag::named("cc");
1653            let mut fb = FocusBuilder::new(None);
1654            fb.widget(&a);
1655            let cc_end = fb.start_with_flags(cc.clone(), Rect::default(), 0);
1656            fb.widget(&d);
1657            fb.widget(&e);
1658            fb.widget(&f);
1659            fb.end(cc_end);
1660            fb.widget(&b);
1661            fb.widget(&c);
1662            let mut ff = fb.build();
1663            assert_eq!(ff.core.focus_flags[0], a);
1664            assert_eq!(ff.core.focus_flags[1], d);
1665            assert_eq!(ff.core.focus_flags[2], e);
1666            assert_eq!(ff.core.focus_flags[3], f);
1667            assert_eq!(ff.core.focus_flags[4], b);
1668            assert_eq!(ff.core.focus_flags[5], c);
1669            assert_eq!(ff.core.containers[0].1, 1..4);
1670
1671            struct DD {
1672                dd: FocusFlag,
1673                g: FocusFlag,
1674                h: FocusFlag,
1675                i: FocusFlag,
1676            }
1677
1678            impl HasFocus for DD {
1679                fn build(&self, fb: &mut FocusBuilder) {
1680                    let tag = fb.start_with_flags(self.dd.clone(), self.area(), self.area_z());
1681                    fb.widget(&self.g);
1682                    fb.widget(&self.h);
1683                    fb.widget(&self.i);
1684                    fb.end(tag);
1685                }
1686
1687                fn focus(&self) -> FocusFlag {
1688                    self.dd.clone()
1689                }
1690
1691                fn area(&self) -> Rect {
1692                    Rect::default()
1693                }
1694            }
1695
1696            let dd = DD {
1697                dd: FocusFlag::named("dd"),
1698                g: g.clone(),
1699                h: h.clone(),
1700                i: i.clone(),
1701            };
1702            ff.replace_container(&cc, &dd);
1703            assert_eq!(ff.core.focus_flags[0], a);
1704            assert_eq!(ff.core.focus_flags[1], g);
1705            assert_eq!(ff.core.focus_flags[2], h);
1706            assert_eq!(ff.core.focus_flags[3], i);
1707            assert_eq!(ff.core.focus_flags[4], b);
1708            assert_eq!(ff.core.focus_flags[5], c);
1709            assert_eq!(ff.core.containers[0].1, 1..4);
1710        }
1711    }
1712}
1713
1714impl HandleEvent<crossterm::event::Event, Regular, Outcome> for Focus {
1715    #[inline(always)]
1716    fn handle(&mut self, event: &crossterm::event::Event, _keymap: Regular) -> Outcome {
1717        match event {
1718            ct_event!(keycode press Tab) => {
1719                focus_debug!(
1720                    self.core.log,
1721                    "Tab {:?}",
1722                    self.focused().map(|v| v.name().to_string())
1723                );
1724                let r = if self.next() {
1725                    Outcome::Changed
1726                } else {
1727                    Outcome::Continue
1728                };
1729                focus_debug!(
1730                    self.core.log,
1731                    "    -> {:?}",
1732                    self.focused().map(|v| v.name().to_string())
1733                );
1734                r
1735            }
1736            ct_event!(keycode press SHIFT-Tab) | ct_event!(keycode press SHIFT-BackTab) => {
1737                focus_debug!(
1738                    self.core.log,
1739                    "BackTab {:?}",
1740                    self.focused().map(|v| v.name().to_string())
1741                );
1742                let r = if self.prev() {
1743                    Outcome::Changed
1744                } else {
1745                    Outcome::Continue
1746                };
1747                focus_debug!(
1748                    self.core.log,
1749                    "    -> {:?}",
1750                    self.focused().map(|v| v.name().to_string())
1751                );
1752                r
1753            }
1754            _ => self.handle(event, MouseOnly),
1755        }
1756    }
1757}
1758
1759impl HandleEvent<crossterm::event::Event, MouseOnly, Outcome> for Focus {
1760    #[inline(always)]
1761    fn handle(&mut self, event: &crossterm::event::Event, _keymap: MouseOnly) -> Outcome {
1762        match event {
1763            ct_event!(mouse down Left for column, row) => {
1764                focus_debug!(self.core.log, "mouse down {},{}", column, row);
1765                if self.focus_at(*column, *row) {
1766                    focus_debug!(
1767                        self.core.log,
1768                        "    -> {:?}",
1769                        self.focused().map(|v| v.name().to_string())
1770                    );
1771                    Outcome::Changed
1772                } else {
1773                    self.reset_lost_gained();
1774                    Outcome::Continue
1775                }
1776            }
1777            _ => {
1778                self.reset_lost_gained();
1779                Outcome::Continue
1780            }
1781        }
1782    }
1783}
1784
1785/// Handle all events.
1786#[inline(always)]
1787pub fn handle_focus(focus: &mut Focus, event: &crossterm::event::Event) -> Outcome {
1788    HandleEvent::handle(focus, event, Regular)
1789}