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 pub fn widget_navigate(
648 &mut self,
649 widget: &dyn HasFocus,
650 navigation: Navigation,
651 ) -> &mut Self {
652 widget.build(self);
653
654 if let Some(idx) = self.focus_flags.iter().position(|v| *v == widget.focus()) {
656 focus_debug!(
657 self.log,
658 "override navigation for {:?} with {:?}",
659 widget.focus(),
660 navigation
661 );
662
663 self.navigable[idx] = navigation;
664 } else {
665 if self.container_ids.contains(&widget.focus().widget_id()) {
666 focus_debug!(
667 self.log,
668 "FAIL to override navigation for {:?}. This is a container.",
669 widget.focus(),
670 );
671 } else {
672 focus_debug!(
673 self.log,
674 "FAIL to override navigation for {:?}. Widget doesn't use this focus-flag",
675 widget.focus(),
676 );
677 }
678 }
679
680 self
681 }
682
683 #[inline]
687 pub fn widgets<const N: usize>(&mut self, widgets: [&dyn HasFocus; N]) -> &mut Self {
688 for widget in widgets {
689 widget.build(self);
690 }
691 self
692 }
693
694 #[must_use]
707 pub fn start(&mut self, container: &dyn HasFocus) -> FocusFlag {
708 self.start_with_flags(container.focus(), container.area(), container.area_z())
709 }
710
711 pub fn end(&mut self, tag: FocusFlag) {
713 focus_debug!(self.log, "end container {:?}", tag);
714 assert!(self.container_ids.contains(&tag.widget_id()));
715
716 for (c, r) in self.containers.iter_mut().rev() {
717 if c.container_flag != tag {
718 if !c.complete {
719 panic!("FocusBuilder: Unclosed container {:?}", c.container_flag);
720 }
721 } else {
722 r.end = self.focus_flags.len();
723 c.complete = true;
724
725 focus_debug!(self.log, "container range {:?}", r);
726
727 self.z_base -= c.delta_z;
728
729 break;
730 }
731 }
732 }
733
734 pub fn leaf_widget(&mut self, widget: &dyn HasFocus) -> &mut Self {
737 self.widget_with_flags(
738 widget.focus(),
739 widget.area(),
740 widget.area_z(),
741 widget.navigable(),
742 );
743 self
744 }
745
746 pub fn widget_with_flags(
759 &mut self,
760 focus: FocusFlag,
761 area: Rect,
762 area_z: u16,
763 navigable: Navigation,
764 ) {
765 let duplicate = self.focus_ids.contains(&focus.widget_id());
766
767 if duplicate {
770 assert!(matches!(navigable, Navigation::Mouse | Navigation::None))
771 }
772
773 focus_debug!(self.log, "widget {:?}", focus);
774
775 self.focus_ids.insert(focus.widget_id());
776 self.focus_flags.push(focus);
777 self.duplicate.push(duplicate);
778 self.areas.push((area, self.z_base + area_z));
779 self.navigable.push(navigable);
780 }
781
782 #[must_use]
794 pub fn start_with_flags(
795 &mut self,
796 container_flag: FocusFlag,
797 area: Rect,
798 area_z: u16,
799 ) -> FocusFlag {
800 focus_debug!(self.log, "start container {:?}", container_flag);
801
802 assert!(!self.container_ids.contains(&container_flag.widget_id()));
804
805 self.z_base += area_z;
806
807 let len = self.focus_flags.len();
808 self.container_ids.insert(container_flag.widget_id());
809 self.containers.push((
810 Container {
811 container_flag: container_flag.clone(),
812 area: (area, self.z_base),
813 delta_z: area_z,
814 complete: false,
815 },
816 len..len,
817 ));
818
819 container_flag
820 }
821
822 pub fn build(mut self) -> Focus {
827 for v in &self.last.focus_flags {
829 if !self.focus_ids.contains(&v.widget_id()) {
830 v.clear();
831 }
832 }
833 for (v, _) in &self.last.containers {
834 let have_container = self
835 .containers
836 .iter()
837 .any(|(c, _)| v.container_flag == c.container_flag);
838 if !have_container {
839 v.container_flag.clear();
840 }
841 }
842 self.last.clear();
843
844 for (c, _) in self.containers.iter_mut().rev() {
846 if !c.complete {
847 panic!("FocusBuilder: Unclosed container {:?}", c.container_flag);
848 }
849 }
850
851 let log = self.last.log.get();
852
853 Focus {
854 last: self.last,
855 core: FocusCore {
856 log: Cell::new(log),
857 focus_ids: self.focus_ids,
858 focus_flags: self.focus_flags,
859 duplicate: self.duplicate,
860 areas: self.areas,
861 navigable: self.navigable,
862 container_ids: self.container_ids,
863 containers: self.containers,
864 },
865 }
866 }
867 }
868
869 #[derive(Debug, Clone)]
871 struct Container {
872 container_flag: FocusFlag,
876 area: (Rect, u16),
879 delta_z: u16,
881 complete: bool,
883 }
884
885 #[derive(Debug, Default, Clone)]
887 pub(super) struct FocusCore {
888 pub(super) log: Cell<bool>,
890
891 focus_ids: HashSet<usize, FxBuildHasher>,
893 focus_flags: Vec<FocusFlag>,
895 duplicate: Vec<bool>,
898 areas: Vec<(Rect, u16)>,
901 navigable: Vec<Navigation>,
903 container_ids: HashSet<usize, FxBuildHasher>,
905 containers: Vec<(Container, Range<usize>)>,
910 }
911
912 impl FocusCore {
913 pub(super) fn clear(&mut self) {
915 self.focus_ids.clear();
916 self.focus_flags.clear();
917 self.duplicate.clear();
918 self.areas.clear();
919 self.navigable.clear();
920 self.container_ids.clear();
921 self.containers.clear();
922 }
923
924 pub(super) fn is_widget(&self, focus_flag: &FocusFlag) -> bool {
926 self.focus_ids.contains(&focus_flag.widget_id())
927 }
928
929 pub(super) fn index_of(&self, focus_flag: &FocusFlag) -> Option<usize> {
931 self.focus_flags
932 .iter()
933 .enumerate()
934 .find(|(_, f)| *f == focus_flag)
935 .map(|(idx, _)| idx)
936 }
937
938 pub(super) fn is_container(&self, focus_flag: &FocusFlag) -> bool {
940 self.container_ids.contains(&focus_flag.widget_id())
941 }
942
943 pub(super) fn container_index_of(
945 &self,
946 container_flag: &FocusFlag,
947 ) -> Option<(usize, Range<usize>)> {
948 self.containers
949 .iter()
950 .enumerate()
951 .find(|(_, (c, _))| &c.container_flag == container_flag)
952 .map(|(idx, (_, range))| (idx, range.clone()))
953 }
954
955 pub(super) fn insert_container(
960 &mut self,
961 idx: usize,
962 cidx: usize,
963 mut container: FocusCore,
964 ) {
965 for c in &self.focus_flags {
966 for d in &container.focus_flags {
967 assert_ne!(c, d);
968 }
969 }
970
971 let start = idx;
973 let end = idx + container.focus_flags.len();
974
975 self.focus_ids.extend(container.focus_ids.iter());
976 self.focus_flags
977 .splice(idx..idx, container.focus_flags.drain(..));
978 self.duplicate
979 .splice(idx..idx, container.duplicate.drain(..));
980 self.areas.splice(idx..idx, container.areas.drain(..));
981 self.navigable
982 .splice(idx..idx, container.navigable.drain(..));
983
984 for (_, r) in &mut self.containers {
986 *r = Self::expand(start..end, r.clone());
987 }
988 self.containers.splice(
990 cidx..cidx,
991 container
992 .containers
993 .drain(..)
994 .map(|(c, r)| (c, Self::shift(start, r))),
995 );
996 self.container_ids.extend(container.container_ids.iter());
997 }
998
999 pub(super) fn remove_container(&mut self, cidx: usize) -> FocusCore {
1002 let crange = self.containers[cidx].1.clone();
1003
1004 let focus_flags = self.focus_flags.drain(crange.clone()).collect::<Vec<_>>();
1006 let mut focus_ids = HashSet::<_, FxBuildHasher>::default();
1007 for f in focus_flags.iter() {
1008 self.focus_ids.remove(&f.widget_id());
1009 focus_ids.insert(f.widget_id());
1010 }
1011 let duplicate = self.duplicate.drain(crange.clone()).collect::<Vec<_>>();
1012 let areas = self.areas.drain(crange.clone()).collect::<Vec<_>>();
1013 let navigable = self.navigable.drain(crange.clone()).collect::<Vec<_>>();
1014 let sub_containers = self
1015 .containers
1016 .iter()
1017 .filter(|(_, r)| r.start >= crange.start && r.end <= crange.end)
1018 .cloned()
1019 .collect::<Vec<_>>();
1020 self.containers
1022 .retain(|(_, r)| !(r.start >= crange.start && r.end <= crange.end));
1023 let mut sub_container_ids: HashSet<usize, FxBuildHasher> = HashSet::default();
1024 for (sc, _) in sub_containers.iter() {
1025 self.container_ids.remove(&sc.container_flag.widget_id());
1026 sub_container_ids.insert(sc.container_flag.widget_id());
1027 }
1028
1029 for (_, r) in &mut self.containers {
1031 *r = Self::shrink(crange.start..crange.end, r.clone());
1032 }
1033
1034 FocusCore {
1035 log: Cell::new(false),
1036 focus_ids,
1037 focus_flags,
1038 duplicate,
1039 areas,
1040 navigable,
1041 container_ids: sub_container_ids,
1042 containers: sub_containers,
1043 }
1044 }
1045
1046 fn shift(n: usize, range: Range<usize>) -> Range<usize> {
1048 range.start + n..range.end + n
1049 }
1050
1051 fn expand(insert: Range<usize>, mut range: Range<usize>) -> Range<usize> {
1053 let len = insert.end - insert.start;
1054
1055 if range.start >= insert.start {
1056 range.start += len;
1057 }
1058 if range.end > insert.start {
1059 range.end += len;
1060 }
1061 range
1062 }
1063
1064 fn shrink(remove: Range<usize>, mut range: Range<usize>) -> Range<usize> {
1066 let len = remove.end - remove.start;
1067
1068 if range.start < remove.start {
1069 } else if range.start >= remove.start && range.start <= remove.end {
1071 range.start = remove.start;
1072 } else {
1073 range.start -= len;
1074 }
1075
1076 if range.end < remove.start {
1077 } else if range.end >= remove.start && range.end <= remove.end {
1079 range.end = remove.start;
1080 } else {
1081 range.end -= len;
1082 }
1083
1084 range
1085 }
1086
1087 fn __start_change(&self, set_lost: bool) {
1090 for (f, duplicate) in self.focus_flags.iter().zip(self.duplicate.iter()) {
1091 if *duplicate {
1092 continue;
1094 }
1095 if set_lost {
1096 f.set_lost(f.get());
1097 } else {
1098 f.set_lost(false);
1099 }
1100 f.set_gained(false);
1101 f.set(false);
1102 }
1103 }
1104
1105 fn __focus(&self, n: usize, set_lost: bool) -> bool {
1108 if let Some(f) = self.focus_flags.get(n) {
1109 focus_debug!(self.log, " -> manual focus {:?}", f.name());
1110 f.set(true);
1111 if set_lost {
1112 if f.lost() {
1113 f.set_lost(false);
1116 f.set_gained(false);
1117 false
1118 } else {
1119 f.set_gained(true);
1120 true
1121 }
1122 } else {
1123 false
1124 }
1125 } else {
1126 false
1127 }
1128 }
1129
1130 fn __accumulate(&self) {
1132 for (f, r) in &self.containers {
1133 let mut any_gained = false;
1134 let mut any_lost = false;
1135 let mut any_focused = false;
1136
1137 for idx in r.clone() {
1138 any_gained |= self.focus_flags[idx].gained();
1139 any_lost |= self.focus_flags[idx].lost();
1140 any_focused |= self.focus_flags[idx].get();
1141 }
1142
1143 f.container_flag.set(any_focused);
1144 f.container_flag.set_lost(any_lost && !any_gained);
1145 f.container_flag.set_gained(any_gained && !any_lost);
1146 }
1147 }
1148
1149 pub(super) fn reset(&self) {
1151 for f in self.focus_flags.iter() {
1152 f.set(false);
1153 f.set_lost(false);
1154 f.set_gained(false);
1155 }
1156 for (f, _) in self.containers.iter() {
1157 f.container_flag.set(false);
1158 f.container_flag.set_gained(false);
1159 f.container_flag.set_lost(false);
1160 }
1161 }
1162
1163 pub(super) fn reset_lost_gained(&self) {
1165 for f in self.focus_flags.iter() {
1166 f.set_lost(false);
1167 f.set_gained(false);
1168 }
1169 for (f, _) in self.containers.iter() {
1170 f.container_flag.set_gained(false);
1171 f.container_flag.set_lost(false);
1172 }
1173 }
1174
1175 pub(super) fn first(&self) {
1177 self.__start_change(true);
1178 if let Some(n) = self.first_navigable(0) {
1179 focus_debug!(self.log, " -> focus {:?}", self.focus_flags[n].name());
1180 self.__focus(n, true);
1181 } else {
1182 focus_debug!(self.log, " -> no navigable widget");
1183 }
1184 self.__accumulate();
1185 }
1186
1187 pub(super) fn none(&self) {
1189 self.__start_change(true);
1190 self.__accumulate();
1191 }
1192
1193 pub(super) fn first_container(&self, container: &FocusFlag) {
1195 self.__start_change(true);
1196 if let Some((_idx, range)) = self.container_index_of(container) {
1197 if let Some(n) = self.first_navigable(range.start) {
1198 if n < range.end {
1199 focus_debug!(self.log, " -> focus {:?}", self.focus_flags[n].name());
1200 self.__focus(n, true);
1201 }
1202 } else {
1203 focus_debug!(self.log, " -> no navigable widget");
1204 }
1205 } else {
1206 focus_debug!(self.log, " => container not found");
1207 }
1208 self.__accumulate();
1209 }
1210
1211 pub(super) fn focus_idx(&self, n: usize, set_lost: bool) {
1213 self.__start_change(set_lost);
1214 self.__focus(n, set_lost);
1215 self.__accumulate();
1216 }
1217
1218 pub(super) fn focus_at(&self, col: u16, row: u16) -> bool {
1222 let pos = (col, row).into();
1223
1224 enum ZOrder {
1225 Widget(usize),
1226 Container(usize),
1227 }
1228
1229 let mut z_order: Option<(ZOrder, u16)> = None;
1231 for (idx, (sub, _)) in self.containers.iter().enumerate() {
1234 if sub.area.0.contains(pos) {
1235 focus_debug!(
1236 self.log,
1237 " container area-match {:?}",
1238 sub.container_flag.name()
1239 );
1240
1241 z_order = if let Some(zz) = z_order {
1242 if zz.1 <= sub.area.1 {
1243 Some((ZOrder::Container(idx), sub.area.1))
1244 } else {
1245 Some(zz)
1246 }
1247 } else {
1248 Some((ZOrder::Container(idx), sub.area.1))
1249 };
1250 }
1251 }
1252 for (idx, area) in self.areas.iter().enumerate() {
1254 if area.0.contains(pos) {
1255 focus_debug!(
1256 self.log,
1257 " area-match {:?}",
1258 self.focus_flags[idx].name()
1259 );
1260
1261 z_order = if let Some(zz) = z_order {
1262 if zz.1 <= area.1 {
1263 Some((ZOrder::Widget(idx), area.1))
1264 } else {
1265 Some(zz)
1266 }
1267 } else {
1268 Some((ZOrder::Widget(idx), area.1))
1269 };
1270 }
1271 }
1272
1273 if let Some((idx, _)) = z_order {
1275 match idx {
1276 ZOrder::Widget(idx) => {
1277 if self.navigable[idx] != Navigation::None {
1278 self.__start_change(true);
1279 let r = self.__focus(idx, true);
1280 self.__accumulate();
1281 focus_debug!(
1282 self.log,
1283 " -> focus {:?}",
1284 self.focus_flags[idx].name()
1285 );
1286 return r;
1287 } else {
1288 focus_debug!(
1289 self.log,
1290 " -> not mouse reachable {:?}",
1291 self.focus_flags[idx].name()
1292 );
1293 return false;
1294 }
1295 }
1296 ZOrder::Container(idx) => {
1297 let range = &self.containers[idx].1;
1298 if let Some(n) = self.first_navigable(range.start) {
1299 self.__start_change(true);
1300 let r = self.__focus(n, true);
1301 self.__accumulate();
1302 focus_debug!(self.log, " -> focus {:?}", self.focus_flags[n].name());
1303 return r;
1304 }
1305 }
1306 }
1307 }
1308
1309 focus_debug!(self.log, " -> no widget at pos");
1311
1312 false
1313 }
1314
1315 pub(super) fn expel_container(&self, flag: FocusFlag) -> bool {
1317 if let Some((_idx, range)) = self.container_index_of(&flag) {
1318 self.__start_change(true);
1319 let n = self.next_navigable(range.end);
1320 self.__focus(n, true);
1321 self.__accumulate();
1322
1323 if flag.is_focused() {
1325 focus_debug!(self.log, " -> focus not usable. cleared");
1326 self.none();
1327 } else {
1328 focus_debug!(self.log, " -> expelled.");
1329 }
1330 true
1331 } else {
1332 focus_debug!(self.log, " => container not found");
1333 false
1334 }
1335 }
1336
1337 pub(super) fn next(&self) -> bool {
1339 self.__start_change(true);
1340 for (n, p) in self.focus_flags.iter().enumerate() {
1341 if p.lost() {
1342 focus_debug!(self.log, " current {:?}", p.name());
1343 let n = self.next_navigable(n);
1344 self.__focus(n, true);
1345 self.__accumulate();
1346 return true;
1347 }
1348 }
1349 if let Some(n) = self.first_navigable(0) {
1350 focus_debug!(self.log, " -> focus {:?}", self.focus_flags[n].name());
1351 self.__focus(n, true);
1352 self.__accumulate();
1353 return true;
1354 }
1355 focus_debug!(self.log, " -> no next");
1356 false
1357 }
1358
1359 pub(super) fn prev(&self) -> bool {
1361 self.__start_change(true);
1362 for (i, p) in self.focus_flags.iter().enumerate() {
1363 if p.lost() {
1364 focus_debug!(self.log, " current {:?}", p.name());
1365 let n = self.prev_navigable(i);
1366 self.__focus(n, true);
1367 self.__accumulate();
1368 return true;
1369 }
1370 }
1371 if let Some(n) = self.first_navigable(0) {
1372 focus_debug!(self.log, " -> focus {:?}", self.focus_flags[n].name());
1373 self.__focus(n, true);
1374 self.__accumulate();
1375 return true;
1376 }
1377 focus_debug!(self.log, " -> no prev");
1378 false
1379 }
1380
1381 pub(super) fn navigation(&self) -> Option<Navigation> {
1383 self.focus_flags
1384 .iter()
1385 .enumerate()
1386 .find(|(_, v)| v.get())
1387 .map(|(i, _)| self.navigable[i])
1388 }
1389
1390 pub(super) fn focused(&self) -> Option<FocusFlag> {
1392 self.focus_flags.iter().find(|v| v.get()).cloned()
1393 }
1394
1395 pub(super) fn lost_focus(&self) -> Option<FocusFlag> {
1397 self.focus_flags.iter().find(|v| v.lost()).cloned()
1398 }
1399
1400 pub(super) fn gained_focus(&self) -> Option<FocusFlag> {
1402 self.focus_flags.iter().find(|v| v.gained()).cloned()
1403 }
1404
1405 fn first_navigable(&self, start: usize) -> Option<usize> {
1407 focus_debug!(
1408 self.log,
1409 "first navigable, start at {:?} ",
1410 if start < self.focus_flags.len() {
1411 self.focus_flags[start].name()
1412 } else {
1413 "beginning"
1414 }
1415 );
1416 for n in start..self.focus_flags.len() {
1417 if matches!(
1418 self.navigable[n],
1419 Navigation::Reach
1420 | Navigation::ReachLeaveBack
1421 | Navigation::ReachLeaveFront
1422 | Navigation::Regular
1423 ) {
1424 focus_debug!(self.log, " -> {:?}", self.focus_flags[n].name());
1425 return Some(n);
1426 }
1427 }
1428 focus_debug!(self.log, " -> no first");
1429 None
1430 }
1431
1432 fn next_navigable(&self, start: usize) -> usize {
1434 focus_debug!(
1435 self.log,
1436 "next navigable after {:?}",
1437 if start < self.focus_flags.len() {
1438 self.focus_flags[start].name()
1439 } else {
1440 "last"
1441 }
1442 );
1443
1444 let mut n = start;
1445 loop {
1446 n = if n + 1 < self.focus_flags.len() {
1447 n + 1
1448 } else {
1449 0
1450 };
1451 if matches!(
1452 self.navigable[n],
1453 Navigation::Reach
1454 | Navigation::ReachLeaveBack
1455 | Navigation::ReachLeaveFront
1456 | Navigation::Regular
1457 ) {
1458 focus_debug!(self.log, " -> {}:{:?}", n, self.focus_flags[n].name());
1459 return n;
1460 }
1461 if n == start {
1462 focus_debug!(self.log, " -> {}:end at start", n);
1463 return n;
1464 }
1465 }
1466 }
1467
1468 fn prev_navigable(&self, start: usize) -> usize {
1470 focus_debug!(
1471 self.log,
1472 "prev navigable before {:?}",
1473 self.focus_flags[start].name()
1474 );
1475
1476 let mut n = start;
1477 loop {
1478 n = if n > 0 {
1479 n - 1
1480 } else {
1481 self.focus_flags.len() - 1
1482 };
1483 if matches!(
1484 self.navigable[n],
1485 Navigation::Reach
1486 | Navigation::ReachLeaveBack
1487 | Navigation::ReachLeaveFront
1488 | Navigation::Regular
1489 ) {
1490 focus_debug!(self.log, " -> {}:{:?}", n, self.focus_flags[n].name());
1491 return n;
1492 }
1493 if n == start {
1494 focus_debug!(self.log, " -> {}:end at start", n);
1495 return n;
1496 }
1497 }
1498 }
1499
1500 #[allow(clippy::type_complexity)]
1502 pub(super) fn clone_destruct(
1503 &self,
1504 ) -> (
1505 Vec<FocusFlag>,
1506 Vec<bool>,
1507 Vec<(Rect, u16)>,
1508 Vec<Navigation>,
1509 Vec<(FocusFlag, (Rect, u16), Range<usize>)>,
1510 ) {
1511 (
1512 self.focus_flags.clone(),
1513 self.duplicate.clone(),
1514 self.areas.clone(),
1515 self.navigable.clone(),
1516 self.containers
1517 .iter()
1518 .map(|(v, w)| (v.container_flag.clone(), v.area, w.clone()))
1519 .collect::<Vec<_>>(),
1520 )
1521 }
1522 }
1523
1524 #[cfg(test)]
1525 mod test {
1526 use crate::focus::core::FocusCore;
1527 use crate::{FocusBuilder, FocusFlag, HasFocus};
1528 use ratatui::layout::Rect;
1529
1530 #[test]
1531 fn test_change() {
1532 assert_eq!(FocusCore::shift(0, 1..1), 1..1);
1533 assert_eq!(FocusCore::shift(1, 1..1), 2..2);
1534
1535 assert_eq!(FocusCore::expand(3..4, 0..1), 0..1);
1536 assert_eq!(FocusCore::expand(3..4, 1..2), 1..2);
1537 assert_eq!(FocusCore::expand(3..4, 2..3), 2..3);
1538 assert_eq!(FocusCore::expand(3..4, 3..4), 4..5);
1539 assert_eq!(FocusCore::expand(3..4, 4..5), 5..6);
1540
1541 assert_eq!(FocusCore::expand(3..3, 0..1), 0..1);
1542 assert_eq!(FocusCore::expand(3..3, 1..2), 1..2);
1543 assert_eq!(FocusCore::expand(3..3, 2..3), 2..3);
1544 assert_eq!(FocusCore::expand(3..3, 3..4), 3..4);
1545 assert_eq!(FocusCore::expand(3..3, 4..5), 4..5);
1546
1547 assert_eq!(FocusCore::shrink(3..4, 0..1), 0..1);
1548 assert_eq!(FocusCore::shrink(3..4, 2..3), 2..3);
1549 assert_eq!(FocusCore::shrink(3..4, 3..4), 3..3);
1550 assert_eq!(FocusCore::shrink(3..4, 4..5), 3..4);
1551 assert_eq!(FocusCore::shrink(3..4, 5..6), 4..5);
1552
1553 assert_eq!(FocusCore::shrink(3..3, 0..1), 0..1);
1554 assert_eq!(FocusCore::shrink(3..3, 1..2), 1..2);
1555 assert_eq!(FocusCore::shrink(3..3, 2..3), 2..3);
1556 assert_eq!(FocusCore::shrink(3..3, 3..4), 3..4);
1557 assert_eq!(FocusCore::shrink(3..3, 4..5), 4..5);
1558 }
1559
1560 #[test]
1561 #[should_panic]
1562 fn test_double_insert() {
1563 let a = FocusFlag::named("a");
1564 let b = FocusFlag::named("b");
1565
1566 let mut fb = FocusBuilder::new(None);
1567 fb.widget(&a);
1568 fb.widget(&b);
1569 fb.widget(&a);
1570 fb.build();
1571 }
1572
1573 #[test]
1574 fn test_insert_remove() {
1575 let a = FocusFlag::named("a");
1576 let b = FocusFlag::named("b");
1577 let c = FocusFlag::named("c");
1578 let d = FocusFlag::named("d");
1579 let e = FocusFlag::named("e");
1580 let f = FocusFlag::named("f");
1581 let g = FocusFlag::named("g");
1582 let h = FocusFlag::named("h");
1583 let i = FocusFlag::named("i");
1584
1585 let mut fb = FocusBuilder::new(None);
1586 fb.widget(&a);
1587 fb.widget(&b);
1588 fb.widget(&c);
1589 let ff = fb.build();
1590 assert_eq!(ff.core.focus_flags[0], a);
1591 assert_eq!(ff.core.focus_flags[1], b);
1592 assert_eq!(ff.core.focus_flags[2], c);
1593
1594 let cc = FocusFlag::named("cc");
1595 let mut fb = FocusBuilder::new(None);
1596 fb.widget(&a);
1597 let cc_end = fb.start_with_flags(cc.clone(), Rect::default(), 0);
1598 fb.widget(&d);
1599 fb.widget(&e);
1600 fb.widget(&f);
1601 fb.end(cc_end);
1602 fb.widget(&b);
1603 fb.widget(&c);
1604 let mut ff = fb.build();
1605 assert_eq!(ff.core.focus_flags[0], a);
1606 assert_eq!(ff.core.focus_flags[1], d);
1607 assert_eq!(ff.core.focus_flags[2], e);
1608 assert_eq!(ff.core.focus_flags[3], f);
1609 assert_eq!(ff.core.focus_flags[4], b);
1610 assert_eq!(ff.core.focus_flags[5], c);
1611 assert_eq!(ff.core.containers[0].1, 1..4);
1612
1613 struct DD {
1614 dd: FocusFlag,
1615 g: FocusFlag,
1616 h: FocusFlag,
1617 i: FocusFlag,
1618 }
1619
1620 impl HasFocus for DD {
1621 fn build(&self, fb: &mut FocusBuilder) {
1622 let tag = fb.start_with_flags(self.dd.clone(), self.area(), self.area_z());
1623 fb.widget(&self.g);
1624 fb.widget(&self.h);
1625 fb.widget(&self.i);
1626 fb.end(tag);
1627 }
1628
1629 fn focus(&self) -> FocusFlag {
1630 self.dd.clone()
1631 }
1632
1633 fn area(&self) -> Rect {
1634 Rect::default()
1635 }
1636 }
1637
1638 let dd = DD {
1639 dd: FocusFlag::named("dd"),
1640 g: g.clone(),
1641 h: h.clone(),
1642 i: i.clone(),
1643 };
1644 ff.replace_container(&cc, &dd);
1645 assert_eq!(ff.core.focus_flags[0], a);
1646 assert_eq!(ff.core.focus_flags[1], g);
1647 assert_eq!(ff.core.focus_flags[2], h);
1648 assert_eq!(ff.core.focus_flags[3], i);
1649 assert_eq!(ff.core.focus_flags[4], b);
1650 assert_eq!(ff.core.focus_flags[5], c);
1651 assert_eq!(ff.core.containers[0].1, 1..4);
1652 }
1653 }
1654}
1655
1656impl HandleEvent<crossterm::event::Event, Regular, Outcome> for Focus {
1657 #[inline(always)]
1658 fn handle(&mut self, event: &crossterm::event::Event, _keymap: Regular) -> Outcome {
1659 match event {
1660 ct_event!(keycode press Tab) => {
1661 focus_debug!(
1662 self.core.log,
1663 "Tab {:?}",
1664 self.focused().map(|v| v.name().to_string())
1665 );
1666 let r = self.next().into();
1667 focus_debug!(
1668 self.core.log,
1669 " -> {:?}",
1670 self.focused().map(|v| v.name().to_string())
1671 );
1672 r
1673 }
1674 ct_event!(keycode press SHIFT-Tab) | ct_event!(keycode press SHIFT-BackTab) => {
1675 focus_debug!(
1676 self.core.log,
1677 "BackTab {:?}",
1678 self.focused().map(|v| v.name().to_string())
1679 );
1680 let r = self.prev().into();
1681 focus_debug!(
1682 self.core.log,
1683 " -> {:?}",
1684 self.focused().map(|v| v.name().to_string())
1685 );
1686 r
1687 }
1688 _ => self.handle(event, MouseOnly),
1689 }
1690 }
1691}
1692
1693impl HandleEvent<crossterm::event::Event, MouseOnly, Outcome> for Focus {
1694 #[inline(always)]
1695 fn handle(&mut self, event: &crossterm::event::Event, _keymap: MouseOnly) -> Outcome {
1696 match event {
1697 ct_event!(mouse down Left for column, row) => {
1698 focus_debug!(self.core.log, "mouse down {},{}", column, row);
1699 if self.focus_at(*column, *row) {
1700 focus_debug!(
1701 self.core.log,
1702 " -> {:?}",
1703 self.focused().map(|v| v.name().to_string())
1704 );
1705 Outcome::Changed
1706 } else {
1707 self.reset_lost_gained();
1708 Outcome::Continue
1709 }
1710 }
1711 _ => {
1712 self.reset_lost_gained();
1713 Outcome::Continue
1714 }
1715 }
1716 }
1717}
1718
1719#[inline(always)]
1721pub fn handle_focus(focus: &mut Focus, event: &crossterm::event::Event) -> Outcome {
1722 HandleEvent::handle(focus, event, Regular)
1723}