1use crate::focus::core::FocusCore;
2use crate::{FocusFlag, HasFocus, Navigation};
3pub use core::FocusBuilder;
4use rat_event::{ct_event, HandleEvent, MouseOnly, Outcome, Regular};
5use ratatui::layout::Rect;
6use std::ops::Range;
7
8#[derive(Debug, Clone)]
15pub struct Focus {
16 last: FocusCore,
17 core: FocusCore,
18}
19
20#[macro_export]
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 pub fn remove_container(&mut self, container: &'_ dyn HasFocus) {
38 focus_debug!(
39 self.core.log,
40 "focus remove container {:?} ",
41 container.focus().name()
42 );
43 let flag = container.focus();
44 if self.core.is_container(&flag) {
45 if let Some((cidx, _)) = self.core.container_index_of(&flag) {
46 self.core.remove_container(cidx).reset();
47 focus_debug!(self.core.log, " -> removed");
48 } else {
49 focus_debug!(self.core.log, " => container not found");
50 }
51 } else {
52 focus_debug!(self.core.log, " => no container flag");
53 }
54 }
55
56 pub fn update_container(&mut self, container: &'_ dyn HasFocus) {
67 focus_debug!(
68 self.core.log,
69 "focus update container {:?} ",
70 container.focus().name()
71 );
72 let flag = container.focus();
73 if self.core.is_container(&flag) {
74 if let Some((cidx, range)) = self.core.container_index_of(&flag) {
75 let removed = self.core.remove_container(cidx);
76
77 let mut b = FocusBuilder::new(Some(Focus {
78 last: Default::default(),
79 core: removed,
80 }));
81 b.widget(container);
82 let insert = b.build();
83
84 self.core.insert_container(range.start, cidx, insert.core);
85
86 focus_debug!(self.core.log, " -> updated");
87 } else {
88 focus_debug!(self.core.log, " => container not found");
89 }
90 } else {
91 focus_debug!(self.core.log, " => no container flag");
92 }
93 }
94
95 pub fn replace_container(&mut self, container: &'_ dyn HasFocus, new: &'_ dyn HasFocus) {
109 focus_debug!(
110 self.core.log,
111 "focus replace container {:?} with {:?} ",
112 container.focus().name(),
113 new.focus().name()
114 );
115 let flag = container.focus();
116 if self.core.is_container(&flag) {
117 if let Some((cidx, range)) = self.core.container_index_of(&flag) {
118 let removed = self.core.remove_container(cidx);
119
120 let mut b = FocusBuilder::new(Some(Focus {
121 last: Default::default(),
122 core: removed,
123 }));
124 b.widget(new);
125 let insert = b.build();
126
127 self.core.insert_container(range.start, cidx, insert.core);
128
129 focus_debug!(self.core.log, " -> replaced");
130 } else {
131 focus_debug!(self.core.log, " => container not found");
132 }
133 } else {
134 focus_debug!(self.core.log, " => no container flag");
135 }
136 }
137
138 pub fn enable_log(&self) {
140 self.core.log.set(true);
141 self.last.log.set(true);
142 }
143
144 pub fn disable_log(&self) {
146 self.core.log.set(false);
147 self.last.log.set(false);
148 }
149
150 #[inline]
155 pub fn focus_no_lost(&self, widget_state: &'_ dyn HasFocus) {
156 focus_debug!(
157 self.core.log,
158 "focus no_lost {:?}",
159 widget_state.focus().name()
160 );
161 let flag = widget_state.focus();
162 if self.core.is_widget(&flag) {
163 if let Some(n) = self.core.index_of(&flag) {
164 self.core.focus_idx(n, false);
165 } else {
166 focus_debug!(self.core.log, " => widget not found");
167 }
168 } else if self.core.is_container(&flag) {
169 if let Some((_idx, range)) = self.core.container_index_of(&flag) {
170 self.core.focus_idx(range.start, false);
171 focus_debug!(self.core.log, " -> focused");
172 } else {
173 focus_debug!(self.core.log, " => container not found");
174 }
175 } else {
176 focus_debug!(self.core.log, " => not a valid widget");
177 }
178 }
179
180 #[inline]
187 pub fn focus(&self, widget_state: &'_ dyn HasFocus) {
188 focus_debug!(self.core.log, "focus {:?}", widget_state.focus().name());
189 let flag = widget_state.focus();
190 if self.core.is_widget(&flag) {
191 if let Some(n) = self.core.index_of(&flag) {
192 self.core.focus_idx(n, true);
193 } else {
194 focus_debug!(self.core.log, " => widget not found");
195 }
196 } else if self.core.is_container(&flag) {
197 if let Some((_idx, range)) = self.core.container_index_of(&flag) {
198 self.core.focus_idx(range.start, true);
199 focus_debug!(self.core.log, " -> focused");
200 } else {
201 focus_debug!(self.core.log, " => container not found");
202 }
203 } else {
204 focus_debug!(self.core.log, " => not a valid widget");
205 }
206 }
207
208 #[inline]
211 pub fn expel_focus(&self, widget_state: &'_ dyn HasFocus) {
212 focus_debug!(
213 self.core.log,
214 "expel from widget {:?}",
215 widget_state.focus().name()
216 );
217 let flag = widget_state.focus();
218 if self.core.is_widget(&flag) {
219 if self.core.index_of(&flag).is_some() {
220 if widget_state.is_focused() {
221 self.core.next();
222 if widget_state.is_focused() {
223 focus_debug!(self.core.log, " -> no other focus, cleared");
224 flag.clear();
225 } else {
226 focus_debug!(self.core.log, " -> expelled");
227 }
228 } else {
229 focus_debug!(self.core.log, " => widget not focused");
230 }
231 } else {
232 focus_debug!(self.core.log, " => widget not found");
233 }
234 } else if self.core.is_container(&flag) {
235 if flag.is_focused() {
236 self.core.expel_container(flag);
237 } else {
238 focus_debug!(self.core.log, " => container not focused");
239 }
240 } else {
241 focus_debug!(self.core.log, " => not a valid widget");
242 }
243 }
244
245 #[inline(always)]
251 pub fn focused(&self) -> Option<FocusFlag> {
252 self.core.focused()
253 }
254
255 #[inline(always)]
259 pub fn focused_name(&self) -> Option<String> {
260 self.core.focused().map(|v| v.name().to_string())
261 }
262
263 #[inline(always)]
265 pub fn navigation(&self) -> Option<Navigation> {
266 self.core.navigation()
267 }
268
269 #[inline(always)]
275 pub fn lost_focus(&self) -> Option<FocusFlag> {
276 self.core.lost_focus()
277 }
278
279 #[inline(always)]
285 pub fn gained_focus(&self) -> Option<FocusFlag> {
286 self.core.gained_focus()
287 }
288
289 #[inline(always)]
292 pub fn reset_lost_gained(&self) {
293 self.core.reset_lost_gained();
294 }
295
296 #[inline(always)]
298 pub fn focus_at(&self, col: u16, row: u16) -> bool {
299 focus_debug!(self.core.log, "focus at {},{}", col, row);
300 match self.navigation() {
301 Some(Navigation::Lock) => {
302 focus_debug!(self.core.log, " -> locked");
303 false
304 }
305 _ => self.core.focus_at(col, row),
306 }
307 }
308
309 #[inline(always)]
314 pub fn first(&self) {
315 focus_debug!(self.core.log, "focus first");
316 self.core.first();
317 }
318
319 #[inline]
324 pub fn first_in(&self, container: &'_ dyn HasFocus) {
325 focus_debug!(
326 self.core.log,
327 "focus first in container {:?} ",
328 container.focus().name()
329 );
330 let flag = container.focus();
331 if self.core.is_container(&flag) {
332 self.core.first_container(&flag);
333 } else if self.core.is_widget(&flag) {
334 if let Some(n) = self.core.index_of(&flag) {
335 self.core.focus_idx(n, true);
336 } else {
337 focus_debug!(self.core.log, " => widget not found");
338 }
339 } else {
340 focus_debug!(self.core.log, " -> not a container");
341 }
342 }
343
344 #[inline(always)]
349 pub fn none(&self) {
350 focus_debug!(self.core.log, "focus none");
351 self.core.none();
352 focus_debug!(self.core.log, " -> done");
353 }
354
355 #[inline]
362 pub fn next(&self) -> bool {
363 match self.navigation() {
364 None => {
365 self.first();
366 true
367 }
368 Some(Navigation::Leave | Navigation::ReachLeaveBack | Navigation::Regular) => {
369 focus_debug!(
370 self.core.log,
371 "next after {:?}",
372 self.core.focused().map(|v| v.name().to_string())
373 );
374 self.core.next()
375 }
376 v => {
377 focus_debug!(
378 self.core.log,
379 "next after {:?}, but navigation says {:?}",
380 self.core.focused().map(|v| v.name().to_string()),
381 v
382 );
383 false
384 }
385 }
386 }
387
388 #[inline]
395 pub fn prev(&self) -> bool {
396 match self.navigation() {
397 None => {
398 self.first();
399 true
400 }
401 Some(Navigation::Leave | Navigation::ReachLeaveFront | Navigation::Regular) => {
402 focus_debug!(
403 self.core.log,
404 "prev before {:?}",
405 self.core.focused().map(|v| v.name().to_string())
406 );
407 self.core.prev()
408 }
409 v => {
410 focus_debug!(
411 self.core.log,
412 "prev before {:?}, but navigation says {:?}",
413 self.core.focused().map(|v| v.name().to_string()),
414 v
415 );
416 false
417 }
418 }
419 }
420
421 #[inline]
430 pub fn next_force(&self) -> bool {
431 match self.navigation() {
432 None => {
433 self.first();
434 true
435 }
436 Some(
437 Navigation::Leave
438 | Navigation::Reach
439 | Navigation::ReachLeaveFront
440 | Navigation::ReachLeaveBack
441 | Navigation::Regular,
442 ) => {
443 focus_debug!(
444 self.core.log,
445 "force next after {:?}",
446 self.core.focused().map(|v| v.name().to_string())
447 );
448 self.core.next()
449 }
450 v => {
451 focus_debug!(
452 self.core.log,
453 "force next after {:?}, but navigation says {:?}",
454 self.core.focused().map(|v| v.name().to_string()),
455 v
456 );
457 false
458 }
459 }
460 }
461
462 #[inline]
472 pub fn prev_force(&self) -> bool {
473 match self.navigation() {
474 None => {
475 self.first();
476 true
477 }
478 Some(
479 Navigation::Leave
480 | Navigation::Reach
481 | Navigation::ReachLeaveFront
482 | Navigation::ReachLeaveBack
483 | Navigation::Regular,
484 ) => {
485 focus_debug!(
486 self.core.log,
487 "force prev before {:?}",
488 self.core.focused().map(|v| v.name().to_string())
489 );
490 self.core.prev()
491 }
492 v => {
493 focus_debug!(
494 self.core.log,
495 "force prev before {:?}, but navigation says {:?}",
496 self.core.focused().map(|v| v.name().to_string()),
497 v
498 );
499 false
500 }
501 }
502 }
503
504 #[allow(clippy::type_complexity)]
506 pub fn clone_destruct(
507 &self,
508 ) -> (
509 Vec<FocusFlag>,
510 Vec<bool>,
511 Vec<(Rect, u16)>,
512 Vec<Navigation>,
513 Vec<(FocusFlag, (Rect, u16), Range<usize>)>,
514 ) {
515 self.core.clone_destruct()
516 }
517}
518
519mod core {
520 use crate::{Focus, FocusFlag, HasFocus, Navigation};
521 use fxhash::FxBuildHasher;
522 use ratatui::layout::Rect;
523 use std::cell::Cell;
524 use std::collections::HashSet;
525 use std::ops::Range;
526
527 #[derive(Debug, Default)]
529 pub struct FocusBuilder {
530 last: FocusCore,
531
532 log: Cell<bool>,
533
534 z_base: u16,
542
543 focus_ids: HashSet<usize, FxBuildHasher>,
545 focus_flags: Vec<FocusFlag>,
546 duplicate: Vec<bool>,
547 areas: Vec<(Rect, u16)>,
548 navigable: Vec<Navigation>,
549 container_ids: HashSet<usize, FxBuildHasher>,
550 containers: Vec<(Container, Range<usize>)>,
551 }
552
553 impl FocusBuilder {
554 pub fn new(last: Option<Focus>) -> FocusBuilder {
555 if let Some(mut last) = last {
556 last.last.clear();
558
559 Self {
560 last: last.core,
561 log: Default::default(),
562 z_base: 0,
563 focus_ids: last.last.focus_ids,
564 focus_flags: last.last.focus_flags,
565 duplicate: last.last.duplicate,
566 areas: last.last.areas,
567 navigable: last.last.navigable,
568 container_ids: last.last.container_ids,
569 containers: last.last.containers,
570 }
571 } else {
572 Self {
573 last: FocusCore::default(),
574 log: Default::default(),
575 z_base: Default::default(),
576 focus_ids: Default::default(),
577 focus_flags: Default::default(),
578 duplicate: Default::default(),
579 areas: Default::default(),
580 navigable: Default::default(),
581 container_ids: Default::default(),
582 containers: Default::default(),
583 }
584 }
585 }
586
587 pub fn build_for(container: &dyn HasFocus) -> Focus {
599 let mut b = FocusBuilder::new(None);
600 b.widget(container);
601 b.build()
602 }
603
604 pub fn rebuild_for(container: &dyn HasFocus, old: Option<Focus>) -> Focus {
611 let mut b = FocusBuilder::new(old);
612 b.widget(container);
613 b.build()
614 }
615
616 pub fn enable_log(&self) {
618 self.log.set(true);
619 }
620
621 pub fn disable_log(&self) {
623 self.log.set(false);
624 }
625
626 pub fn widget(&mut self, widget: &dyn HasFocus) -> &mut Self {
632 widget.build(self);
633 self
634 }
635
636 #[allow(clippy::collapsible_else_if)]
648 pub fn widget_navigate(
649 &mut self,
650 widget: &dyn HasFocus,
651 navigation: Navigation,
652 ) -> &mut Self {
653 widget.build(self);
654
655 if let Some(idx) = self.focus_flags.iter().position(|v| *v == widget.focus()) {
657 focus_debug!(
658 self.log,
659 "override navigation for {:?} with {:?}",
660 widget.focus(),
661 navigation
662 );
663
664 self.navigable[idx] = navigation;
665 } else {
666 if self.container_ids.contains(&widget.focus().widget_id()) {
667 focus_debug!(
668 self.log,
669 "FAIL to override navigation for {:?}. This is a container.",
670 widget.focus(),
671 );
672 } else {
673 focus_debug!(
674 self.log,
675 "FAIL to override navigation for {:?}. Widget doesn't use this focus-flag",
676 widget.focus(),
677 );
678 }
679 }
680
681 self
682 }
683
684 #[inline]
688 pub fn widgets<const N: usize>(&mut self, widgets: [&dyn HasFocus; N]) -> &mut Self {
689 for widget in widgets {
690 widget.build(self);
691 }
692 self
693 }
694
695 #[must_use]
708 pub fn start(&mut self, container: &dyn HasFocus) -> FocusFlag {
709 self.start_with_flags(container.focus(), container.area(), container.area_z())
710 }
711
712 pub fn end(&mut self, tag: FocusFlag) {
714 focus_debug!(self.log, "end container {:?}", tag);
715 assert!(self.container_ids.contains(&tag.widget_id()));
716
717 for (c, r) in self.containers.iter_mut().rev() {
718 if c.container_flag != tag {
719 if !c.complete {
720 panic!("FocusBuilder: Unclosed container {:?}", c.container_flag);
721 }
722 } else {
723 r.end = self.focus_flags.len();
724 c.complete = true;
725
726 focus_debug!(self.log, "container range {:?}", r);
727
728 self.z_base -= c.delta_z;
729
730 break;
731 }
732 }
733 }
734
735 pub fn leaf_widget(&mut self, widget: &dyn HasFocus) -> &mut Self {
738 self.widget_with_flags(
739 widget.focus(),
740 widget.area(),
741 widget.area_z(),
742 widget.navigable(),
743 );
744 self
745 }
746
747 pub fn widget_with_flags(
760 &mut self,
761 focus: FocusFlag,
762 area: Rect,
763 area_z: u16,
764 navigable: Navigation,
765 ) {
766 let duplicate = self.focus_ids.contains(&focus.widget_id());
767
768 if duplicate {
771 assert!(matches!(navigable, Navigation::Mouse | Navigation::None))
772 }
773
774 focus_debug!(self.log, "widget {:?}", focus);
775
776 self.focus_ids.insert(focus.widget_id());
777 self.focus_flags.push(focus);
778 self.duplicate.push(duplicate);
779 self.areas.push((area, self.z_base + area_z));
780 self.navigable.push(navigable);
781 }
782
783 #[must_use]
795 pub fn start_with_flags(
796 &mut self,
797 container_flag: FocusFlag,
798 area: Rect,
799 area_z: u16,
800 ) -> FocusFlag {
801 focus_debug!(self.log, "start container {:?}", container_flag);
802
803 assert!(!self.container_ids.contains(&container_flag.widget_id()));
805
806 self.z_base += area_z;
807
808 let len = self.focus_flags.len();
809 self.container_ids.insert(container_flag.widget_id());
810 self.containers.push((
811 Container {
812 container_flag: container_flag.clone(),
813 area: (area, self.z_base),
814 delta_z: area_z,
815 complete: false,
816 },
817 len..len,
818 ));
819
820 container_flag
821 }
822
823 pub fn build(mut self) -> Focus {
828 for v in &self.last.focus_flags {
830 if !self.focus_ids.contains(&v.widget_id()) {
831 v.clear();
832 }
833 }
834 for (v, _) in &self.last.containers {
835 let have_container = self
836 .containers
837 .iter()
838 .any(|(c, _)| v.container_flag == c.container_flag);
839 if !have_container {
840 v.container_flag.clear();
841 }
842 }
843 self.last.clear();
844
845 for (c, _) in self.containers.iter_mut().rev() {
847 if !c.complete {
848 panic!("FocusBuilder: Unclosed container {:?}", c.container_flag);
849 }
850 }
851
852 let log = self.last.log.get();
853
854 Focus {
855 last: self.last,
856 core: FocusCore {
857 log: Cell::new(log),
858 focus_ids: self.focus_ids,
859 focus_flags: self.focus_flags,
860 duplicate: self.duplicate,
861 areas: self.areas,
862 navigable: self.navigable,
863 container_ids: self.container_ids,
864 containers: self.containers,
865 },
866 }
867 }
868 }
869
870 #[derive(Debug, Clone)]
872 struct Container {
873 container_flag: FocusFlag,
877 area: (Rect, u16),
880 delta_z: u16,
882 complete: bool,
884 }
885
886 #[derive(Debug, Default, Clone)]
888 pub(super) struct FocusCore {
889 pub(super) log: Cell<bool>,
891
892 focus_ids: HashSet<usize, FxBuildHasher>,
894 focus_flags: Vec<FocusFlag>,
896 duplicate: Vec<bool>,
899 areas: Vec<(Rect, u16)>,
902 navigable: Vec<Navigation>,
904 container_ids: HashSet<usize, FxBuildHasher>,
906 containers: Vec<(Container, Range<usize>)>,
911 }
912
913 impl FocusCore {
914 pub(super) fn clear(&mut self) {
916 self.focus_ids.clear();
917 self.focus_flags.clear();
918 self.duplicate.clear();
919 self.areas.clear();
920 self.navigable.clear();
921 self.container_ids.clear();
922 self.containers.clear();
923 }
924
925 pub(super) fn is_widget(&self, focus_flag: &FocusFlag) -> bool {
927 self.focus_ids.contains(&focus_flag.widget_id())
928 }
929
930 pub(super) fn index_of(&self, focus_flag: &FocusFlag) -> Option<usize> {
932 self.focus_flags
933 .iter()
934 .enumerate()
935 .find(|(_, f)| *f == focus_flag)
936 .map(|(idx, _)| idx)
937 }
938
939 pub(super) fn is_container(&self, focus_flag: &FocusFlag) -> bool {
941 self.container_ids.contains(&focus_flag.widget_id())
942 }
943
944 pub(super) fn container_index_of(
946 &self,
947 container_flag: &FocusFlag,
948 ) -> Option<(usize, Range<usize>)> {
949 self.containers
950 .iter()
951 .enumerate()
952 .find(|(_, (c, _))| &c.container_flag == container_flag)
953 .map(|(idx, (_, range))| (idx, range.clone()))
954 }
955
956 pub(super) fn insert_container(
961 &mut self,
962 idx: usize,
963 cidx: usize,
964 mut container: FocusCore,
965 ) {
966 for c in &self.focus_flags {
967 for d in &container.focus_flags {
968 assert_ne!(c, d);
969 }
970 }
971
972 let start = idx;
974 let end = idx + container.focus_flags.len();
975
976 self.focus_ids.extend(container.focus_ids.iter());
977 self.focus_flags
978 .splice(idx..idx, container.focus_flags.drain(..));
979 self.duplicate
980 .splice(idx..idx, container.duplicate.drain(..));
981 self.areas.splice(idx..idx, container.areas.drain(..));
982 self.navigable
983 .splice(idx..idx, container.navigable.drain(..));
984
985 for (_, r) in &mut self.containers {
987 *r = Self::expand(start..end, r.clone());
988 }
989 self.containers.splice(
991 cidx..cidx,
992 container
993 .containers
994 .drain(..)
995 .map(|(c, r)| (c, Self::shift(start, r))),
996 );
997 self.container_ids.extend(container.container_ids.iter());
998 }
999
1000 pub(super) fn remove_container(&mut self, cidx: usize) -> FocusCore {
1003 let crange = self.containers[cidx].1.clone();
1004
1005 let focus_flags = self.focus_flags.drain(crange.clone()).collect::<Vec<_>>();
1007 let mut focus_ids = HashSet::<_, FxBuildHasher>::default();
1008 for f in focus_flags.iter() {
1009 self.focus_ids.remove(&f.widget_id());
1010 focus_ids.insert(f.widget_id());
1011 }
1012 let duplicate = self.duplicate.drain(crange.clone()).collect::<Vec<_>>();
1013 let areas = self.areas.drain(crange.clone()).collect::<Vec<_>>();
1014 let navigable = self.navigable.drain(crange.clone()).collect::<Vec<_>>();
1015 let sub_containers = self
1016 .containers
1017 .iter()
1018 .filter(|(_, r)| r.start >= crange.start && r.end <= crange.end)
1019 .cloned()
1020 .collect::<Vec<_>>();
1021 self.containers
1023 .retain(|(_, r)| !(r.start >= crange.start && r.end <= crange.end));
1024 let mut sub_container_ids: HashSet<usize, FxBuildHasher> = HashSet::default();
1025 for (sc, _) in sub_containers.iter() {
1026 self.container_ids.remove(&sc.container_flag.widget_id());
1027 sub_container_ids.insert(sc.container_flag.widget_id());
1028 }
1029
1030 for (_, r) in &mut self.containers {
1032 *r = Self::shrink(crange.start..crange.end, r.clone());
1033 }
1034
1035 FocusCore {
1036 log: Cell::new(false),
1037 focus_ids,
1038 focus_flags,
1039 duplicate,
1040 areas,
1041 navigable,
1042 container_ids: sub_container_ids,
1043 containers: sub_containers,
1044 }
1045 }
1046
1047 fn shift(n: usize, range: Range<usize>) -> Range<usize> {
1049 range.start + n..range.end + n
1050 }
1051
1052 fn expand(insert: Range<usize>, mut range: Range<usize>) -> Range<usize> {
1054 let len = insert.end - insert.start;
1055
1056 if range.start >= insert.start {
1057 range.start += len;
1058 }
1059 if range.end > insert.start {
1060 range.end += len;
1061 }
1062 range
1063 }
1064
1065 fn shrink(remove: Range<usize>, mut range: Range<usize>) -> Range<usize> {
1067 let len = remove.end - remove.start;
1068
1069 if range.start < remove.start {
1070 } else if range.start >= remove.start && range.start <= remove.end {
1072 range.start = remove.start;
1073 } else {
1074 range.start -= len;
1075 }
1076
1077 if range.end < remove.start {
1078 } else if range.end >= remove.start && range.end <= remove.end {
1080 range.end = remove.start;
1081 } else {
1082 range.end -= len;
1083 }
1084
1085 range
1086 }
1087
1088 fn __start_change(&self, set_lost: bool) {
1091 for (f, duplicate) in self.focus_flags.iter().zip(self.duplicate.iter()) {
1092 if *duplicate {
1093 continue;
1095 }
1096 if set_lost {
1097 f.set_lost(f.get());
1098 } else {
1099 f.set_lost(false);
1100 }
1101 f.set_gained(false);
1102 f.set(false);
1103 }
1104 }
1105
1106 fn __focus(&self, n: usize, set_lost: bool) -> bool {
1109 if let Some(f) = self.focus_flags.get(n) {
1110 focus_debug!(self.log, " -> manual focus {:?}", f.name());
1111 f.set(true);
1112 if set_lost {
1113 if f.lost() {
1114 f.set_lost(false);
1117 f.set_gained(false);
1118 false
1119 } else {
1120 f.set_gained(true);
1121 true
1122 }
1123 } else {
1124 false
1125 }
1126 } else {
1127 false
1128 }
1129 }
1130
1131 fn __accumulate(&self) {
1133 for (f, r) in &self.containers {
1134 let mut any_gained = false;
1135 let mut any_lost = false;
1136 let mut any_focused = false;
1137
1138 for idx in r.clone() {
1139 any_gained |= self.focus_flags[idx].gained();
1140 any_lost |= self.focus_flags[idx].lost();
1141 any_focused |= self.focus_flags[idx].get();
1142 }
1143
1144 f.container_flag.set(any_focused);
1145 f.container_flag.set_lost(any_lost && !any_gained);
1146 f.container_flag.set_gained(any_gained && !any_lost);
1147 }
1148 }
1149
1150 pub(super) fn reset(&self) {
1152 for f in self.focus_flags.iter() {
1153 f.set(false);
1154 f.set_lost(false);
1155 f.set_gained(false);
1156 }
1157 for (f, _) in self.containers.iter() {
1158 f.container_flag.set(false);
1159 f.container_flag.set_gained(false);
1160 f.container_flag.set_lost(false);
1161 }
1162 }
1163
1164 pub(super) fn reset_lost_gained(&self) {
1166 for f in self.focus_flags.iter() {
1167 f.set_lost(false);
1168 f.set_gained(false);
1169 }
1170 for (f, _) in self.containers.iter() {
1171 f.container_flag.set_gained(false);
1172 f.container_flag.set_lost(false);
1173 }
1174 }
1175
1176 pub(super) fn first(&self) {
1178 self.__start_change(true);
1179 if let Some(n) = self.first_navigable(0) {
1180 focus_debug!(self.log, " -> focus {:?}", self.focus_flags[n].name());
1181 self.__focus(n, true);
1182 } else {
1183 focus_debug!(self.log, " -> no navigable widget");
1184 }
1185 self.__accumulate();
1186 }
1187
1188 pub(super) fn none(&self) {
1190 self.__start_change(true);
1191 self.__accumulate();
1192 }
1193
1194 pub(super) fn first_container(&self, container: &FocusFlag) {
1196 self.__start_change(true);
1197 if let Some((_idx, range)) = self.container_index_of(container) {
1198 if let Some(n) = self.first_navigable(range.start) {
1199 if n < range.end {
1200 focus_debug!(self.log, " -> focus {:?}", self.focus_flags[n].name());
1201 self.__focus(n, true);
1202 }
1203 } else {
1204 focus_debug!(self.log, " -> no navigable widget");
1205 }
1206 } else {
1207 focus_debug!(self.log, " => container not found");
1208 }
1209 self.__accumulate();
1210 }
1211
1212 pub(super) fn focus_idx(&self, n: usize, set_lost: bool) {
1214 self.__start_change(set_lost);
1215 self.__focus(n, set_lost);
1216 self.__accumulate();
1217 }
1218
1219 pub(super) fn focus_at(&self, col: u16, row: u16) -> bool {
1223 let pos = (col, row).into();
1224
1225 enum ZOrder {
1226 Widget(usize),
1227 Container(usize),
1228 }
1229
1230 let mut z_order: Option<(ZOrder, u16)> = None;
1232 for (idx, (sub, _)) in self.containers.iter().enumerate() {
1235 if sub.area.0.contains(pos) {
1236 focus_debug!(
1237 self.log,
1238 " container area-match {:?}",
1239 sub.container_flag.name()
1240 );
1241
1242 z_order = if let Some(zz) = z_order {
1243 if zz.1 <= sub.area.1 {
1244 Some((ZOrder::Container(idx), sub.area.1))
1245 } else {
1246 Some(zz)
1247 }
1248 } else {
1249 Some((ZOrder::Container(idx), sub.area.1))
1250 };
1251 }
1252 }
1253 for (idx, area) in self.areas.iter().enumerate() {
1255 if area.0.contains(pos) {
1256 focus_debug!(
1257 self.log,
1258 " area-match {:?}",
1259 self.focus_flags[idx].name()
1260 );
1261
1262 z_order = if let Some(zz) = z_order {
1263 if zz.1 <= area.1 {
1264 Some((ZOrder::Widget(idx), area.1))
1265 } else {
1266 Some(zz)
1267 }
1268 } else {
1269 Some((ZOrder::Widget(idx), area.1))
1270 };
1271 }
1272 }
1273
1274 if let Some((idx, _)) = z_order {
1276 match idx {
1277 ZOrder::Widget(idx) => {
1278 if self.navigable[idx] != Navigation::None {
1279 self.__start_change(true);
1280 let r = self.__focus(idx, true);
1281 self.__accumulate();
1282 focus_debug!(
1283 self.log,
1284 " -> focus {:?}",
1285 self.focus_flags[idx].name()
1286 );
1287 return r;
1288 } else {
1289 focus_debug!(
1290 self.log,
1291 " -> not mouse reachable {:?}",
1292 self.focus_flags[idx].name()
1293 );
1294 return false;
1295 }
1296 }
1297 ZOrder::Container(idx) => {
1298 let range = &self.containers[idx].1;
1299 if let Some(n) = self.first_navigable(range.start) {
1300 self.__start_change(true);
1301 let r = self.__focus(n, true);
1302 self.__accumulate();
1303 focus_debug!(self.log, " -> focus {:?}", self.focus_flags[n].name());
1304 return r;
1305 }
1306 }
1307 }
1308 }
1309
1310 focus_debug!(self.log, " -> no widget at pos");
1312
1313 false
1314 }
1315
1316 pub(super) fn expel_container(&self, flag: FocusFlag) -> bool {
1318 if let Some((_idx, range)) = self.container_index_of(&flag) {
1319 self.__start_change(true);
1320 let n = self.next_navigable(range.end);
1321 self.__focus(n, true);
1322 self.__accumulate();
1323
1324 if flag.is_focused() {
1326 focus_debug!(self.log, " -> focus not usable. cleared");
1327 self.none();
1328 } else {
1329 focus_debug!(self.log, " -> expelled.");
1330 }
1331 true
1332 } else {
1333 focus_debug!(self.log, " => container not found");
1334 false
1335 }
1336 }
1337
1338 pub(super) fn next(&self) -> bool {
1340 self.__start_change(true);
1341 for (n, p) in self.focus_flags.iter().enumerate() {
1342 if p.lost() {
1343 focus_debug!(self.log, " current {:?}", p.name());
1344 let n = self.next_navigable(n);
1345 self.__focus(n, true);
1346 self.__accumulate();
1347 return true;
1348 }
1349 }
1350 if let Some(n) = self.first_navigable(0) {
1351 focus_debug!(self.log, " -> focus {:?}", self.focus_flags[n].name());
1352 self.__focus(n, true);
1353 self.__accumulate();
1354 return true;
1355 }
1356 focus_debug!(self.log, " -> no next");
1357 false
1358 }
1359
1360 pub(super) fn prev(&self) -> bool {
1362 self.__start_change(true);
1363 for (i, p) in self.focus_flags.iter().enumerate() {
1364 if p.lost() {
1365 focus_debug!(self.log, " current {:?}", p.name());
1366 let n = self.prev_navigable(i);
1367 self.__focus(n, true);
1368 self.__accumulate();
1369 return true;
1370 }
1371 }
1372 if let Some(n) = self.first_navigable(0) {
1373 focus_debug!(self.log, " -> focus {:?}", self.focus_flags[n].name());
1374 self.__focus(n, true);
1375 self.__accumulate();
1376 return true;
1377 }
1378 focus_debug!(self.log, " -> no prev");
1379 false
1380 }
1381
1382 pub(super) fn navigation(&self) -> Option<Navigation> {
1384 self.focus_flags
1385 .iter()
1386 .enumerate()
1387 .find(|(_, v)| v.get())
1388 .map(|(i, _)| self.navigable[i])
1389 }
1390
1391 pub(super) fn focused(&self) -> Option<FocusFlag> {
1393 self.focus_flags.iter().find(|v| v.get()).cloned()
1394 }
1395
1396 pub(super) fn lost_focus(&self) -> Option<FocusFlag> {
1398 self.focus_flags.iter().find(|v| v.lost()).cloned()
1399 }
1400
1401 pub(super) fn gained_focus(&self) -> Option<FocusFlag> {
1403 self.focus_flags.iter().find(|v| v.gained()).cloned()
1404 }
1405
1406 fn first_navigable(&self, start: usize) -> Option<usize> {
1408 focus_debug!(
1409 self.log,
1410 "first navigable, start at {:?} ",
1411 if start < self.focus_flags.len() {
1412 self.focus_flags[start].name()
1413 } else {
1414 "beginning"
1415 }
1416 );
1417 for n in start..self.focus_flags.len() {
1418 if matches!(
1419 self.navigable[n],
1420 Navigation::Reach
1421 | Navigation::ReachLeaveBack
1422 | Navigation::ReachLeaveFront
1423 | Navigation::Regular
1424 ) {
1425 focus_debug!(self.log, " -> {:?}", self.focus_flags[n].name());
1426 return Some(n);
1427 }
1428 }
1429 focus_debug!(self.log, " -> no first");
1430 None
1431 }
1432
1433 fn next_navigable(&self, start: usize) -> usize {
1435 focus_debug!(
1436 self.log,
1437 "next navigable after {:?}",
1438 if start < self.focus_flags.len() {
1439 self.focus_flags[start].name()
1440 } else {
1441 "last"
1442 }
1443 );
1444
1445 let mut n = start;
1446 loop {
1447 n = if n + 1 < self.focus_flags.len() {
1448 n + 1
1449 } else {
1450 0
1451 };
1452 if matches!(
1453 self.navigable[n],
1454 Navigation::Reach
1455 | Navigation::ReachLeaveBack
1456 | Navigation::ReachLeaveFront
1457 | Navigation::Regular
1458 ) {
1459 focus_debug!(self.log, " -> {}:{:?}", n, self.focus_flags[n].name());
1460 return n;
1461 }
1462 if n == start {
1463 focus_debug!(self.log, " -> {}:end at start", n);
1464 return n;
1465 }
1466 }
1467 }
1468
1469 fn prev_navigable(&self, start: usize) -> usize {
1471 focus_debug!(
1472 self.log,
1473 "prev navigable before {:?}",
1474 self.focus_flags[start].name()
1475 );
1476
1477 let mut n = start;
1478 loop {
1479 n = if n > 0 {
1480 n - 1
1481 } else {
1482 self.focus_flags.len() - 1
1483 };
1484 if matches!(
1485 self.navigable[n],
1486 Navigation::Reach
1487 | Navigation::ReachLeaveBack
1488 | Navigation::ReachLeaveFront
1489 | Navigation::Regular
1490 ) {
1491 focus_debug!(self.log, " -> {}:{:?}", n, self.focus_flags[n].name());
1492 return n;
1493 }
1494 if n == start {
1495 focus_debug!(self.log, " -> {}:end at start", n);
1496 return n;
1497 }
1498 }
1499 }
1500
1501 #[allow(clippy::type_complexity)]
1503 pub(super) fn clone_destruct(
1504 &self,
1505 ) -> (
1506 Vec<FocusFlag>,
1507 Vec<bool>,
1508 Vec<(Rect, u16)>,
1509 Vec<Navigation>,
1510 Vec<(FocusFlag, (Rect, u16), Range<usize>)>,
1511 ) {
1512 (
1513 self.focus_flags.clone(),
1514 self.duplicate.clone(),
1515 self.areas.clone(),
1516 self.navigable.clone(),
1517 self.containers
1518 .iter()
1519 .map(|(v, w)| (v.container_flag.clone(), v.area, w.clone()))
1520 .collect::<Vec<_>>(),
1521 )
1522 }
1523 }
1524
1525 #[cfg(test)]
1526 mod test {
1527 use crate::focus::core::FocusCore;
1528 use crate::{FocusBuilder, FocusFlag, HasFocus};
1529 use ratatui::layout::Rect;
1530
1531 #[test]
1532 fn test_change() {
1533 assert_eq!(FocusCore::shift(0, 1..1), 1..1);
1534 assert_eq!(FocusCore::shift(1, 1..1), 2..2);
1535
1536 assert_eq!(FocusCore::expand(3..4, 0..1), 0..1);
1537 assert_eq!(FocusCore::expand(3..4, 1..2), 1..2);
1538 assert_eq!(FocusCore::expand(3..4, 2..3), 2..3);
1539 assert_eq!(FocusCore::expand(3..4, 3..4), 4..5);
1540 assert_eq!(FocusCore::expand(3..4, 4..5), 5..6);
1541
1542 assert_eq!(FocusCore::expand(3..3, 0..1), 0..1);
1543 assert_eq!(FocusCore::expand(3..3, 1..2), 1..2);
1544 assert_eq!(FocusCore::expand(3..3, 2..3), 2..3);
1545 assert_eq!(FocusCore::expand(3..3, 3..4), 3..4);
1546 assert_eq!(FocusCore::expand(3..3, 4..5), 4..5);
1547
1548 assert_eq!(FocusCore::shrink(3..4, 0..1), 0..1);
1549 assert_eq!(FocusCore::shrink(3..4, 2..3), 2..3);
1550 assert_eq!(FocusCore::shrink(3..4, 3..4), 3..3);
1551 assert_eq!(FocusCore::shrink(3..4, 4..5), 3..4);
1552 assert_eq!(FocusCore::shrink(3..4, 5..6), 4..5);
1553
1554 assert_eq!(FocusCore::shrink(3..3, 0..1), 0..1);
1555 assert_eq!(FocusCore::shrink(3..3, 1..2), 1..2);
1556 assert_eq!(FocusCore::shrink(3..3, 2..3), 2..3);
1557 assert_eq!(FocusCore::shrink(3..3, 3..4), 3..4);
1558 assert_eq!(FocusCore::shrink(3..3, 4..5), 4..5);
1559 }
1560
1561 #[test]
1562 #[should_panic]
1563 fn test_double_insert() {
1564 let a = FocusFlag::named("a");
1565 let b = FocusFlag::named("b");
1566
1567 let mut fb = FocusBuilder::new(None);
1568 fb.widget(&a);
1569 fb.widget(&b);
1570 fb.widget(&a);
1571 fb.build();
1572 }
1573
1574 #[test]
1575 fn test_insert_remove() {
1576 let a = FocusFlag::named("a");
1577 let b = FocusFlag::named("b");
1578 let c = FocusFlag::named("c");
1579 let d = FocusFlag::named("d");
1580 let e = FocusFlag::named("e");
1581 let f = FocusFlag::named("f");
1582 let g = FocusFlag::named("g");
1583 let h = FocusFlag::named("h");
1584 let i = FocusFlag::named("i");
1585
1586 let mut fb = FocusBuilder::new(None);
1587 fb.widget(&a);
1588 fb.widget(&b);
1589 fb.widget(&c);
1590 let ff = fb.build();
1591 assert_eq!(ff.core.focus_flags[0], a);
1592 assert_eq!(ff.core.focus_flags[1], b);
1593 assert_eq!(ff.core.focus_flags[2], c);
1594
1595 let cc = FocusFlag::named("cc");
1596 let mut fb = FocusBuilder::new(None);
1597 fb.widget(&a);
1598 let cc_end = fb.start_with_flags(cc.clone(), Rect::default(), 0);
1599 fb.widget(&d);
1600 fb.widget(&e);
1601 fb.widget(&f);
1602 fb.end(cc_end);
1603 fb.widget(&b);
1604 fb.widget(&c);
1605 let mut ff = fb.build();
1606 assert_eq!(ff.core.focus_flags[0], a);
1607 assert_eq!(ff.core.focus_flags[1], d);
1608 assert_eq!(ff.core.focus_flags[2], e);
1609 assert_eq!(ff.core.focus_flags[3], f);
1610 assert_eq!(ff.core.focus_flags[4], b);
1611 assert_eq!(ff.core.focus_flags[5], c);
1612 assert_eq!(ff.core.containers[0].1, 1..4);
1613
1614 struct DD {
1615 dd: FocusFlag,
1616 g: FocusFlag,
1617 h: FocusFlag,
1618 i: FocusFlag,
1619 }
1620
1621 impl HasFocus for DD {
1622 fn build(&self, fb: &mut FocusBuilder) {
1623 let tag = fb.start_with_flags(self.dd.clone(), self.area(), self.area_z());
1624 fb.widget(&self.g);
1625 fb.widget(&self.h);
1626 fb.widget(&self.i);
1627 fb.end(tag);
1628 }
1629
1630 fn focus(&self) -> FocusFlag {
1631 self.dd.clone()
1632 }
1633
1634 fn area(&self) -> Rect {
1635 Rect::default()
1636 }
1637 }
1638
1639 let dd = DD {
1640 dd: FocusFlag::named("dd"),
1641 g: g.clone(),
1642 h: h.clone(),
1643 i: i.clone(),
1644 };
1645 ff.replace_container(&cc, &dd);
1646 assert_eq!(ff.core.focus_flags[0], a);
1647 assert_eq!(ff.core.focus_flags[1], g);
1648 assert_eq!(ff.core.focus_flags[2], h);
1649 assert_eq!(ff.core.focus_flags[3], i);
1650 assert_eq!(ff.core.focus_flags[4], b);
1651 assert_eq!(ff.core.focus_flags[5], c);
1652 assert_eq!(ff.core.containers[0].1, 1..4);
1653 }
1654 }
1655}
1656
1657impl HandleEvent<crossterm::event::Event, Regular, Outcome> for Focus {
1658 #[inline(always)]
1659 fn handle(&mut self, event: &crossterm::event::Event, _keymap: Regular) -> Outcome {
1660 match event {
1661 ct_event!(keycode press Tab) => {
1662 focus_debug!(
1663 self.core.log,
1664 "Tab {:?}",
1665 self.focused().map(|v| v.name().to_string())
1666 );
1667 let r = self.next().into();
1668 focus_debug!(
1669 self.core.log,
1670 " -> {:?}",
1671 self.focused().map(|v| v.name().to_string())
1672 );
1673 r
1674 }
1675 ct_event!(keycode press SHIFT-Tab) | ct_event!(keycode press SHIFT-BackTab) => {
1676 focus_debug!(
1677 self.core.log,
1678 "BackTab {:?}",
1679 self.focused().map(|v| v.name().to_string())
1680 );
1681 let r = self.prev().into();
1682 focus_debug!(
1683 self.core.log,
1684 " -> {:?}",
1685 self.focused().map(|v| v.name().to_string())
1686 );
1687 r
1688 }
1689 _ => self.handle(event, MouseOnly),
1690 }
1691 }
1692}
1693
1694impl HandleEvent<crossterm::event::Event, MouseOnly, Outcome> for Focus {
1695 #[inline(always)]
1696 fn handle(&mut self, event: &crossterm::event::Event, _keymap: MouseOnly) -> Outcome {
1697 match event {
1698 ct_event!(mouse down Left for column, row) => {
1699 focus_debug!(self.core.log, "mouse down {},{}", column, row);
1700 if self.focus_at(*column, *row) {
1701 focus_debug!(
1702 self.core.log,
1703 " -> {:?}",
1704 self.focused().map(|v| v.name().to_string())
1705 );
1706 Outcome::Changed
1707 } else {
1708 self.reset_lost_gained();
1709 Outcome::Continue
1710 }
1711 }
1712 _ => {
1713 self.reset_lost_gained();
1714 Outcome::Continue
1715 }
1716 }
1717 }
1718}
1719
1720#[inline(always)]
1722pub fn handle_focus(focus: &mut Focus, event: &crossterm::event::Event) -> Outcome {
1723 HandleEvent::handle(focus, event, Regular)
1724}