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#[derive(Default, Debug, Clone)]
16pub struct Focus {
17 last: FocusCore,
18 core: FocusCore,
19}
20
21macro_rules! focus_debug {
22 ($core:expr, $($arg:tt)+) => {
23 if $core.log.get() {
24 log::log!(log::Level::Debug, $($arg)+);
25 }
26 }
27}
28
29macro_rules! focus_fail {
30 ($core:expr, $($arg:tt)+) => {
31 if $core.log.get() {
32 log::log!(log::Level::Debug, $($arg)+);
33 }
34 if $core.insta_panic.get() {
35 panic!($($arg)+)
36 }
37 }
38}
39
40impl Focus {
41 pub fn enable_log(&self) {
43 self.core.log.set(true);
44 self.last.log.set(true);
45 }
46
47 pub fn disable_log(&self) {
49 self.core.log.set(false);
50 self.last.log.set(false);
51 }
52
53 pub fn enable_panic(&self) {
56 self.core.insta_panic.set(true);
57 self.last.insta_panic.set(true);
58 }
59
60 pub fn disable_panic(&self) {
62 self.core.insta_panic.set(false);
63 self.last.insta_panic.set(false);
64 }
65
66 pub fn flip_focus(
71 &self,
72 widget_state: &'_ dyn HasFocus,
73 flip_focus: &'_ mut Option<FocusFlag>,
74 ) {
75 focus_debug!(
76 self.core,
77 "flip-focus {:?} {:?}",
78 widget_state.focus().name(),
79 flip_focus
80 );
81 let flag = widget_state.focus();
82 if self.core.is_widget(&flag) {
83 if flag.is_focused() {
84 if let Some(flip_focus) = flip_focus {
85 self.focus(flip_focus);
86 } else {
87 focus_fail!(self.core, " => no previous widget");
88 }
89 } else {
90 *flip_focus = self.focused();
91 self.focus(&flag);
92 }
93 } else if self.core.is_container(&flag) {
94 if flag.is_focused() {
95 if let Some(flip_focus) = flip_focus {
96 self.focus(flip_focus);
97 } else {
98 focus_fail!(self.core, " => no previous widget");
99 }
100 } else {
101 self.core.first_container(&flag);
102 }
103 } else {
104 focus_fail!(self.core, " => not a valid widget");
105 }
106 }
107
108 #[inline]
121 pub fn focus(&self, widget_state: &'_ dyn HasFocus) {
122 focus_debug!(self.core, "focus {:?}", widget_state.focus().name());
123 let flag = widget_state.focus();
124 if self.core.is_widget(&flag) {
125 if let Some(n) = self.core.index_of(&flag) {
126 self.core.focus_idx(n, true);
127 } else {
128 panic!(" => invalid widget?");
129 }
130 } else if self.core.is_container(&flag) {
131 self.core.first_container(&flag);
132 } else {
133 focus_fail!(self.core, " => not a valid widget");
134 }
135 }
136
137 #[inline]
154 pub fn by_widget_id(&self, widget_id: usize) {
155 let widget_state = self.core.find_widget_id(widget_id);
156 focus_debug!(self.core, "focus {:?} -> {:?}", widget_id, widget_state);
157 let Some(widget_state) = widget_state else {
158 return;
159 };
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, true);
165 } else {
166 panic!(" => invalid widget");
167 }
168 } else if self.core.is_container(&flag) {
169 self.core.first_container(&flag);
170 } else {
171 focus_fail!(self.core, " => not a valid widget");
172 }
173 }
174
175 #[inline(always)]
184 pub fn first(&self) {
185 focus_debug!(self.core, "focus first");
186 self.core.first();
187 }
188
189 #[deprecated(since = "1.1.2", note = "use focus() instead")]
190 pub fn first_in(&self, container: &'_ dyn HasFocus) {
191 self.focus(container);
192 }
193
194 #[inline(always)]
199 pub fn none(&self) {
200 focus_debug!(self.core, "focus none");
201 self.core.none();
202 focus_debug!(self.core, " -> done");
203 }
204
205 #[inline(always)]
216 pub fn future(&self, widget_state: &'_ dyn HasFocus) {
217 focus_debug!(self.core, "focus {:?}", widget_state.focus().name());
218 let flag = widget_state.focus();
219 if self.core.is_widget(&flag) {
220 focus_fail!(
221 self.core,
222 " => widget is part of focus. use focus() instead"
223 );
224 } else if self.core.is_container(&flag) {
225 focus_debug!(self.core, "future container");
226 let had_focus = flag.get();
227 flag.set(true);
228 if !had_focus {
229 flag.set_gained(true);
230 flag.call_on_gained();
231 }
232 focus_debug!(self.core, " -> done");
233 } else {
234 focus_debug!(self.core, "future focus");
235 self.core.none();
236 flag.set(true);
237 flag.set_gained(true);
238 flag.call_on_gained();
239 focus_debug!(self.core, " -> done");
240 }
241 }
242
243 #[inline(always)]
252 pub fn focus_at(&self, col: u16, row: u16) -> bool {
253 focus_debug!(self.core, "focus at {},{}", col, row);
254 match self.navigation() {
255 Some(Navigation::Lock) => {
256 focus_debug!(self.core, " -> locked");
257 false
258 }
259 _ => self.core.focus_at(col, row),
260 }
261 }
262
263 #[inline]
273 pub fn next(&self) -> bool {
274 match self.navigation() {
275 None => {
276 self.first();
277 true
278 }
279 Some(Navigation::Leave | Navigation::ReachLeaveBack | Navigation::Regular) => {
280 focus_debug!(
281 self.core,
282 "next after {:?}",
283 self.core
284 .focused()
285 .map(|v| v.name())
286 .unwrap_or("None".into())
287 );
288 self.core.next()
289 }
290 v => {
291 focus_debug!(
292 self.core,
293 "next after {:?}, but navigation says {:?}",
294 self.core
295 .focused()
296 .map(|v| v.name().to_string())
297 .unwrap_or("None".into()),
298 v
299 );
300 false
301 }
302 }
303 }
304
305 #[inline]
315 pub fn prev(&self) -> bool {
316 match self.navigation() {
317 None => {
318 self.first();
319 true
320 }
321 Some(Navigation::Leave | Navigation::ReachLeaveFront | Navigation::Regular) => {
322 focus_debug!(
323 self.core,
324 "prev before {:?}",
325 self.core
326 .focused()
327 .map(|v| v.name().to_string())
328 .unwrap_or("None".into())
329 );
330 self.core.prev()
331 }
332 v => {
333 focus_debug!(
334 self.core,
335 "prev before {:?}, but navigation says {:?}",
336 self.core
337 .focused()
338 .map(|v| v.name().to_string())
339 .unwrap_or("None".into()),
340 v
341 );
342 false
343 }
344 }
345 }
346
347 #[inline]
359 pub fn next_force(&self) -> bool {
360 match self.navigation() {
361 None => {
362 self.first();
363 true
364 }
365 Some(
366 Navigation::Leave
367 | Navigation::Reach
368 | Navigation::ReachLeaveFront
369 | Navigation::ReachLeaveBack
370 | Navigation::Regular,
371 ) => {
372 focus_debug!(
373 self.core,
374 "force next after {:?}",
375 self.core.focused().map(|v| v.name().to_string())
376 );
377 self.core.next()
378 }
379 v => {
380 focus_debug!(
381 self.core,
382 "force next after {:?}, but navigation says {:?}",
383 self.core.focused().map(|v| v.name().to_string()),
384 v
385 );
386 false
387 }
388 }
389 }
390
391 #[inline]
403 pub fn prev_force(&self) -> bool {
404 match self.navigation() {
405 None => {
406 self.first();
407 true
408 }
409 Some(
410 Navigation::Leave
411 | Navigation::Reach
412 | Navigation::ReachLeaveFront
413 | Navigation::ReachLeaveBack
414 | Navigation::Regular,
415 ) => {
416 focus_debug!(
417 self.core,
418 "force prev before {:?}",
419 self.core.focused().map(|v| v.name().to_string())
420 );
421 self.core.prev()
422 }
423 v => {
424 focus_debug!(
425 self.core,
426 "force prev before {:?}, but navigation says {:?}",
427 self.core.focused().map(|v| v.name().to_string()),
428 v
429 );
430 false
431 }
432 }
433 }
434
435 #[inline(always)]
437 pub fn is_valid_widget(&self, widget_state: &'_ dyn HasFocus) -> bool {
438 self.core.is_widget(&widget_state.focus())
439 }
440
441 #[inline(always)]
443 pub fn is_valid_container(&self, widget_state: &'_ dyn HasFocus) -> bool {
444 self.core.is_container(&widget_state.focus())
445 }
446
447 #[inline(always)]
452 pub fn focused(&self) -> Option<FocusFlag> {
453 self.core.focused()
454 }
455
456 #[inline(always)]
461 pub fn focused_widget_id(&self) -> Option<usize> {
462 self.core.focused().map(|v| v.id())
463 }
464
465 #[inline(always)]
467 pub fn focused_name(&self) -> Option<String> {
468 self.core.focused().map(|v| v.name().to_string())
469 }
470
471 #[inline(always)]
473 pub fn navigation(&self) -> Option<Navigation> {
474 self.core.navigation()
475 }
476
477 #[inline(always)]
482 pub fn lost_focus(&self) -> Option<FocusFlag> {
483 self.core.lost_focus()
484 }
485
486 #[inline(always)]
491 pub fn gained_focus(&self) -> Option<FocusFlag> {
492 self.core.gained_focus()
493 }
494
495 #[inline]
510 pub fn focus_no_lost(&self, widget_state: &'_ dyn HasFocus) {
511 focus_debug!(self.core, "focus no_lost {:?}", widget_state.focus().name());
512 let flag = widget_state.focus();
513 if self.core.is_widget(&flag) {
514 if let Some(n) = self.core.index_of(&flag) {
515 self.core.focus_idx(n, false);
516 } else {
517 panic!(" => invalid widget");
518 }
519 } else if self.core.is_container(&flag) {
520 self.core.first_container(&flag);
521 } else {
522 focus_fail!(self.core, " => not a valid widget");
523 }
524 }
525
526 #[inline]
538 pub fn expel_focus(&self, widget_state: &'_ dyn HasFocus) {
539 focus_debug!(
540 self.core,
541 "expel from widget {:?}",
542 widget_state.focus().name()
543 );
544 let flag = widget_state.focus();
545 if self.core.is_widget(&flag) {
546 if self.core.index_of(&flag).is_some() {
547 if widget_state.is_focused() {
548 self.core.next();
549 if widget_state.is_focused() {
550 focus_debug!(self.core, " -> no other focus, cleared");
551 flag.clear();
552 } else {
553 focus_debug!(self.core, " -> expelled");
554 }
555 } else {
556 focus_debug!(self.core, " => widget not focused");
557 }
558 } else {
559 panic!(" => invalid widget");
560 }
561 } else if self.core.is_container(&flag) {
562 if flag.is_focused() {
563 self.core.expel_container(flag);
564 } else {
565 focus_debug!(self.core, " => container not focused");
566 }
567 } else {
568 focus_fail!(self.core, " => not a valid widget");
569 }
570 }
571
572 pub fn remove_container(&mut self, container: &'_ dyn HasFocus) {
580 focus_debug!(
581 self.core,
582 "focus remove container {:?} ",
583 container.focus().name()
584 );
585 let flag = container.focus();
586 if self.core.is_container(&flag) {
587 if let Some((cidx, _)) = self.core.container_index_of(&flag) {
588 self.core.remove_container(cidx).reset();
589 focus_debug!(self.core, " -> removed");
590 } else {
591 panic!(" => invalid container?");
592 }
593 } else {
594 focus_fail!(self.core, " => no container flag");
595 }
596 }
597
598 pub fn update_container(&mut self, container: &'_ dyn HasFocus) {
609 focus_debug!(
610 self.core,
611 "focus update container {:?} ",
612 container.focus().name()
613 );
614 let flag = container.focus();
615 if self.core.is_container(&flag) {
616 if let Some((cidx, range)) = self.core.container_index_of(&flag) {
617 let removed = self.core.remove_container(cidx);
618
619 let mut b = FocusBuilder::new(Some(Focus {
620 last: Default::default(),
621 core: removed,
622 }));
623 b.widget(container);
624 let insert = b.build();
625
626 self.core.insert_container(range.start, cidx, insert.core);
627
628 focus_debug!(self.core, " -> updated");
629 } else {
630 panic!(" => invalid container?");
631 }
632 } else {
633 focus_fail!(self.core, " => no container flag");
634 }
635 }
636
637 pub fn replace_container(&mut self, container: &'_ dyn HasFocus, new: &'_ dyn HasFocus) {
651 focus_debug!(
652 self.core,
653 "focus replace container {:?} with {:?} ",
654 container.focus().name(),
655 new.focus().name()
656 );
657 let flag = container.focus();
658 if self.core.is_container(&flag) {
659 if let Some((cidx, range)) = self.core.container_index_of(&flag) {
660 let removed = self.core.remove_container(cidx);
661
662 let mut b = FocusBuilder::new(Some(Focus {
663 last: Default::default(),
664 core: removed,
665 }));
666 b.widget(new);
667 let insert = b.build();
668
669 self.core.insert_container(range.start, cidx, insert.core);
670
671 focus_debug!(self.core, " -> replaced");
672 } else {
673 panic!(" => invalid container");
674 }
675 } else {
676 focus_fail!(self.core, " => no container flag");
677 }
678 }
679
680 #[inline(always)]
687 pub fn reset_lost_gained(&self) {
688 self.core.reset_lost_gained();
689 }
690
691 #[allow(clippy::type_complexity)]
693 pub fn clone_destruct(
694 &self,
695 ) -> (
696 Vec<FocusFlag>,
697 Vec<bool>,
698 Vec<(Rect, u16)>,
699 Vec<Navigation>,
700 Vec<(FocusFlag, (Rect, u16), Range<usize>)>,
701 ) {
702 self.core.clone_destruct()
703 }
704}
705
706mod core {
707 use crate::{Focus, FocusFlag, HasFocus, Navigation};
708 use fxhash::FxBuildHasher;
709 use ratatui::layout::Rect;
710 use std::cell::Cell;
711 use std::collections::HashSet;
712 use std::ops::Range;
713
714 #[derive(Debug, Default)]
716 pub struct FocusBuilder {
717 last: FocusCore,
718
719 log: Cell<bool>,
720 insta_panic: Cell<bool>,
721
722 z_base: u16,
730
731 focus_ids: HashSet<usize, FxBuildHasher>,
733 focus_flags: Vec<FocusFlag>,
734 duplicate: Vec<bool>,
735 areas: Vec<(Rect, u16)>,
736 navigable: Vec<Navigation>,
737 container_ids: HashSet<usize, FxBuildHasher>,
738 containers: Vec<(Container, Range<usize>)>,
739 }
740
741 impl FocusBuilder {
742 pub fn new(last: Option<Focus>) -> FocusBuilder {
750 if let Some(mut last) = last {
751 last.last.clear();
753
754 Self {
755 last: last.core,
756 log: Default::default(),
757 insta_panic: Default::default(),
758 z_base: 0,
759 focus_ids: last.last.focus_ids,
760 focus_flags: last.last.focus_flags,
761 duplicate: last.last.duplicate,
762 areas: last.last.areas,
763 navigable: last.last.navigable,
764 container_ids: last.last.container_ids,
765 containers: last.last.containers,
766 }
767 } else {
768 Self {
769 last: FocusCore::default(),
770 log: Default::default(),
771 insta_panic: Default::default(),
772 z_base: Default::default(),
773 focus_ids: Default::default(),
774 focus_flags: Default::default(),
775 duplicate: Default::default(),
776 areas: Default::default(),
777 navigable: Default::default(),
778 container_ids: Default::default(),
779 containers: Default::default(),
780 }
781 }
782 }
783
784 pub fn log_build_for(container: &dyn HasFocus) -> Focus {
786 let mut b = FocusBuilder::new(None);
787 b.enable_log();
788 b.widget(container);
789 b.build()
790 }
791
792 pub fn build_for(container: &dyn HasFocus) -> Focus {
805 let mut b = FocusBuilder::new(None);
806 b.widget(container);
807 b.build()
808 }
809
810 pub fn log_rebuild_for(container: &dyn HasFocus, old: Option<Focus>) -> Focus {
812 let mut b = FocusBuilder::new(old);
813 b.enable_log();
814 b.widget(container);
815 b.build()
816 }
817
818 pub fn rebuild_for(container: &dyn HasFocus, old: Option<Focus>) -> Focus {
825 let mut b = FocusBuilder::new(old);
826 b.widget(container);
827 b.build()
828 }
829
830 pub fn enable_log(&self) {
832 self.log.set(true);
833 }
834
835 pub fn disable_log(&self) {
837 self.log.set(false);
838 }
839
840 pub fn enable_panic(&self) {
842 self.insta_panic.set(true);
843 }
844
845 pub fn disable_panic(&self) {
847 self.insta_panic.set(false);
848 }
849
850 pub fn widget(&mut self, widget: &dyn HasFocus) -> &mut Self {
852 widget.build(self);
853 self
854 }
855
856 #[allow(clippy::collapsible_else_if)]
865 pub fn widget_navigate(
866 &mut self,
867 widget: &dyn HasFocus,
868 navigation: Navigation,
869 ) -> &mut Self {
870 widget.build(self);
871
872 let widget_flag = widget.focus();
873 if let Some(idx) = self.focus_flags.iter().position(|v| *v == widget_flag) {
875 focus_debug!(
876 self,
877 "override navigation for {:?} with {:?}",
878 widget_flag,
879 navigation
880 );
881
882 self.navigable[idx] = navigation;
883 } else {
884 if self.container_ids.contains(&widget_flag.widget_id()) {
885 focus_fail!(
886 self,
887 "FAIL to override navigation for {:?}. This is a container.",
888 widget_flag,
889 );
890 } else {
891 focus_fail!(
892 self,
893 "FAIL to override navigation for {:?}. Widget doesn't use this focus-flag",
894 widget_flag,
895 );
896 }
897 }
898
899 self
900 }
901
902 #[inline]
904 pub fn widgets<const N: usize>(&mut self, widgets: [&dyn HasFocus; N]) -> &mut Self {
905 for widget in widgets {
906 widget.build(self);
907 }
908 self
909 }
910
911 #[must_use]
924 pub fn start(&mut self, container: &dyn HasFocus) -> FocusFlag {
925 self.start_with_flags(container.focus(), container.area(), container.area_z())
926 }
927
928 pub fn end(&mut self, tag: FocusFlag) {
930 focus_debug!(self, "end container {:?}", tag);
931 assert!(self.container_ids.contains(&tag.widget_id()));
932
933 for (c, r) in self.containers.iter_mut().rev() {
934 if c.container_flag != tag {
935 if !c.complete {
936 panic!("FocusBuilder: Unclosed container {:?}", c.container_flag);
937 }
938 } else {
939 r.end = self.focus_flags.len();
940 c.complete = true;
941
942 focus_debug!(self, "container range {:?}", r);
943
944 self.z_base -= c.delta_z;
945
946 break;
947 }
948 }
949 }
950
951 pub fn leaf_widget(&mut self, widget: &dyn HasFocus) -> &mut Self {
963 self.widget_with_flags(
964 widget.focus(),
965 widget.area(),
966 widget.area_z(),
967 widget.navigable(),
968 );
969 self
970 }
971
972 pub fn widget_with_flags(
985 &mut self,
986 focus: FocusFlag,
987 area: Rect,
988 area_z: u16,
989 navigable: Navigation,
990 ) {
991 let duplicate = self.focus_ids.contains(&focus.widget_id());
992
993 if duplicate {
996 if !matches!(navigable, Navigation::Mouse | Navigation::None) {
997 focus_debug!(self, "{:#?}", self);
998 panic!(
999 "Duplicate flag is only allowed if the second call uses Navigation::Mouse|Navigation::None. Was {:?}.",
1000 focus
1001 )
1002 }
1003 }
1004
1005 focus_debug!(self, "widget {:?}", focus);
1006
1007 self.focus_ids.insert(focus.widget_id());
1008 self.focus_flags.push(focus);
1009 self.duplicate.push(duplicate);
1010 self.areas.push((area, self.z_base + area_z));
1011 self.navigable.push(navigable);
1012 }
1013
1014 #[must_use]
1023 pub fn start_with_flags(
1024 &mut self,
1025 container_flag: FocusFlag,
1026 area: Rect,
1027 area_z: u16,
1028 ) -> FocusFlag {
1029 focus_debug!(self, "start container {:?}", container_flag);
1030
1031 assert!(!self.container_ids.contains(&container_flag.widget_id()));
1033
1034 self.z_base += area_z;
1035
1036 let len = self.focus_flags.len();
1037 self.container_ids.insert(container_flag.widget_id());
1038 self.containers.push((
1039 Container {
1040 container_flag: container_flag.clone(),
1041 area: (area, self.z_base),
1042 delta_z: area_z,
1043 complete: false,
1044 },
1045 len..len,
1046 ));
1047
1048 container_flag
1049 }
1050
1051 pub fn build(mut self) -> Focus {
1057 for v in &self.last.focus_flags {
1059 if !self.focus_ids.contains(&v.widget_id()) {
1060 v.clear();
1061 }
1062 }
1063 for (v, _) in &self.last.containers {
1064 let have_container = self
1065 .containers
1066 .iter()
1067 .any(|(c, _)| v.container_flag == c.container_flag);
1068 if !have_container {
1069 v.container_flag.clear();
1070 }
1071 }
1072 self.last.clear();
1073
1074 for (c, _) in self.containers.iter_mut().rev() {
1076 if !c.complete {
1077 panic!("FocusBuilder: Unclosed container {:?}", c.container_flag);
1078 }
1079 }
1080
1081 let log = self.last.log.get();
1082 let insta_panic = self.last.insta_panic.get();
1083
1084 Focus {
1085 last: self.last,
1086 core: FocusCore {
1087 log: Cell::new(log),
1088 insta_panic: Cell::new(insta_panic),
1089 focus_ids: self.focus_ids,
1090 focus_flags: self.focus_flags,
1091 duplicate: self.duplicate,
1092 areas: self.areas,
1093 navigable: self.navigable,
1094 container_ids: self.container_ids,
1095 containers: self.containers,
1096 },
1097 }
1098 }
1099 }
1100
1101 #[derive(Debug, Clone)]
1103 struct Container {
1104 container_flag: FocusFlag,
1108 area: (Rect, u16),
1111 delta_z: u16,
1113 complete: bool,
1115 }
1116
1117 #[derive(Debug, Default, Clone)]
1119 pub(super) struct FocusCore {
1120 pub(super) log: Cell<bool>,
1122 pub(super) insta_panic: Cell<bool>,
1123
1124 focus_ids: HashSet<usize, FxBuildHasher>,
1126 focus_flags: Vec<FocusFlag>,
1128 duplicate: Vec<bool>,
1131 areas: Vec<(Rect, u16)>,
1134 navigable: Vec<Navigation>,
1137 container_ids: HashSet<usize, FxBuildHasher>,
1139 containers: Vec<(Container, Range<usize>)>,
1144 }
1145
1146 impl FocusCore {
1147 pub(super) fn clear(&mut self) {
1149 self.focus_ids.clear();
1150 self.focus_flags.clear();
1151 self.duplicate.clear();
1152 self.areas.clear();
1153 self.navigable.clear();
1154 self.container_ids.clear();
1155 self.containers.clear();
1156 }
1157
1158 pub(super) fn find_widget_id(&self, widget_id: usize) -> Option<FocusFlag> {
1160 self.focus_flags
1161 .iter()
1162 .find(|v| widget_id == v.widget_id())
1163 .cloned()
1164 }
1165
1166 pub(super) fn is_widget(&self, focus_flag: &FocusFlag) -> bool {
1168 self.focus_ids.contains(&focus_flag.widget_id())
1169 }
1170
1171 pub(super) fn index_of(&self, focus_flag: &FocusFlag) -> Option<usize> {
1173 self.focus_flags
1174 .iter()
1175 .enumerate()
1176 .find(|(_, f)| *f == focus_flag)
1177 .map(|(idx, _)| idx)
1178 }
1179
1180 pub(super) fn is_container(&self, focus_flag: &FocusFlag) -> bool {
1182 self.container_ids.contains(&focus_flag.widget_id())
1183 }
1184
1185 pub(super) fn container_index_of(
1187 &self,
1188 container_flag: &FocusFlag,
1189 ) -> Option<(usize, Range<usize>)> {
1190 self.containers
1191 .iter()
1192 .enumerate()
1193 .find(|(_, (c, _))| &c.container_flag == container_flag)
1194 .map(|(idx, (_, range))| (idx, range.clone()))
1195 }
1196
1197 pub(super) fn insert_container(
1202 &mut self,
1203 idx: usize,
1204 cidx: usize,
1205 mut container: FocusCore,
1206 ) {
1207 for c in &self.focus_flags {
1208 for d in &container.focus_flags {
1209 assert_ne!(c, d);
1210 }
1211 }
1212
1213 let start = idx;
1215 let end = idx + container.focus_flags.len();
1216
1217 self.focus_ids.extend(container.focus_ids.iter());
1218 self.focus_flags
1219 .splice(idx..idx, container.focus_flags.drain(..));
1220 self.duplicate
1221 .splice(idx..idx, container.duplicate.drain(..));
1222 self.areas.splice(idx..idx, container.areas.drain(..));
1223 self.navigable
1224 .splice(idx..idx, container.navigable.drain(..));
1225
1226 for (_, r) in &mut self.containers {
1228 *r = Self::expand(start..end, r.clone());
1229 }
1230 self.containers.splice(
1232 cidx..cidx,
1233 container
1234 .containers
1235 .drain(..)
1236 .map(|(c, r)| (c, Self::shift(start, r))),
1237 );
1238 self.container_ids.extend(container.container_ids.iter());
1239 }
1240
1241 pub(super) fn remove_container(&mut self, cidx: usize) -> FocusCore {
1244 let crange = self.containers[cidx].1.clone();
1245
1246 let focus_flags = self.focus_flags.drain(crange.clone()).collect::<Vec<_>>();
1248 let mut focus_ids = HashSet::<_, FxBuildHasher>::default();
1249 for f in focus_flags.iter() {
1250 self.focus_ids.remove(&f.widget_id());
1251 focus_ids.insert(f.widget_id());
1252 }
1253 let duplicate = self.duplicate.drain(crange.clone()).collect::<Vec<_>>();
1254 let areas = self.areas.drain(crange.clone()).collect::<Vec<_>>();
1255 let navigable = self.navigable.drain(crange.clone()).collect::<Vec<_>>();
1256 let sub_containers = self
1257 .containers
1258 .iter()
1259 .filter(|(_, r)| r.start >= crange.start && r.end <= crange.end)
1260 .cloned()
1261 .collect::<Vec<_>>();
1262 self.containers
1264 .retain(|(_, r)| !(r.start >= crange.start && r.end <= crange.end));
1265 let mut sub_container_ids: HashSet<usize, FxBuildHasher> = HashSet::default();
1266 for (sc, _) in sub_containers.iter() {
1267 self.container_ids.remove(&sc.container_flag.widget_id());
1268 sub_container_ids.insert(sc.container_flag.widget_id());
1269 }
1270
1271 for (_, r) in &mut self.containers {
1273 *r = Self::shrink(crange.start..crange.end, r.clone());
1274 }
1275
1276 FocusCore {
1277 log: Cell::new(false),
1278 insta_panic: Cell::new(false),
1279 focus_ids,
1280 focus_flags,
1281 duplicate,
1282 areas,
1283 navigable,
1284 container_ids: sub_container_ids,
1285 containers: sub_containers,
1286 }
1287 }
1288
1289 fn shift(n: usize, range: Range<usize>) -> Range<usize> {
1291 range.start + n..range.end + n
1292 }
1293
1294 fn expand(insert: Range<usize>, mut range: Range<usize>) -> Range<usize> {
1296 let len = insert.end - insert.start;
1297
1298 if range.start >= insert.start {
1299 range.start += len;
1300 }
1301 if range.end > insert.start {
1302 range.end += len;
1303 }
1304 range
1305 }
1306
1307 fn shrink(remove: Range<usize>, mut range: Range<usize>) -> Range<usize> {
1309 let len = remove.end - remove.start;
1310
1311 if range.start < remove.start {
1312 } else if range.start >= remove.start && range.start <= remove.end {
1314 range.start = remove.start;
1315 } else {
1316 range.start -= len;
1317 }
1318
1319 if range.end < remove.start {
1320 } else if range.end >= remove.start && range.end <= remove.end {
1322 range.end = remove.start;
1323 } else {
1324 range.end -= len;
1325 }
1326
1327 range
1328 }
1329
1330 fn __start_change(&self, set_lost: bool) {
1333 for (f, duplicate) in self.focus_flags.iter().zip(self.duplicate.iter()) {
1334 if *duplicate {
1335 continue;
1337 }
1338 if set_lost {
1339 f.set_lost(f.get());
1340 } else {
1341 f.set_lost(false);
1342 }
1343 f.set_gained(false);
1344 f.set(false);
1345 }
1346 }
1347
1348 fn __focus(&self, n: usize, set_lost: bool) -> bool {
1351 if let Some(f) = self.focus_flags.get(n) {
1352 focus_debug!(self, " -> focus {}:{:?}", n, f.name());
1353 f.set(true);
1354 if set_lost {
1355 if f.lost() {
1356 f.set_lost(false);
1359 f.set_gained(false);
1360 false
1361 } else {
1362 f.set_gained(true);
1363 true
1364 }
1365 } else {
1366 false
1367 }
1368 } else {
1369 false
1370 }
1371 }
1372
1373 #[allow(clippy::collapsible_if)]
1375 fn __accumulate(&self) {
1376 for (n, f) in self.focus_flags.iter().enumerate() {
1377 if f.gained() && !self.duplicate[n] {
1378 if let Some(on_gained_cb) = f.0.on_gained.borrow().as_ref() {
1379 focus_debug!(self, " -> notify_on_gained {}:{:?}", n, f.name());
1380 on_gained_cb();
1381 }
1382 }
1383 if f.lost() && !self.duplicate[n] {
1384 if let Some(on_lost_cb) = f.0.on_lost.borrow().as_ref() {
1385 focus_debug!(self, " -> notify_on_lost {}:{:?}", n, f.name());
1386 on_lost_cb();
1387 }
1388 }
1389 }
1390
1391 for (f, r) in &self.containers {
1392 let mut any_gained = false;
1393 let mut any_lost = false;
1394 let mut any_focused = false;
1395
1396 for idx in r.clone() {
1397 any_gained |= self.focus_flags[idx].gained();
1398 any_lost |= self.focus_flags[idx].lost();
1399 any_focused |= self.focus_flags[idx].get();
1400 }
1401
1402 f.container_flag.set(any_focused);
1403 f.container_flag.set_lost(any_lost && !any_gained);
1404 if any_lost && !any_gained {
1405 if let Some(on_lost_cb) = f.container_flag.0.on_lost.borrow().as_ref() {
1406 focus_debug!(
1407 self,
1408 "-> notify_on_lost container {:?}",
1409 f.container_flag.name()
1410 );
1411 on_lost_cb();
1412 }
1413 }
1414 f.container_flag.set_gained(any_gained && !any_lost);
1415 if any_gained && !any_lost {
1416 if let Some(on_gained_cb) = f.container_flag.0.on_gained.borrow().as_ref() {
1417 focus_debug!(
1418 self,
1419 "-> notify_on_gained container {:?}",
1420 f.container_flag.name()
1421 );
1422 on_gained_cb();
1423 }
1424 }
1425 }
1426 }
1427
1428 pub(super) fn reset(&self) {
1430 for f in self.focus_flags.iter() {
1431 f.set(false);
1432 f.set_lost(false);
1433 f.set_gained(false);
1434 }
1435 for (f, _) in self.containers.iter() {
1436 f.container_flag.set(false);
1437 f.container_flag.set_gained(false);
1438 f.container_flag.set_lost(false);
1439 }
1440 }
1441
1442 pub(super) fn reset_lost_gained(&self) {
1444 for f in self.focus_flags.iter() {
1445 f.set_lost(false);
1446 f.set_gained(false);
1447 }
1448 for (f, _) in self.containers.iter() {
1449 f.container_flag.set_gained(false);
1450 f.container_flag.set_lost(false);
1451 }
1452 }
1453
1454 pub(super) fn first(&self) {
1456 if let Some(n) = self.first_navigable(0) {
1457 self.__start_change(true);
1458 self.__focus(n, true);
1459 self.__accumulate();
1460 } else {
1461 focus_debug!(self, " -> no navigable widget");
1462 }
1463 }
1464
1465 pub(super) fn none(&self) {
1467 self.__start_change(true);
1468 self.__accumulate();
1469 }
1470
1471 pub(super) fn first_container(&self, container: &FocusFlag) {
1473 if let Some((_idx, range)) = self.container_index_of(container) {
1474 if let Some(n) = self.first_navigable(range.start) {
1475 if n < range.end {
1476 self.__start_change(true);
1477 self.__focus(n, true);
1478 self.__accumulate();
1479 } else {
1480 focus_debug!(self, " -> no navigable widget for container");
1481 }
1482 } else {
1483 focus_debug!(self, " -> no navigable widget");
1484 }
1485 } else {
1486 focus_fail!(self, " => container not found");
1487 }
1488 }
1489
1490 pub(super) fn focus_idx(&self, n: usize, set_lost: bool) {
1492 self.__start_change(set_lost);
1493 self.__focus(n, set_lost);
1494 self.__accumulate();
1495 }
1496
1497 pub(super) fn focus_at(&self, col: u16, row: u16) -> bool {
1501 let pos = (col, row).into();
1502
1503 enum ZOrder {
1504 Widget(usize),
1505 Container(usize),
1506 }
1507
1508 let mut z_order: Option<(ZOrder, u16)> = None;
1510 for (idx, (sub, _)) in self.containers.iter().enumerate() {
1513 if sub.area.0.contains(pos) {
1514 focus_debug!(
1515 self,
1516 " container area-match {:?}",
1517 sub.container_flag.name()
1518 );
1519
1520 z_order = if let Some(zz) = z_order {
1521 if zz.1 <= sub.area.1 {
1522 Some((ZOrder::Container(idx), sub.area.1))
1523 } else {
1524 Some(zz)
1525 }
1526 } else {
1527 Some((ZOrder::Container(idx), sub.area.1))
1528 };
1529 }
1530 }
1531 for (idx, area) in self.areas.iter().enumerate() {
1533 if area.0.contains(pos) {
1534 focus_debug!(self, " area-match {:?}", self.focus_flags[idx].name());
1535
1536 z_order = if let Some(zz) = z_order {
1537 if zz.1 <= area.1 {
1538 Some((ZOrder::Widget(idx), area.1))
1539 } else {
1540 Some(zz)
1541 }
1542 } else {
1543 Some((ZOrder::Widget(idx), area.1))
1544 };
1545 }
1546 }
1547
1548 if let Some((idx, _)) = z_order {
1550 match idx {
1551 ZOrder::Widget(idx) => {
1552 if self.navigable[idx] != Navigation::None {
1553 self.__start_change(true);
1554 let r = self.__focus(idx, true);
1555 self.__accumulate();
1556 return r;
1557 } else {
1558 focus_debug!(
1559 self,
1560 " -> not mouse reachable {:?}",
1561 self.focus_flags[idx].name()
1562 );
1563 return false;
1564 }
1565 }
1566 ZOrder::Container(idx) => {
1567 let range = &self.containers[idx].1;
1568 if let Some(n) = self.first_navigable(range.start) {
1569 self.__start_change(true);
1570 let r = self.__focus(n, true);
1571 self.__accumulate();
1572 return r;
1573 }
1574 }
1575 }
1576 }
1577
1578 focus_debug!(self, " -> no widget at pos");
1580
1581 false
1582 }
1583
1584 pub(super) fn expel_container(&self, flag: FocusFlag) -> bool {
1586 if let Some((_idx, range)) = self.container_index_of(&flag) {
1587 self.__start_change(true);
1588 let n = self.next_navigable(range.end);
1589 self.__focus(n, true);
1590 self.__accumulate();
1591
1592 if flag.is_focused() {
1594 focus_debug!(self, " -> focus not usable. cleared");
1595 self.none();
1596 } else {
1597 focus_debug!(self, " -> expelled.");
1598 }
1599 true
1600 } else {
1601 focus_fail!(self, " => container not found");
1602 false
1603 }
1604 }
1605
1606 pub(super) fn next(&self) -> bool {
1608 self.__start_change(true);
1609 for (n, p) in self.focus_flags.iter().enumerate() {
1610 if p.lost() {
1611 let n = self.next_navigable(n);
1612 self.__focus(n, true);
1613 self.__accumulate();
1614 return true;
1615 }
1616 }
1617 if let Some(n) = self.first_navigable(0) {
1618 focus_debug!(
1619 self,
1620 " use first_navigable {}:{:?}",
1621 n,
1622 self.focus_flags[n].name()
1623 );
1624 self.__focus(n, true);
1625 self.__accumulate();
1626 return true;
1627 }
1628 focus_debug!(self, " -> no next");
1629 false
1630 }
1631
1632 pub(super) fn prev(&self) -> bool {
1634 self.__start_change(true);
1635 for (i, p) in self.focus_flags.iter().enumerate() {
1636 if p.lost() {
1637 let n = self.prev_navigable(i);
1638 self.__focus(n, true);
1639 self.__accumulate();
1640 return true;
1641 }
1642 }
1643 if let Some(n) = self.first_navigable(0) {
1644 focus_debug!(
1645 self,
1646 " use first_navigable {}:{:?}",
1647 n,
1648 self.focus_flags[n].name()
1649 );
1650 self.__focus(n, true);
1651 self.__accumulate();
1652 return true;
1653 }
1654 focus_debug!(self, " -> no prev");
1655 false
1656 }
1657
1658 pub(super) fn navigation(&self) -> Option<Navigation> {
1660 self.focus_flags
1661 .iter()
1662 .enumerate()
1663 .find(|(_, v)| v.get())
1664 .map(|(i, _)| self.navigable[i])
1665 }
1666
1667 pub(super) fn focused(&self) -> Option<FocusFlag> {
1669 self.focus_flags.iter().find(|v| v.get()).cloned()
1670 }
1671
1672 pub(super) fn lost_focus(&self) -> Option<FocusFlag> {
1674 self.focus_flags.iter().find(|v| v.lost()).cloned()
1675 }
1676
1677 pub(super) fn gained_focus(&self) -> Option<FocusFlag> {
1679 self.focus_flags.iter().find(|v| v.gained()).cloned()
1680 }
1681
1682 fn first_navigable(&self, start: usize) -> Option<usize> {
1684 focus_debug!(
1685 self,
1686 "first navigable, start at {}:{:?} ",
1687 start,
1688 if start < self.focus_flags.len() {
1689 self.focus_flags[start].name()
1690 } else {
1691 "beginning".into()
1692 }
1693 );
1694 for n in start..self.focus_flags.len() {
1695 if matches!(
1696 self.navigable[n],
1697 Navigation::Reach
1698 | Navigation::ReachLeaveBack
1699 | Navigation::ReachLeaveFront
1700 | Navigation::Regular
1701 ) {
1702 focus_debug!(self, " -> {}:{:?}", n, self.focus_flags[n].name());
1703 return Some(n);
1704 }
1705 }
1706 focus_debug!(self, " -> no first");
1707 None
1708 }
1709
1710 fn next_navigable(&self, start: usize) -> usize {
1712 focus_debug!(
1713 self,
1714 "next navigable after {}:{:?}",
1715 start,
1716 if start < self.focus_flags.len() {
1717 self.focus_flags[start].name()
1718 } else {
1719 "last".into()
1720 }
1721 );
1722
1723 let mut n = start;
1724 loop {
1725 n = if n + 1 < self.focus_flags.len() {
1726 n + 1
1727 } else {
1728 0
1729 };
1730 if matches!(
1731 self.navigable[n],
1732 Navigation::Reach
1733 | Navigation::ReachLeaveBack
1734 | Navigation::ReachLeaveFront
1735 | Navigation::Regular
1736 ) {
1737 focus_debug!(self, " -> {}:{:?}", n, self.focus_flags[n].name());
1738 return n;
1739 }
1740 if n == start {
1741 focus_debug!(self, " -> {}:end at start", n);
1742 return n;
1743 }
1744 }
1745 }
1746
1747 fn prev_navigable(&self, start: usize) -> usize {
1749 focus_debug!(
1750 self,
1751 "prev navigable before {}:{:?}",
1752 start,
1753 self.focus_flags[start].name()
1754 );
1755
1756 let mut n = start;
1757 loop {
1758 n = if n > 0 {
1759 n - 1
1760 } else {
1761 self.focus_flags.len() - 1
1762 };
1763 if matches!(
1764 self.navigable[n],
1765 Navigation::Reach
1766 | Navigation::ReachLeaveBack
1767 | Navigation::ReachLeaveFront
1768 | Navigation::Regular
1769 ) {
1770 focus_debug!(self, " -> {}:{:?}", n, self.focus_flags[n].name());
1771 return n;
1772 }
1773 if n == start {
1774 focus_debug!(self, " -> {}:end at start", n);
1775 return n;
1776 }
1777 }
1778 }
1779
1780 #[allow(clippy::type_complexity)]
1782 pub(super) fn clone_destruct(
1783 &self,
1784 ) -> (
1785 Vec<FocusFlag>,
1786 Vec<bool>,
1787 Vec<(Rect, u16)>,
1788 Vec<Navigation>,
1789 Vec<(FocusFlag, (Rect, u16), Range<usize>)>,
1790 ) {
1791 (
1792 self.focus_flags.clone(),
1793 self.duplicate.clone(),
1794 self.areas.clone(),
1795 self.navigable.clone(),
1796 self.containers
1797 .iter()
1798 .map(|(v, w)| (v.container_flag.clone(), v.area, w.clone()))
1799 .collect::<Vec<_>>(),
1800 )
1801 }
1802 }
1803
1804 #[cfg(test)]
1805 mod test {
1806 use crate::focus::core::FocusCore;
1807 use crate::{FocusBuilder, FocusFlag, HasFocus};
1808 use ratatui::layout::Rect;
1809
1810 #[test]
1811 fn test_change() {
1812 assert_eq!(FocusCore::shift(0, 1..1), 1..1);
1813 assert_eq!(FocusCore::shift(1, 1..1), 2..2);
1814
1815 assert_eq!(FocusCore::expand(3..4, 0..1), 0..1);
1816 assert_eq!(FocusCore::expand(3..4, 1..2), 1..2);
1817 assert_eq!(FocusCore::expand(3..4, 2..3), 2..3);
1818 assert_eq!(FocusCore::expand(3..4, 3..4), 4..5);
1819 assert_eq!(FocusCore::expand(3..4, 4..5), 5..6);
1820
1821 assert_eq!(FocusCore::expand(3..3, 0..1), 0..1);
1822 assert_eq!(FocusCore::expand(3..3, 1..2), 1..2);
1823 assert_eq!(FocusCore::expand(3..3, 2..3), 2..3);
1824 assert_eq!(FocusCore::expand(3..3, 3..4), 3..4);
1825 assert_eq!(FocusCore::expand(3..3, 4..5), 4..5);
1826
1827 assert_eq!(FocusCore::shrink(3..4, 0..1), 0..1);
1828 assert_eq!(FocusCore::shrink(3..4, 2..3), 2..3);
1829 assert_eq!(FocusCore::shrink(3..4, 3..4), 3..3);
1830 assert_eq!(FocusCore::shrink(3..4, 4..5), 3..4);
1831 assert_eq!(FocusCore::shrink(3..4, 5..6), 4..5);
1832
1833 assert_eq!(FocusCore::shrink(3..3, 0..1), 0..1);
1834 assert_eq!(FocusCore::shrink(3..3, 1..2), 1..2);
1835 assert_eq!(FocusCore::shrink(3..3, 2..3), 2..3);
1836 assert_eq!(FocusCore::shrink(3..3, 3..4), 3..4);
1837 assert_eq!(FocusCore::shrink(3..3, 4..5), 4..5);
1838 }
1839
1840 #[test]
1841 #[should_panic]
1842 fn test_double_insert() {
1843 let a = FocusFlag::new().with_name("a");
1844 let b = FocusFlag::new().with_name("b");
1845
1846 let mut fb = FocusBuilder::new(None);
1847 fb.widget(&a);
1848 fb.widget(&b);
1849 fb.widget(&a);
1850 fb.build();
1851 }
1852
1853 #[test]
1854 fn test_insert_remove() {
1855 let a = FocusFlag::new().with_name("a");
1856 let b = FocusFlag::new().with_name("b");
1857 let c = FocusFlag::new().with_name("c");
1858 let d = FocusFlag::new().with_name("d");
1859 let e = FocusFlag::new().with_name("e");
1860 let f = FocusFlag::new().with_name("f");
1861 let g = FocusFlag::new().with_name("g");
1862 let h = FocusFlag::new().with_name("h");
1863 let i = FocusFlag::new().with_name("i");
1864
1865 let mut fb = FocusBuilder::new(None);
1866 fb.widget(&a);
1867 fb.widget(&b);
1868 fb.widget(&c);
1869 let ff = fb.build();
1870 assert_eq!(ff.core.focus_flags[0], a);
1871 assert_eq!(ff.core.focus_flags[1], b);
1872 assert_eq!(ff.core.focus_flags[2], c);
1873
1874 let cc = FocusFlag::new().with_name("cc");
1875 let mut fb = FocusBuilder::new(None);
1876 fb.widget(&a);
1877 let cc_end = fb.start_with_flags(cc.clone(), Rect::default(), 0);
1878 fb.widget(&d);
1879 fb.widget(&e);
1880 fb.widget(&f);
1881 fb.end(cc_end);
1882 fb.widget(&b);
1883 fb.widget(&c);
1884 let mut ff = fb.build();
1885 assert_eq!(ff.core.focus_flags[0], a);
1886 assert_eq!(ff.core.focus_flags[1], d);
1887 assert_eq!(ff.core.focus_flags[2], e);
1888 assert_eq!(ff.core.focus_flags[3], f);
1889 assert_eq!(ff.core.focus_flags[4], b);
1890 assert_eq!(ff.core.focus_flags[5], c);
1891 assert_eq!(ff.core.containers[0].1, 1..4);
1892
1893 struct DD {
1894 dd: FocusFlag,
1895 g: FocusFlag,
1896 h: FocusFlag,
1897 i: FocusFlag,
1898 }
1899
1900 impl HasFocus for DD {
1901 fn build(&self, fb: &mut FocusBuilder) {
1902 let tag = fb.start_with_flags(self.dd.clone(), self.area(), self.area_z());
1903 fb.widget(&self.g);
1904 fb.widget(&self.h);
1905 fb.widget(&self.i);
1906 fb.end(tag);
1907 }
1908
1909 fn focus(&self) -> FocusFlag {
1910 self.dd.clone()
1911 }
1912
1913 fn area(&self) -> Rect {
1914 Rect::default()
1915 }
1916 }
1917
1918 let dd = DD {
1919 dd: FocusFlag::new().with_name("dd"),
1920 g: g.clone(),
1921 h: h.clone(),
1922 i: i.clone(),
1923 };
1924 ff.replace_container(&cc, &dd);
1925 assert_eq!(ff.core.focus_flags[0], a);
1926 assert_eq!(ff.core.focus_flags[1], g);
1927 assert_eq!(ff.core.focus_flags[2], h);
1928 assert_eq!(ff.core.focus_flags[3], i);
1929 assert_eq!(ff.core.focus_flags[4], b);
1930 assert_eq!(ff.core.focus_flags[5], c);
1931 assert_eq!(ff.core.containers[0].1, 1..4);
1932 }
1933 }
1934}
1935
1936impl HandleEvent<crossterm::event::Event, Regular, Outcome> for Focus {
1937 #[inline(always)]
1938 fn handle(&mut self, event: &crossterm::event::Event, _keymap: Regular) -> Outcome {
1939 match event {
1940 ct_event!(keycode press Tab) => {
1941 focus_debug!(
1942 self.core,
1943 "Tab {:?}",
1944 self.focused().map(|v| v.name().to_string())
1945 );
1946 let r = if self.next() {
1947 Outcome::Changed
1948 } else {
1949 Outcome::Continue
1950 };
1951 focus_debug!(
1952 self.core,
1953 " -> {:?} {:?}",
1954 r,
1955 self.focused().map(|v| v.name().to_string())
1956 );
1957 r
1958 }
1959 ct_event!(keycode press SHIFT-Tab) | ct_event!(keycode press SHIFT-BackTab) => {
1960 focus_debug!(
1961 self.core,
1962 "BackTab {:?}",
1963 self.focused().map(|v| v.name().to_string())
1964 );
1965 let r = if self.prev() {
1966 Outcome::Changed
1967 } else {
1968 Outcome::Continue
1969 };
1970 focus_debug!(
1971 self.core,
1972 " -> {:?} {:?}",
1973 r,
1974 self.focused().map(|v| v.name().to_string())
1975 );
1976 r
1977 }
1978 _ => self.handle(event, MouseOnly),
1979 }
1980 }
1981}
1982
1983impl HandleEvent<crossterm::event::Event, MouseOnly, Outcome> for Focus {
1984 #[inline(always)]
1985 fn handle(&mut self, event: &crossterm::event::Event, _keymap: MouseOnly) -> Outcome {
1986 match event {
1987 ct_event!(mouse down Left for column, row) => {
1988 focus_debug!(self.core, "mouse down {},{}", column, row);
1989 if self.focus_at(*column, *row) {
1990 focus_debug!(
1991 self.core,
1992 " -> {:?}",
1993 self.focused().map(|v| v.name().to_string())
1994 );
1995 Outcome::Changed
1996 } else {
1997 self.reset_lost_gained();
1998 Outcome::Continue
1999 }
2000 }
2001 _ => {
2002 self.reset_lost_gained();
2003 Outcome::Continue
2004 }
2005 }
2006 }
2007}
2008
2009#[inline(always)]
2011pub fn handle_focus(focus: &mut Focus, event: &crossterm::event::Event) -> Outcome {
2012 HandleEvent::handle(focus, event, Regular)
2013}