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