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