From 9876b07faa5b366015ee626614cf17c52724512b Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Sat, 14 Dec 2024 15:16:49 +0000 Subject: [PATCH 1/4] Add Layout::find_id, renaming the old find_id to l_find_id --- crates/kas-core/src/core/layout.rs | 12 ++++++++++- crates/kas-core/src/core/widget.rs | 2 +- crates/kas-core/src/root.rs | 2 +- crates/kas-macros/src/make_layout.rs | 2 +- crates/kas-macros/src/widget.rs | 25 +++++++++++++++------- crates/kas-macros/src/widget_derive.rs | 20 +++++++++++++---- crates/kas-view/src/list_view.rs | 2 +- crates/kas-view/src/matrix_view.rs | 2 +- crates/kas-widgets/src/adapt/with_label.rs | 2 +- crates/kas-widgets/src/check_box.rs | 2 +- crates/kas-widgets/src/edit.rs | 4 ++-- crates/kas-widgets/src/grid.rs | 2 +- crates/kas-widgets/src/list.rs | 2 +- crates/kas-widgets/src/menu/menu_entry.rs | 4 ++-- crates/kas-widgets/src/menu/menubar.rs | 2 +- crates/kas-widgets/src/menu/mod.rs | 2 +- crates/kas-widgets/src/menu/submenu.rs | 4 ++-- crates/kas-widgets/src/radio_box.rs | 2 +- crates/kas-widgets/src/scroll.rs | 2 +- crates/kas-widgets/src/scroll_bar.rs | 4 ++-- crates/kas-widgets/src/scroll_label.rs | 2 +- crates/kas-widgets/src/scroll_text.rs | 2 +- crates/kas-widgets/src/slider.rs | 2 +- crates/kas-widgets/src/spinner.rs | 2 +- crates/kas-widgets/src/splitter.rs | 4 ++-- crates/kas-widgets/src/stack.rs | 2 +- crates/kas-widgets/src/tab_stack.rs | 2 +- examples/cursors.rs | 2 +- 28 files changed, 74 insertions(+), 43 deletions(-) diff --git a/crates/kas-core/src/core/layout.rs b/crates/kas-core/src/core/layout.rs index 86edb77a1..58dc39984 100644 --- a/crates/kas-core/src/core/layout.rs +++ b/crates/kas-core/src/core/layout.rs @@ -274,11 +274,21 @@ pub trait Layout { /// } /// Some(self.id()) /// ``` - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { let _ = coord; unimplemented!() // make rustdoc show that this is a provided method } + /// Translate a coordinate to an [`Id`] + /// + /// This wraps [`Layout::l_find_id`]. + /// + /// It is expected that [`Tile::set_rect`] is called before this method, + /// but failure to do so should not cause a fatal error. + fn find_id(&mut self, coord: Coord) -> Option { + self.l_find_id(coord) + } + /// Draw a widget and its children /// /// This method is invoked each frame to draw visible widgets. It should diff --git a/crates/kas-core/src/core/widget.rs b/crates/kas-core/src/core/widget.rs index 1a6ee04ba..3cde1570a 100644 --- a/crates/kas-core/src/core/widget.rs +++ b/crates/kas-core/src/core/widget.rs @@ -310,7 +310,7 @@ pub enum NavAdvance { /// - **Layout** is specified either via [layout syntax](macros::widget#layout-1) /// or via implementation of at least [`Layout::size_rules`] and /// [`Layout::draw`] (optionally also `set_rect`, `nav_next`, `translation` -/// and `find_id`). +/// and `l_find_id`). ///- **Event handling** is optional, implemented through [`Events`]. /// /// For examples, check the source code of widgets in the widgets library diff --git a/crates/kas-core/src/root.rs b/crates/kas-core/src/root.rs index 8be1851ad..19a1c2c18 100644 --- a/crates/kas-core/src/root.rs +++ b/crates/kas-core/src/root.rs @@ -146,7 +146,7 @@ impl_scope! { self.inner.set_rect(cx, Rect::new(p_in, s_in), hints); } - fn find_id(&mut self, _: Coord) -> Option { + fn l_find_id(&mut self, _: Coord) -> Option { unimplemented!() } diff --git a/crates/kas-macros/src/make_layout.rs b/crates/kas-macros/src/make_layout.rs index d62daaf85..755d68a4c 100644 --- a/crates/kas-macros/src/make_layout.rs +++ b/crates/kas-macros/src/make_layout.rs @@ -195,7 +195,7 @@ impl Tree { ::kas::layout::LayoutVisitor::layout_visitor(self).set_rect(cx, rect, hints); } - fn find_id(&mut self, coord: ::kas::geom::Coord) -> Option<::kas::Id> { + fn l_find_id(&mut self, coord: ::kas::geom::Coord) -> Option<::kas::Id> { use ::kas::{Layout, LayoutExt, layout::LayoutVisitor}; #[cfg(debug_assertions)] #core_path.status.require_rect(&#core_path.id); diff --git a/crates/kas-macros/src/widget.rs b/crates/kas-macros/src/widget.rs index 6f9b6c475..035793697 100644 --- a/crates/kas-macros/src/widget.rs +++ b/crates/kas-macros/src/widget.rs @@ -383,7 +383,7 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul let mut fn_nav_next_err = None; let mut fn_size_rules = None; let mut set_rect = quote! { self.#core.rect = rect; }; - let mut find_id = quote! { + let mut l_find_id = quote! { use ::kas::{Layout, LayoutExt}; self.rect().contains(coord).then(|| self.id()) }; @@ -422,7 +422,7 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul #core_path.rect = rect; ::kas::layout::LayoutVisitor::layout_visitor(self).set_rect(cx, rect, hints); }; - find_id = quote! { + l_find_id = quote! { use ::kas::{Layout, LayoutExt, layout::LayoutVisitor}; if !self.rect().contains(coord) { @@ -460,12 +460,12 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul #set_rect } }; - let fn_find_id = quote! { - fn find_id(&mut self, coord: ::kas::geom::Coord) -> Option<::kas::Id> { + let fn_l_find_id = quote! { + fn l_find_id(&mut self, coord: ::kas::geom::Coord) -> Option<::kas::Id> { #[cfg(debug_assertions)] #core_path.status.require_rect(&#core_path.id); - #find_id + #l_find_id } }; @@ -601,7 +601,7 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul } } - if let Some((index, _)) = item_idents.iter().find(|(_, ident)| *ident == "find_id") { + if let Some((index, _)) = item_idents.iter().find(|(_, ident)| *ident == "l_find_id") { if let Some(ref core) = core_data { if let ImplItem::Fn(f) = &mut layout_impl.items[*index] { f.block.stmts.insert(0, parse_quote! { @@ -611,7 +611,16 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul } } } else { - layout_impl.items.push(Verbatim(fn_find_id)); + layout_impl.items.push(Verbatim(fn_l_find_id)); + } + + if let Some((index, _)) = item_idents.iter().find(|(_, ident)| *ident == "find_id") { + if let ImplItem::Fn(f) = &mut layout_impl.items[*index] { + emit_warning!( + f, + "Implementations are expected to impl `fn l_find_id`, not `find_id`" + ); + } } if let Some((index, _)) = item_idents.iter().find(|(_, ident)| *ident == "draw") { @@ -639,7 +648,7 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul #fn_size_rules #fn_set_rect #fn_nav_next - #fn_find_id + #fn_l_find_id #fn_draw } }); diff --git a/crates/kas-macros/src/widget_derive.rs b/crates/kas-macros/src/widget_derive.rs index 21645b1c0..8cf339238 100644 --- a/crates/kas-macros/src/widget_derive.rs +++ b/crates/kas-macros/src/widget_derive.rs @@ -161,7 +161,7 @@ pub fn widget(_attr_span: Span, args: WidgetArgs, scope: &mut Scope) -> Result<( self.#inner.translation() } }; - let fn_find_id = quote! { + let fn_find_id_forward = quote! { #[inline] fn find_id(&mut self, coord: ::kas::geom::Coord) -> Option<::kas::Id> { self.#inner.find_id(coord) @@ -280,8 +280,20 @@ pub fn widget(_attr_span: Span, args: WidgetArgs, scope: &mut Scope) -> Result<( layout_impl.items.push(Verbatim(fn_translation)); } - if !has_item("find_id") { - layout_impl.items.push(Verbatim(fn_find_id)); + if has_item("l_find_id") { + // Use default Layout::find_id impl + } else { + // Use default Layout::l_find_id (unimplemented) + layout_impl.items.push(Verbatim(fn_find_id_forward)); + } + + if let Some((index, _)) = item_idents.iter().find(|(_, ident)| *ident == "find_id") { + if let syn::ImplItem::Fn(f) = &mut layout_impl.items[*index] { + emit_warning!( + f, + "Implementations are expected to impl `fn l_find_id`, not `find_id`" + ); + } } if !has_item("draw") { @@ -295,7 +307,7 @@ pub fn widget(_attr_span: Span, args: WidgetArgs, scope: &mut Scope) -> Result<( #fn_set_rect #fn_nav_next #fn_translation - #fn_find_id + #fn_find_id_forward #fn_draw } }); diff --git a/crates/kas-view/src/list_view.rs b/crates/kas-view/src/list_view.rs index 8a5fbfca3..293833fdd 100644 --- a/crates/kas-view/src/list_view.rs +++ b/crates/kas-view/src/list_view.rs @@ -553,7 +553,7 @@ impl_scope! { self.scroll_offset() } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if !self.rect().contains(coord) { return None; } diff --git a/crates/kas-view/src/matrix_view.rs b/crates/kas-view/src/matrix_view.rs index 4874d27a9..fd0ebc02d 100644 --- a/crates/kas-view/src/matrix_view.rs +++ b/crates/kas-view/src/matrix_view.rs @@ -487,7 +487,7 @@ impl_scope! { self.scroll_offset() } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if !self.rect().contains(coord) { return None; } diff --git a/crates/kas-widgets/src/adapt/with_label.rs b/crates/kas-widgets/src/adapt/with_label.rs index 4ba1c8529..3d4a6b459 100644 --- a/crates/kas-widgets/src/adapt/with_label.rs +++ b/crates/kas-widgets/src/adapt/with_label.rs @@ -113,7 +113,7 @@ impl_scope! { } impl Layout for Self { - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { self.rect().contains(coord).then(|| self.inner.id()) } } diff --git a/crates/kas-widgets/src/check_box.rs b/crates/kas-widgets/src/check_box.rs index b7b60b6a2..a14af7377 100644 --- a/crates/kas-widgets/src/check_box.rs +++ b/crates/kas-widgets/src/check_box.rs @@ -192,7 +192,7 @@ impl_scope! { shrink_to_text(&mut self.core.rect, dir, &self.label); } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { self.rect().contains(coord).then(|| self.inner.id()) } } diff --git a/crates/kas-widgets/src/edit.rs b/crates/kas-widgets/src/edit.rs index b5639bf5c..fe174683b 100644 --- a/crates/kas-widgets/src/edit.rs +++ b/crates/kas-widgets/src/edit.rs @@ -396,7 +396,7 @@ impl_scope! { self.update_scroll_bar(cx); } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if !self.rect().contains(coord) { return None; } @@ -692,7 +692,7 @@ impl_scope! { self.view_offset = self.view_offset.min(self.max_scroll_offset()); } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { self.outer_rect.contains(coord).then_some(self.id()) } diff --git a/crates/kas-widgets/src/grid.rs b/crates/kas-widgets/src/grid.rs index 0fe98d701..74d57b226 100644 --- a/crates/kas-widgets/src/grid.rs +++ b/crates/kas-widgets/src/grid.rs @@ -100,7 +100,7 @@ impl_scope! { } } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if !self.rect().contains(coord) { return None; } diff --git a/crates/kas-widgets/src/list.rs b/crates/kas-widgets/src/list.rs index 267354b88..7b562c900 100644 --- a/crates/kas-widgets/src/list.rs +++ b/crates/kas-widgets/src/list.rs @@ -119,7 +119,7 @@ impl_scope! { } } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { let solver = RowPositionSolver::new(self.direction); solver .find_child_mut(&mut self.widgets, coord) diff --git a/crates/kas-widgets/src/menu/menu_entry.rs b/crates/kas-widgets/src/menu/menu_entry.rs index f38646f01..5750cbf6a 100644 --- a/crates/kas-widgets/src/menu/menu_entry.rs +++ b/crates/kas-widgets/src/menu/menu_entry.rs @@ -31,7 +31,7 @@ impl_scope! { } impl Layout for Self { - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { self.rect().contains(coord).then(|| self.id()) } @@ -120,7 +120,7 @@ impl_scope! { } impl Layout for Self { - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { self.rect().contains(coord).then(|| self.checkbox.id()) } diff --git a/crates/kas-widgets/src/menu/menubar.rs b/crates/kas-widgets/src/menu/menubar.rs index 1d994c34a..6ff648718 100644 --- a/crates/kas-widgets/src/menu/menubar.rs +++ b/crates/kas-widgets/src/menu/menubar.rs @@ -99,7 +99,7 @@ impl_scope! { } } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if !self.rect().contains(coord) { return None; } diff --git a/crates/kas-widgets/src/menu/mod.rs b/crates/kas-widgets/src/menu/mod.rs index b4f29c331..edfd89883 100644 --- a/crates/kas-widgets/src/menu/mod.rs +++ b/crates/kas-widgets/src/menu/mod.rs @@ -48,7 +48,7 @@ pub struct SubItems<'a> { /// Trait governing menus, sub-menus and menu-entries /// /// Implementations will automatically receive nav focus on mouse-hover, thus -/// should ensure that [`Layout::find_id`] returns the identifier of the widget +/// should ensure that [`Layout::l_find_id`] returns the identifier of the widget /// which should be focussed, and that this widget has /// [`Events::navigable`] return true. #[autoimpl(for Box)] diff --git a/crates/kas-widgets/src/menu/submenu.rs b/crates/kas-widgets/src/menu/submenu.rs index e378e4469..fb5165371 100644 --- a/crates/kas-widgets/src/menu/submenu.rs +++ b/crates/kas-widgets/src/menu/submenu.rs @@ -101,7 +101,7 @@ impl_scope! { None } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { self.rect().contains(coord).then(|| self.id()) } @@ -354,7 +354,7 @@ impl_scope! { } } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if !self.rect().contains(coord) { return None; } diff --git a/crates/kas-widgets/src/radio_box.rs b/crates/kas-widgets/src/radio_box.rs index 700629547..dd3283288 100644 --- a/crates/kas-widgets/src/radio_box.rs +++ b/crates/kas-widgets/src/radio_box.rs @@ -153,7 +153,7 @@ impl_scope! { crate::check_box::shrink_to_text(&mut self.core.rect, dir, &self.label); } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { self.rect().contains(coord).then(|| self.inner.id()) } } diff --git a/crates/kas-widgets/src/scroll.rs b/crates/kas-widgets/src/scroll.rs index 36089f352..70559a190 100644 --- a/crates/kas-widgets/src/scroll.rs +++ b/crates/kas-widgets/src/scroll.rs @@ -123,7 +123,7 @@ impl_scope! { self.scroll_offset() } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if !self.rect().contains(coord) { return None; } diff --git a/crates/kas-widgets/src/scroll_bar.rs b/crates/kas-widgets/src/scroll_bar.rs index 315623d3a..659c75bde 100644 --- a/crates/kas-widgets/src/scroll_bar.rs +++ b/crates/kas-widgets/src/scroll_bar.rs @@ -290,7 +290,7 @@ impl_scope! { let _ = self.update_widgets(); } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if !self.rect().contains(coord) { return None; } @@ -500,7 +500,7 @@ impl_scope! { } } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if !self.rect().contains(coord) { return None; } diff --git a/crates/kas-widgets/src/scroll_label.rs b/crates/kas-widgets/src/scroll_label.rs index 3d732654a..fe12347bf 100644 --- a/crates/kas-widgets/src/scroll_label.rs +++ b/crates/kas-widgets/src/scroll_label.rs @@ -61,7 +61,7 @@ impl_scope! { self.bar.set_value(cx, self.view_offset.1); } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if !self.rect().contains(coord) { return None; } diff --git a/crates/kas-widgets/src/scroll_text.rs b/crates/kas-widgets/src/scroll_text.rs index dcf13acb2..4798f6e09 100644 --- a/crates/kas-widgets/src/scroll_text.rs +++ b/crates/kas-widgets/src/scroll_text.rs @@ -61,7 +61,7 @@ impl_scope! { self.bar.set_value(cx, self.view_offset.1); } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if !self.rect().contains(coord) { return None; } diff --git a/crates/kas-widgets/src/slider.rs b/crates/kas-widgets/src/slider.rs index e94a98ff2..63eb9a630 100644 --- a/crates/kas-widgets/src/slider.rs +++ b/crates/kas-widgets/src/slider.rs @@ -311,7 +311,7 @@ impl_scope! { let _ = self.grip.set_size_and_offset(size, self.offset()); } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if !self.rect().contains(coord) { return None; } diff --git a/crates/kas-widgets/src/spinner.rs b/crates/kas-widgets/src/spinner.rs index 83bcb354e..02fd7f652 100644 --- a/crates/kas-widgets/src/spinner.rs +++ b/crates/kas-widgets/src/spinner.rs @@ -286,7 +286,7 @@ impl_scope! { self.edit.set_outer_rect(rect, FrameStyle::EditBox); } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { self.b_up.find_id(coord) .or_else(|| self.b_down.find_id(coord)) .or_else(|| self.edit.find_id(coord)) diff --git a/crates/kas-widgets/src/splitter.rs b/crates/kas-widgets/src/splitter.rs index e8683e5c4..87f4161e0 100644 --- a/crates/kas-widgets/src/splitter.rs +++ b/crates/kas-widgets/src/splitter.rs @@ -213,7 +213,7 @@ impl_scope! { } } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if !self.rect().contains(coord) || !self.size_solved { return None; } @@ -239,7 +239,7 @@ impl_scope! { if !self.size_solved { return; } - // as with find_id, there's not much harm in invoking the solver twice + // as with l_find_id, there's not much harm in invoking the solver twice let solver = layout::RowPositionSolver::new(self.direction); solver.for_children_mut(&mut self.widgets, draw.get_clip_rect(), |w| { diff --git a/crates/kas-widgets/src/stack.rs b/crates/kas-widgets/src/stack.rs index 1aa47a0c5..57482235e 100644 --- a/crates/kas-widgets/src/stack.rs +++ b/crates/kas-widgets/src/stack.rs @@ -127,7 +127,7 @@ impl_scope! { } } - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { if let Some(entry) = self.widgets.get_mut(self.active) { debug_assert_eq!(entry.1, State::Sized); return entry.0.find_id(coord); diff --git a/crates/kas-widgets/src/tab_stack.rs b/crates/kas-widgets/src/tab_stack.rs index 08c09ab33..96f3267d2 100644 --- a/crates/kas-widgets/src/tab_stack.rs +++ b/crates/kas-widgets/src/tab_stack.rs @@ -44,7 +44,7 @@ impl_scope! { } impl Layout for Self { - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { self.rect().contains(coord).then_some(self.id()) } } diff --git a/examples/cursors.rs b/examples/cursors.rs index 0a00938fe..e0e1d9f9b 100644 --- a/examples/cursors.rs +++ b/examples/cursors.rs @@ -22,7 +22,7 @@ impl_scope! { cursor: CursorIcon, } impl Layout for Self { - fn find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Option { // Steal mouse focus: hover points to self, not self.label self.rect().contains(coord).then(|| self.id()) } From 23d146254df49522ba89d7f0cf106d4fe1a379e9 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 10 Dec 2024 10:50:21 +0000 Subject: [PATCH 2/4] EditField: don't rely on set_outer_rect for find_id --- crates/kas-widgets/src/edit.rs | 6 ++---- crates/kas-widgets/src/spinner.rs | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/crates/kas-widgets/src/edit.rs b/crates/kas-widgets/src/edit.rs index fe174683b..7e5f14ef2 100644 --- a/crates/kas-widgets/src/edit.rs +++ b/crates/kas-widgets/src/edit.rs @@ -1040,10 +1040,8 @@ impl EditField { /// /// Optionally, call this immediately after [`Self::set_rect`] with the /// "outer" rect and frame style. In this case, a frame will be drawn using - /// this `outer_rect` and `style`. The advantages are: - /// - /// - The "error state" background can correctly fill the frame - /// - Clicks on the frame get registered as clicks on self + /// this `outer_rect` and `style`. This allows the "error state" background + /// to correctly fill the frame. /// /// Any other widgets painted over the `outer_rect` should be drawn after /// the `EditField`. diff --git a/crates/kas-widgets/src/spinner.rs b/crates/kas-widgets/src/spinner.rs index 02fd7f652..11e4bf602 100644 --- a/crates/kas-widgets/src/spinner.rs +++ b/crates/kas-widgets/src/spinner.rs @@ -289,7 +289,7 @@ impl_scope! { fn l_find_id(&mut self, coord: Coord) -> Option { self.b_up.find_id(coord) .or_else(|| self.b_down.find_id(coord)) - .or_else(|| self.edit.find_id(coord)) + .or_else(|| Some(self.edit.id())) } fn draw(&mut self, mut draw: DrawCx) { From 203f262afd4ff6f39f15732ce3b829b264a3216f Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 10 Dec 2024 14:57:28 +0000 Subject: [PATCH 3/4] Change behaviour of Layout::l_find_id Fix: set rect in List::l_set_rect Tweak: Splitter: debug_assert that size_solved --- crates/kas-core/src/core/layout.rs | 15 +++++---------- crates/kas-core/src/layout/visitor.rs | 11 ++++------- crates/kas-core/src/root.rs | 2 +- crates/kas-macros/src/make_layout.rs | 7 ++----- crates/kas-macros/src/widget.rs | 9 +++------ crates/kas-view/src/list_view.rs | 10 +++------- crates/kas-view/src/matrix_view.rs | 10 +++------- crates/kas-widgets/src/adapt/with_label.rs | 4 ++-- crates/kas-widgets/src/check_box.rs | 4 ++-- crates/kas-widgets/src/edit.rs | 14 +++++--------- crates/kas-widgets/src/grid.rs | 9 +++------ crates/kas-widgets/src/list.rs | 3 ++- crates/kas-widgets/src/menu/menu_entry.rs | 10 +++++----- crates/kas-widgets/src/menu/menubar.rs | 7 ++----- crates/kas-widgets/src/menu/submenu.rs | 16 ++++++---------- crates/kas-widgets/src/radio_box.rs | 4 ++-- crates/kas-widgets/src/scroll.rs | 6 ++---- crates/kas-widgets/src/scroll_bar.rs | 19 ++++++------------- crates/kas-widgets/src/scroll_label.rs | 8 ++------ crates/kas-widgets/src/scroll_text.rs | 8 ++------ crates/kas-widgets/src/slider.rs | 9 +++------ crates/kas-widgets/src/spinner.rs | 4 ++-- crates/kas-widgets/src/splitter.rs | 14 ++++++++------ crates/kas-widgets/src/stack.rs | 8 +++++--- crates/kas-widgets/src/tab_stack.rs | 4 ++-- examples/cursors.rs | 4 ++-- 26 files changed, 84 insertions(+), 135 deletions(-) diff --git a/crates/kas-core/src/core/layout.rs b/crates/kas-core/src/core/layout.rs index 58dc39984..5f2e6f257 100644 --- a/crates/kas-core/src/core/layout.rs +++ b/crates/kas-core/src/core/layout.rs @@ -254,39 +254,34 @@ pub trait Layout { /// /// When writing a custom implementation: /// - /// - Widgets should test `self.rect().contains(coord)`, returning `None` - /// if this test is `false`; otherwise, they should always return *some* - /// [`Id`], either a childs or their own. + /// - Widgets may assume that `self.rect().contains(coord)`. /// - If the Widget uses a translated coordinate space (i.e. /// `self.translation() != Offset::ZERO`) then pass /// `coord + self.translation()` to children. /// /// The default implementation is non-trivial: /// ```ignore - /// if !self.rect().contains(coord) { - /// return None; - /// } /// let coord = coord + self.translation(); /// for child in ITER_OVER_CHILDREN { /// if let Some(id) = child.find_id(coord) { /// return Some(id); /// } /// } - /// Some(self.id()) + /// self.id() /// ``` - fn l_find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Id { let _ = coord; unimplemented!() // make rustdoc show that this is a provided method } /// Translate a coordinate to an [`Id`] /// - /// This wraps [`Layout::l_find_id`]. + /// This tests whether `self.rect().contains(coord)`, then calls [`Layout::l_find_id`]. /// /// It is expected that [`Tile::set_rect`] is called before this method, /// but failure to do so should not cause a fatal error. fn find_id(&mut self, coord: Coord) -> Option { - self.l_find_id(coord) + self.rect().contains(coord).then(|| self.l_find_id(coord)) } /// Draw a widget and its children diff --git a/crates/kas-core/src/layout/visitor.rs b/crates/kas-core/src/layout/visitor.rs index cb2e7928d..753ea9582 100644 --- a/crates/kas-core/src/layout/visitor.rs +++ b/crates/kas-core/src/layout/visitor.rs @@ -36,14 +36,11 @@ pub trait Visitable { /// In other respects, this functions identically to [`Layout::set_rect`]. fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect, hints: AlignHints); - /// Translate a coordinate to an [`Id`] - /// - /// The caller is expected to + /// Look for a widget at this `coord` /// - /// 1. Return `None` if `!self.rect().contains(coord)` - /// 2. Translate `coord`: `let coord = coord + self.translation();` - /// 3. Call `find_id` (this method), returning its result if not `None` - /// 4. Otherwise return `Some(self.id())` + /// Returns the [`Id`] of a child when some child occupies `coord`. Returns + /// [`None`] when there is no (probable) child widget at `coord`, in which + /// case the caller may use its own [`Id`]. fn find_id(&mut self, coord: Coord) -> Option; /// Draw a widget and its children diff --git a/crates/kas-core/src/root.rs b/crates/kas-core/src/root.rs index 19a1c2c18..293db07d0 100644 --- a/crates/kas-core/src/root.rs +++ b/crates/kas-core/src/root.rs @@ -146,7 +146,7 @@ impl_scope! { self.inner.set_rect(cx, Rect::new(p_in, s_in), hints); } - fn l_find_id(&mut self, _: Coord) -> Option { + fn l_find_id(&mut self, _: Coord) -> Id { unimplemented!() } diff --git a/crates/kas-macros/src/make_layout.rs b/crates/kas-macros/src/make_layout.rs index 755d68a4c..72bcc579d 100644 --- a/crates/kas-macros/src/make_layout.rs +++ b/crates/kas-macros/src/make_layout.rs @@ -195,18 +195,15 @@ impl Tree { ::kas::layout::LayoutVisitor::layout_visitor(self).set_rect(cx, rect, hints); } - fn l_find_id(&mut self, coord: ::kas::geom::Coord) -> Option<::kas::Id> { + fn l_find_id(&mut self, coord: ::kas::geom::Coord) -> ::kas::Id { use ::kas::{Layout, LayoutExt, layout::LayoutVisitor}; #[cfg(debug_assertions)] #core_path.status.require_rect(&#core_path.id); - if !self.rect().contains(coord) { - return None; - } let coord = coord + self.translation(); self.layout_visitor() .find_id(coord) - .or_else(|| Some(self.id())) + .unwrap_or_else(|| self.id()) } fn draw(&mut self, draw: ::kas::theme::DrawCx) { diff --git a/crates/kas-macros/src/widget.rs b/crates/kas-macros/src/widget.rs index 035793697..8299bdf05 100644 --- a/crates/kas-macros/src/widget.rs +++ b/crates/kas-macros/src/widget.rs @@ -385,7 +385,7 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul let mut set_rect = quote! { self.#core.rect = rect; }; let mut l_find_id = quote! { use ::kas::{Layout, LayoutExt}; - self.rect().contains(coord).then(|| self.id()) + self.id() }; let mut fn_draw = None; if let Some(Layout { tree, .. }) = args.layout.take() { @@ -425,13 +425,10 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul l_find_id = quote! { use ::kas::{Layout, LayoutExt, layout::LayoutVisitor}; - if !self.rect().contains(coord) { - return None; - } let coord = coord + self.translation(); self.layout_visitor() .find_id(coord) - .or_else(|| Some(self.id())) + .unwrap_or_else(|| self.id()) }; fn_draw = Some(quote! { fn draw(&mut self, draw: ::kas::theme::DrawCx) { @@ -461,7 +458,7 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul } }; let fn_l_find_id = quote! { - fn l_find_id(&mut self, coord: ::kas::geom::Coord) -> Option<::kas::Id> { + fn l_find_id(&mut self, coord: ::kas::geom::Coord) -> ::kas::Id { #[cfg(debug_assertions)] #core_path.status.require_rect(&#core_path.id); diff --git a/crates/kas-view/src/list_view.rs b/crates/kas-view/src/list_view.rs index 293833fdd..ad2d9a5e1 100644 --- a/crates/kas-view/src/list_view.rs +++ b/crates/kas-view/src/list_view.rs @@ -553,20 +553,16 @@ impl_scope! { self.scroll_offset() } - fn l_find_id(&mut self, coord: Coord) -> Option { - if !self.rect().contains(coord) { - return None; - } - + fn l_find_id(&mut self, coord: Coord) -> Id { let coord = coord + self.scroll.offset(); for child in &mut self.widgets[..self.cur_len.cast()] { if child.key.is_some() { if let Some(id) = child.widget.find_id(coord) { - return Some(id); + return id; } } } - Some(self.id()) + self.id() } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-view/src/matrix_view.rs b/crates/kas-view/src/matrix_view.rs index fd0ebc02d..32e27ac28 100644 --- a/crates/kas-view/src/matrix_view.rs +++ b/crates/kas-view/src/matrix_view.rs @@ -487,21 +487,17 @@ impl_scope! { self.scroll_offset() } - fn l_find_id(&mut self, coord: Coord) -> Option { - if !self.rect().contains(coord) { - return None; - } - + fn l_find_id(&mut self, coord: Coord) -> Id { let num = self.num_children(); let coord = coord + self.scroll.offset(); for child in &mut self.widgets[..num] { if child.key.is_some() { if let Some(id) = child.widget.find_id(coord) { - return Some(id); + return id; } } } - Some(self.id()) + self.id() } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/adapt/with_label.rs b/crates/kas-widgets/src/adapt/with_label.rs index 3d4a6b459..c8f1c352f 100644 --- a/crates/kas-widgets/src/adapt/with_label.rs +++ b/crates/kas-widgets/src/adapt/with_label.rs @@ -113,8 +113,8 @@ impl_scope! { } impl Layout for Self { - fn l_find_id(&mut self, coord: Coord) -> Option { - self.rect().contains(coord).then(|| self.inner.id()) + fn l_find_id(&mut self, _: Coord) -> Id { + self.inner.id() } } } diff --git a/crates/kas-widgets/src/check_box.rs b/crates/kas-widgets/src/check_box.rs index a14af7377..69e4bb5a2 100644 --- a/crates/kas-widgets/src/check_box.rs +++ b/crates/kas-widgets/src/check_box.rs @@ -192,8 +192,8 @@ impl_scope! { shrink_to_text(&mut self.core.rect, dir, &self.label); } - fn l_find_id(&mut self, coord: Coord) -> Option { - self.rect().contains(coord).then(|| self.inner.id()) + fn l_find_id(&mut self, _: Coord) -> Id { + self.inner.id() } } diff --git a/crates/kas-widgets/src/edit.rs b/crates/kas-widgets/src/edit.rs index 7e5f14ef2..f12c9d484 100644 --- a/crates/kas-widgets/src/edit.rs +++ b/crates/kas-widgets/src/edit.rs @@ -396,20 +396,16 @@ impl_scope! { self.update_scroll_bar(cx); } - fn l_find_id(&mut self, coord: Coord) -> Option { - if !self.rect().contains(coord) { - return None; - } - + fn l_find_id(&mut self, coord: Coord) -> Id { if self.max_scroll_offset().1 > 0 { if let Some(id) = self.bar.find_id(coord) { - return Some(id); + return id; } } // If coord is over self but not over self.bar, we assign // the event to self.inner without further question. - Some(self.inner.id()) + self.inner.id() } fn draw(&mut self, mut draw: DrawCx) { @@ -692,8 +688,8 @@ impl_scope! { self.view_offset = self.view_offset.min(self.max_scroll_offset()); } - fn l_find_id(&mut self, coord: Coord) -> Option { - self.outer_rect.contains(coord).then_some(self.id()) + fn l_find_id(&mut self, _: Coord) -> Id { + self.id() } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/grid.rs b/crates/kas-widgets/src/grid.rs index 74d57b226..7252daa5f 100644 --- a/crates/kas-widgets/src/grid.rs +++ b/crates/kas-widgets/src/grid.rs @@ -100,18 +100,15 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Option { - if !self.rect().contains(coord) { - return None; - } + fn l_find_id(&mut self, coord: Coord) -> Id { for n in 0..self.widgets.len() { if let Some(child) = self.widgets.get_mut_layout(n) { if let Some(id) = child.find_id(coord) { - return Some(id); + return id; } } } - Some(self.id()) + self.id() } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/list.rs b/crates/kas-widgets/src/list.rs index 7b562c900..5644f47cf 100644 --- a/crates/kas-widgets/src/list.rs +++ b/crates/kas-widgets/src/list.rs @@ -119,11 +119,12 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Id { let solver = RowPositionSolver::new(self.direction); solver .find_child_mut(&mut self.widgets, coord) .and_then(|child| child.find_id(coord)) + .unwrap_or_else(|| self.id()) } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/menu/menu_entry.rs b/crates/kas-widgets/src/menu/menu_entry.rs index 5750cbf6a..5590c86c1 100644 --- a/crates/kas-widgets/src/menu/menu_entry.rs +++ b/crates/kas-widgets/src/menu/menu_entry.rs @@ -31,13 +31,13 @@ impl_scope! { } impl Layout for Self { - fn l_find_id(&mut self, coord: Coord) -> Option { - self.rect().contains(coord).then(|| self.id()) + fn l_find_id(&mut self, _: Coord) -> Id { + self.id() } fn draw(&mut self, mut draw: DrawCx) { draw.frame(self.rect(), FrameStyle::MenuEntry, Default::default()); - self.label.draw(draw); + draw.recurse(&mut self.label); } } @@ -120,8 +120,8 @@ impl_scope! { } impl Layout for Self { - fn l_find_id(&mut self, coord: Coord) -> Option { - self.rect().contains(coord).then(|| self.checkbox.id()) + fn l_find_id(&mut self, _: Coord) -> Id { + self.checkbox.id() } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/menu/menubar.rs b/crates/kas-widgets/src/menu/menubar.rs index 6ff648718..617f2fdf6 100644 --- a/crates/kas-widgets/src/menu/menubar.rs +++ b/crates/kas-widgets/src/menu/menubar.rs @@ -99,15 +99,12 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Option { - if !self.rect().contains(coord) { - return None; - } + fn l_find_id(&mut self, coord: Coord) -> Id { let solver = RowPositionSolver::new(self.direction); solver .find_child_mut(&mut self.widgets, coord) .and_then(|child| child.find_id(coord)) - .or_else(|| Some(self.id())) + .unwrap_or_else(|| self.id()) } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/menu/submenu.rs b/crates/kas-widgets/src/menu/submenu.rs index fb5165371..c087d9338 100644 --- a/crates/kas-widgets/src/menu/submenu.rs +++ b/crates/kas-widgets/src/menu/submenu.rs @@ -101,13 +101,13 @@ impl_scope! { None } - fn l_find_id(&mut self, coord: Coord) -> Option { - self.rect().contains(coord).then(|| self.id()) + fn l_find_id(&mut self, _: Coord) -> Id { + self.id() } fn draw(&mut self, mut draw: DrawCx) { draw.frame(self.rect(), FrameStyle::MenuEntry, Default::default()); - self.label.draw(draw.re_id(self.id())); + draw.recurse(&mut self.label); if self.mark.rect().size != Size::ZERO { draw.recurse(&mut self.mark); } @@ -354,17 +354,13 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Option { - if !self.rect().contains(coord) { - return None; - } - + fn l_find_id(&mut self, coord: Coord) -> Id { for child in self.list.iter_mut() { if let Some(id) = child.find_id(coord) { - return Some(id); + return id; } } - Some(self.id()) + self.id() } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/radio_box.rs b/crates/kas-widgets/src/radio_box.rs index dd3283288..877eeaf6d 100644 --- a/crates/kas-widgets/src/radio_box.rs +++ b/crates/kas-widgets/src/radio_box.rs @@ -153,8 +153,8 @@ impl_scope! { crate::check_box::shrink_to_text(&mut self.core.rect, dir, &self.label); } - fn l_find_id(&mut self, coord: Coord) -> Option { - self.rect().contains(coord).then(|| self.inner.id()) + fn l_find_id(&mut self, _: Coord) -> Id { + self.inner.id() } } diff --git a/crates/kas-widgets/src/scroll.rs b/crates/kas-widgets/src/scroll.rs index 70559a190..323ed2bbc 100644 --- a/crates/kas-widgets/src/scroll.rs +++ b/crates/kas-widgets/src/scroll.rs @@ -123,11 +123,9 @@ impl_scope! { self.scroll_offset() } - fn l_find_id(&mut self, coord: Coord) -> Option { - if !self.rect().contains(coord) { - return None; - } + fn l_find_id(&mut self, coord: Coord) -> Id { self.inner.find_id(coord + self.translation()) + .unwrap_or_else(|| self.id()) } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/scroll_bar.rs b/crates/kas-widgets/src/scroll_bar.rs index 659c75bde..3da9adca3 100644 --- a/crates/kas-widgets/src/scroll_bar.rs +++ b/crates/kas-widgets/src/scroll_bar.rs @@ -290,14 +290,11 @@ impl_scope! { let _ = self.update_widgets(); } - fn l_find_id(&mut self, coord: Coord) -> Option { - if !self.rect().contains(coord) { - return None; - } + fn l_find_id(&mut self, coord: Coord) -> Id { if self.invisible && self.max_value == 0 { - return None; + return self.id(); } - self.grip.find_id(coord).or_else(|| Some(self.id())) + self.grip.find_id(coord).unwrap_or_else(|| self.id()) } fn draw(&mut self, mut draw: DrawCx) { @@ -500,15 +497,11 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Option { - if !self.rect().contains(coord) { - return None; - } - self.vert_bar - .find_id(coord) + fn l_find_id(&mut self, coord: Coord) -> Id { + self.vert_bar.find_id(coord) .or_else(|| self.horiz_bar.find_id(coord)) .or_else(|| self.inner.find_id(coord)) - .or_else(|| Some(self.id())) + .unwrap_or_else(|| self.id()) } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/scroll_label.rs b/crates/kas-widgets/src/scroll_label.rs index fe12347bf..9420982ca 100644 --- a/crates/kas-widgets/src/scroll_label.rs +++ b/crates/kas-widgets/src/scroll_label.rs @@ -61,12 +61,8 @@ impl_scope! { self.bar.set_value(cx, self.view_offset.1); } - fn l_find_id(&mut self, coord: Coord) -> Option { - if !self.rect().contains(coord) { - return None; - } - - self.bar.find_id(coord).or_else(|| Some(self.id())) + fn l_find_id(&mut self, coord: Coord) -> Id { + self.bar.find_id(coord).unwrap_or_else(|| self.id()) } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/scroll_text.rs b/crates/kas-widgets/src/scroll_text.rs index 4798f6e09..18a4510d8 100644 --- a/crates/kas-widgets/src/scroll_text.rs +++ b/crates/kas-widgets/src/scroll_text.rs @@ -61,12 +61,8 @@ impl_scope! { self.bar.set_value(cx, self.view_offset.1); } - fn l_find_id(&mut self, coord: Coord) -> Option { - if !self.rect().contains(coord) { - return None; - } - - self.bar.find_id(coord).or_else(|| Some(self.id())) + fn l_find_id(&mut self, coord: Coord) -> Id { + self.bar.find_id(coord).unwrap_or_else(|| self.id()) } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/slider.rs b/crates/kas-widgets/src/slider.rs index 63eb9a630..90b12f64b 100644 --- a/crates/kas-widgets/src/slider.rs +++ b/crates/kas-widgets/src/slider.rs @@ -311,16 +311,13 @@ impl_scope! { let _ = self.grip.set_size_and_offset(size, self.offset()); } - fn l_find_id(&mut self, coord: Coord) -> Option { - if !self.rect().contains(coord) { - return None; - } + fn l_find_id(&mut self, coord: Coord) -> Id { if self.on_move.is_some() { if let Some(id) = self.grip.find_id(coord) { - return Some(id); + return id; } } - Some(self.id()) + self.id() } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/spinner.rs b/crates/kas-widgets/src/spinner.rs index 11e4bf602..a635577d5 100644 --- a/crates/kas-widgets/src/spinner.rs +++ b/crates/kas-widgets/src/spinner.rs @@ -286,10 +286,10 @@ impl_scope! { self.edit.set_outer_rect(rect, FrameStyle::EditBox); } - fn l_find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Id { self.b_up.find_id(coord) .or_else(|| self.b_down.find_id(coord)) - .or_else(|| Some(self.edit.id())) + .unwrap_or_else(|| self.edit.id()) } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/splitter.rs b/crates/kas-widgets/src/splitter.rs index 87f4161e0..391513b44 100644 --- a/crates/kas-widgets/src/splitter.rs +++ b/crates/kas-widgets/src/splitter.rs @@ -213,9 +213,10 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Option { - if !self.rect().contains(coord) || !self.size_solved { - return None; + fn l_find_id(&mut self, coord: Coord) -> Id { + if !self.size_solved { + debug_assert!(false); + return self.id(); } // find_child should gracefully handle the case that a coord is between @@ -224,19 +225,20 @@ impl_scope! { let solver = layout::RowPositionSolver::new(self.direction); if let Some(child) = solver.find_child_mut(&mut self.widgets, coord) { - return child.find_id(coord).or_else(|| Some(self.id())); + return child.find_id(coord).unwrap_or_else(|| self.id()); } let solver = layout::RowPositionSolver::new(self.direction); if let Some(child) = solver.find_child_mut(&mut self.grips, coord) { - return child.find_id(coord).or_else(|| Some(self.id())); + return child.find_id(coord).unwrap_or_else(|| self.id()); } - Some(self.id()) + self.id() } fn draw(&mut self, mut draw: DrawCx) { if !self.size_solved { + debug_assert!(false); return; } // as with l_find_id, there's not much harm in invoking the solver twice diff --git a/crates/kas-widgets/src/stack.rs b/crates/kas-widgets/src/stack.rs index 57482235e..c14943447 100644 --- a/crates/kas-widgets/src/stack.rs +++ b/crates/kas-widgets/src/stack.rs @@ -127,12 +127,14 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, coord: Coord) -> Id { if let Some(entry) = self.widgets.get_mut(self.active) { debug_assert_eq!(entry.1, State::Sized); - return entry.0.find_id(coord); + if let Some(id) = entry.0.find_id(coord) { + return id; + } } - None + self.id() } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/tab_stack.rs b/crates/kas-widgets/src/tab_stack.rs index 96f3267d2..3dc332d1b 100644 --- a/crates/kas-widgets/src/tab_stack.rs +++ b/crates/kas-widgets/src/tab_stack.rs @@ -44,8 +44,8 @@ impl_scope! { } impl Layout for Self { - fn l_find_id(&mut self, coord: Coord) -> Option { - self.rect().contains(coord).then_some(self.id()) + fn l_find_id(&mut self, _: Coord) -> Id { + self.id() } } diff --git a/examples/cursors.rs b/examples/cursors.rs index e0e1d9f9b..3f405730c 100644 --- a/examples/cursors.rs +++ b/examples/cursors.rs @@ -22,9 +22,9 @@ impl_scope! { cursor: CursorIcon, } impl Layout for Self { - fn l_find_id(&mut self, coord: Coord) -> Option { + fn l_find_id(&mut self, _: Coord) -> Id { // Steal mouse focus: hover points to self, not self.label - self.rect().contains(coord).then(|| self.id()) + self.id() } } } From 1425dc232c2d43138a634bb2162d7ad57d3ca3e4 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 30 Dec 2024 10:13:15 +0000 Subject: [PATCH 4/4] Rename fn Layout::l_find_id -> probe and fn Tile::find_id -> try_probe --- crates/kas-core/src/core/layout.rs | 63 +++++++++++----------- crates/kas-core/src/core/node.rs | 10 ++-- crates/kas-core/src/core/widget.rs | 6 +-- crates/kas-core/src/event/cx/cx_pub.rs | 2 +- crates/kas-core/src/event/cx/platform.rs | 10 ++-- crates/kas-core/src/event/events.rs | 4 +- crates/kas-core/src/event/mod.rs | 2 +- crates/kas-core/src/layout/visitor.rs | 50 ++++++++--------- crates/kas-core/src/root.rs | 26 ++++----- crates/kas-macros/src/make_layout.rs | 4 +- crates/kas-macros/src/widget.rs | 22 ++++---- crates/kas-macros/src/widget_derive.rs | 20 +++---- crates/kas-view/src/list_view.rs | 4 +- crates/kas-view/src/matrix_view.rs | 4 +- crates/kas-widgets/src/adapt/with_label.rs | 2 +- crates/kas-widgets/src/check_box.rs | 2 +- crates/kas-widgets/src/edit.rs | 6 +-- crates/kas-widgets/src/grid.rs | 4 +- crates/kas-widgets/src/list.rs | 4 +- crates/kas-widgets/src/menu/menu_entry.rs | 4 +- crates/kas-widgets/src/menu/menubar.rs | 4 +- crates/kas-widgets/src/menu/mod.rs | 2 +- crates/kas-widgets/src/menu/submenu.rs | 6 +-- crates/kas-widgets/src/radio_box.rs | 2 +- crates/kas-widgets/src/scroll.rs | 4 +- crates/kas-widgets/src/scroll_bar.rs | 12 ++--- crates/kas-widgets/src/scroll_label.rs | 4 +- crates/kas-widgets/src/scroll_text.rs | 4 +- crates/kas-widgets/src/slider.rs | 4 +- crates/kas-widgets/src/spinner.rs | 6 +-- crates/kas-widgets/src/splitter.rs | 8 +-- crates/kas-widgets/src/stack.rs | 4 +- crates/kas-widgets/src/tab_stack.rs | 2 +- examples/cursors.rs | 2 +- 34 files changed, 157 insertions(+), 156 deletions(-) diff --git a/crates/kas-core/src/core/layout.rs b/crates/kas-core/src/core/layout.rs index 5f2e6f257..2b440b7f9 100644 --- a/crates/kas-core/src/core/layout.rs +++ b/crates/kas-core/src/core/layout.rs @@ -42,7 +42,7 @@ use kas_macros::autoimpl; /// cached by `size_rules`. /// 4. The widget is updated again after any data change (see [`ConfigCx::update`]). /// 5. The widget is ready for event-handling and drawing ([`Events`], -/// [`Self::find_id`], [`Self::draw`]). +/// [`Self::try_probe`], [`Self::draw`]). /// /// Widgets are responsible for ensuring that their children may observe this /// lifecycle. Usually this simply involves inclusion of the child in layout @@ -176,7 +176,7 @@ pub trait Layout { /// Required: [`Self::size_rules`] is called for both axes before this /// method is called, and that this method has been called *after* the last /// call to [`Self::size_rules`] *before* any of the following methods: - /// [`Layout::find_id`], [`Layout::draw`], [`Events::handle_event`]. + /// [`Layout::try_probe`], [`Layout::draw`], [`Events::handle_event`]. /// /// Default implementation when not using the `layout` property: set `rect` /// field of `widget_core!()` to the input `rect`. @@ -216,7 +216,7 @@ pub trait Layout { /// *and* child widgets need to implement this. /// Such widgets must also implement [`Events::handle_scroll`]. /// - /// Affects event handling via [`Layout::find_id`] and affects the positioning + /// Affects event handling via [`Layout::probe`] and affects the positioning /// of pop-up menus. [`Layout::draw`] must be implemented directly using /// [`DrawCx::with_clip_region`] to offset contents. /// @@ -226,14 +226,19 @@ pub trait Layout { Offset::ZERO } - /// Translate a coordinate to an [`Id`] + /// Probe a coordinate for a widget's [`Id`] /// - /// This method is used to determine which widget reacts to the mouse cursor - /// or a touch event. The result affects mouse-hover highlighting, event - /// handling by the target, and potentially also event handling by other - /// widgets (e.g. a `Label` widget will not handle touch events, but if it - /// is contained by a `ScrollRegion`, that widget may capture these via - /// [`Events::handle_event`] to implement touch scrolling). + /// Returns the [`Id`] of the lowest descendant (leaf-most element of the + /// widget tree) occupying `coord` (exceptions possible; see below). + /// + /// The callee may assume that it occupies `coord`. + /// Callers should prefer to call [`Tile::try_probe`] instead. + /// + /// This method is used to determine which widget reacts to the mouse and + /// touch events at the given coordinates. The widget identified by this + /// method may be highlighted (if hovered by the mouse) and may respond to + /// click/touch events. Unhandled click/touch events are passed to the + /// parent widget and so on up the widget tree. /// /// The result is usually the widget which draws at the given `coord`, but /// does not have to be. For example, a `Button` widget will return its own @@ -241,47 +246,43 @@ pub trait Layout { /// widget uses an internal component for event handling and thus reports /// this component's `id` even over its own area. /// + /// ### Call order + /// /// It is expected that [`Layout::set_rect`] is called before this method, /// but failure to do so should not cause a fatal error. /// - /// The default implementation suffices for widgets without children as well - /// as widgets using the `layout` property of [`#[widget]`](crate::widget). - /// Custom implementations may be required if: - /// - /// - A custom [`Layout`] implementation is used - /// - Event stealing or donation is desired (but note that - /// `layout = button: ..;` does this already) + /// ### Default implementation /// - /// When writing a custom implementation: - /// - /// - Widgets may assume that `self.rect().contains(coord)`. - /// - If the Widget uses a translated coordinate space (i.e. - /// `self.translation() != Offset::ZERO`) then pass - /// `coord + self.translation()` to children. - /// - /// The default implementation is non-trivial: + /// The default macro-generated implementation considers all children of the + /// `layout` property and of [`#[widget]`](crate::widget) fields: /// ```ignore /// let coord = coord + self.translation(); /// for child in ITER_OVER_CHILDREN { - /// if let Some(id) = child.find_id(coord) { + /// if let Some(id) = child.try_probe(coord) { /// return Some(id); /// } /// } /// self.id() /// ``` - fn l_find_id(&mut self, coord: Coord) -> Id { + fn probe(&mut self, coord: Coord) -> Id { let _ = coord; unimplemented!() // make rustdoc show that this is a provided method } - /// Translate a coordinate to an [`Id`] + /// Probe a coordinate for a widget's [`Id`] + /// + /// Returns the [`Id`] of the lowest descendant (leaf-most element of the + /// widget tree) occupying `coord`, if any. + /// + /// This method returns `None` if `!self.rect().contains(coord)`, otherwise + /// returning the result of [`Layout::probe`]. /// - /// This tests whether `self.rect().contains(coord)`, then calls [`Layout::l_find_id`]. + /// ### Call order /// /// It is expected that [`Tile::set_rect`] is called before this method, /// but failure to do so should not cause a fatal error. - fn find_id(&mut self, coord: Coord) -> Option { - self.rect().contains(coord).then(|| self.l_find_id(coord)) + fn try_probe(&mut self, coord: Coord) -> Option { + self.rect().contains(coord).then(|| self.probe(coord)) } /// Draw a widget and its children diff --git a/crates/kas-core/src/core/node.rs b/crates/kas-core/src/core/node.rs index 0019fb2fc..b3f4c288c 100644 --- a/crates/kas-core/src/core/node.rs +++ b/crates/kas-core/src/core/node.rs @@ -28,7 +28,7 @@ trait NodeT { fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect, hints: AlignHints); fn nav_next(&self, reverse: bool, from: Option) -> Option; - fn find_id(&mut self, coord: Coord) -> Option; + fn try_probe(&mut self, coord: Coord) -> Option; fn _draw(&mut self, draw: DrawCx); fn _configure(&mut self, cx: &mut ConfigCx, id: Id); @@ -80,8 +80,8 @@ impl<'a, T> NodeT for (&'a mut dyn Widget, &'a T) { fn nav_next(&self, reverse: bool, from: Option) -> Option { self.0.nav_next(reverse, from) } - fn find_id(&mut self, coord: Coord) -> Option { - self.0.find_id(coord) + fn try_probe(&mut self, coord: Coord) -> Option { + self.0.try_probe(coord) } fn _draw(&mut self, mut draw: DrawCx) { draw.recurse(&mut self.0); @@ -303,8 +303,8 @@ impl<'a> Node<'a> { } /// Translate a coordinate to an [`Id`] - pub(crate) fn find_id(&mut self, coord: Coord) -> Option { - self.0.find_id(coord) + pub(crate) fn try_probe(&mut self, coord: Coord) -> Option { + self.0.try_probe(coord) } cfg_if::cfg_if! { diff --git a/crates/kas-core/src/core/widget.rs b/crates/kas-core/src/core/widget.rs index 3cde1570a..92982ef4a 100644 --- a/crates/kas-core/src/core/widget.rs +++ b/crates/kas-core/src/core/widget.rs @@ -31,7 +31,7 @@ use kas_macros::autoimpl; /// cached by `size_rules`. /// 4. The widget is updated again after any data change (see [`ConfigCx::update`]). /// 5. The widget is ready for event-handling and drawing -/// ([`Events::handle_event`], [`Layout::find_id`], [`Layout::draw`]). +/// ([`Events::handle_event`], [`Layout::try_probe`], [`Layout::draw`]). /// /// Widgets are responsible for ensuring that their children may observe this /// lifecycle. Usually this simply involves inclusion of the child in layout @@ -256,7 +256,7 @@ pub enum NavAdvance { /// cached by `size_rules`. /// 4. The widget is updated again after any data change (see [`ConfigCx::update`]). /// 5. The widget is ready for event-handling and drawing -/// ([`Events::handle_event`], [`Layout::find_id`], [`Layout::draw`]). +/// ([`Events::handle_event`], [`Layout::try_probe`], [`Layout::draw`]). /// /// Widgets are responsible for ensuring that their children may observe this /// lifecycle. Usually this simply involves inclusion of the child in layout @@ -310,7 +310,7 @@ pub enum NavAdvance { /// - **Layout** is specified either via [layout syntax](macros::widget#layout-1) /// or via implementation of at least [`Layout::size_rules`] and /// [`Layout::draw`] (optionally also `set_rect`, `nav_next`, `translation` -/// and `l_find_id`). +/// and `probe`). ///- **Event handling** is optional, implemented through [`Events`]. /// /// For examples, check the source code of widgets in the widgets library diff --git a/crates/kas-core/src/event/cx/cx_pub.rs b/crates/kas-core/src/event/cx/cx_pub.rs index 5a355748e..d36e05655 100644 --- a/crates/kas-core/src/event/cx/cx_pub.rs +++ b/crates/kas-core/src/event/cx/cx_pub.rs @@ -717,7 +717,7 @@ impl<'a> EventCx<'a> { /// /// When calling this method, be aware that some widgets use an inner /// component to handle events, thus calling with the outer widget's `id` - /// may not have the desired effect. [`Layout::find_id`] and + /// may not have the desired effect. [`Layout::try_probe`] and /// [`EventState::next_nav_focus`] are usually able to find the appropriate /// event-handling target. pub fn send_command(&mut self, id: Id, cmd: Command) { diff --git a/crates/kas-core/src/event/cx/platform.rs b/crates/kas-core/src/event/cx/platform.rs index fd2bcb12c..8ce22141a 100644 --- a/crates/kas-core/src/event/cx/platform.rs +++ b/crates/kas-core/src/event/cx/platform.rs @@ -266,11 +266,11 @@ impl EventState { cx.action.remove(Action::REGION_MOVED); // Update hovered widget - let hover = win.find_id(data, cx.last_mouse_coord); + let hover = win.try_probe(data, cx.last_mouse_coord); cx.set_hover(win.as_node(data), hover); for grab in cx.touch_grab.iter_mut() { - grab.cur_id = win.find_id(data, grab.coord); + grab.cur_id = win.try_probe(data, grab.coord); } } }); @@ -408,7 +408,7 @@ impl<'a> EventCx<'a> { let coord = position.cast_approx(); // Update hovered win - let id = win.find_id(data, coord); + let id = win.try_probe(data, coord); self.set_hover(win.as_node(data), id.clone()); if let Some(grab) = self.state.mouse_grab.as_mut() { @@ -527,7 +527,7 @@ impl<'a> EventCx<'a> { let coord = touch.location.cast_approx(); match touch.phase { TouchPhase::Started => { - let start_id = win.find_id(data, coord); + let start_id = win.try_probe(data, coord); if let Some(id) = start_id.as_ref() { if self.config.event().touch_nav_focus() { if let Some(id) = @@ -547,7 +547,7 @@ impl<'a> EventCx<'a> { } } TouchPhase::Moved => { - let cur_id = win.find_id(data, coord); + let cur_id = win.try_probe(data, coord); let mut redraw = false; let mut pan_grab = None; diff --git a/crates/kas-core/src/event/events.rs b/crates/kas-core/src/event/events.rs index 611ff0e60..3c8af3c96 100644 --- a/crates/kas-core/src/event/events.rs +++ b/crates/kas-core/src/event/events.rs @@ -152,7 +152,7 @@ pub enum Event { /// Motion events for the grabbed mouse pointer or touched finger are sent. /// /// If `cur_id` is `None`, no widget was found at the coordinate (either - /// outside the window or [`crate::Layout::find_id`] failed). + /// outside the window or [`crate::Layout::try_probe`] failed). PressMove { press: Press, delta: Offset }, /// End of a click/touch press /// @@ -168,7 +168,7 @@ pub enum Event { /// sent. /// /// If `cur_id` is `None`, no widget was found at the coordinate (either - /// outside the window or [`crate::Layout::find_id`] failed). + /// outside the window or [`crate::Layout::try_probe`] failed). PressEnd { press: Press, success: bool }, /// Update from a timer /// diff --git a/crates/kas-core/src/event/mod.rs b/crates/kas-core/src/event/mod.rs index 5ec4f7f74..c869bf5f9 100644 --- a/crates/kas-core/src/event/mod.rs +++ b/crates/kas-core/src/event/mod.rs @@ -16,7 +16,7 @@ //! //! 1. Determine the target's [`Id`]. For example, this may be //! the [`nav_focus`](EventState::nav_focus) or may be determined from -//! from mouse/touch coordinates by calling [`find_id`](crate::Layout::find_id). +//! from mouse/touch coordinates by calling [`try_probe`](crate::Layout::try_probe). //! 2. If the target is [disabled](EventState::is_disabled), then find the //! top-most ancestor which is disabled and make that the target, but //! inhibit calling of [`Events::handle_event`] on this widget (but still diff --git a/crates/kas-core/src/layout/visitor.rs b/crates/kas-core/src/layout/visitor.rs index 753ea9582..661d67cc8 100644 --- a/crates/kas-core/src/layout/visitor.rs +++ b/crates/kas-core/src/layout/visitor.rs @@ -41,7 +41,7 @@ pub trait Visitable { /// Returns the [`Id`] of a child when some child occupies `coord`. Returns /// [`None`] when there is no (probable) child widget at `coord`, in which /// case the caller may use its own [`Id`]. - fn find_id(&mut self, coord: Coord) -> Option; + fn try_probe(&mut self, coord: Coord) -> Option; /// Draw a widget and its children /// @@ -225,14 +225,14 @@ impl Visitor { /// /// 1. Return `None` if `!self.rect().contains(coord)` /// 2. Translate `coord`: `let coord = coord + self.translation();` - /// 3. Call `find_id` (this method), returning its result if not `None` + /// 3. Call `try_probe` (this method), returning its result if not `None` /// 4. Otherwise return `Some(self.id())` #[inline] - pub fn find_id(mut self, coord: Coord) -> Option { - self.find_id_(coord) + pub fn try_probe(mut self, coord: Coord) -> Option { + self.try_probe_(coord) } - fn find_id_(&mut self, coord: Coord) -> Option { - self.0.find_id(coord) + fn try_probe_(&mut self, coord: Coord) -> Option { + self.0.try_probe(coord) } /// Draw a widget and its children @@ -256,8 +256,8 @@ impl Visitable for Visitor { self.set_rect_(cx, rect, hints); } - fn find_id(&mut self, coord: Coord) -> Option { - self.find_id_(coord) + fn try_probe(&mut self, coord: Coord) -> Option { + self.try_probe_(coord) } fn draw(&mut self, draw: DrawCx) { @@ -278,8 +278,8 @@ impl<'a> Visitable for Single<'a> { self.widget.set_rect(cx, rect, hints); } - fn find_id(&mut self, coord: Coord) -> Option { - self.widget.find_id(coord) + fn try_probe(&mut self, coord: Coord) -> Option { + self.widget.try_probe(coord) } fn draw(&mut self, mut draw: DrawCx) { @@ -302,8 +302,8 @@ impl Visitable for Align { self.child.set_rect(cx, rect, hints); } - fn find_id(&mut self, coord: Coord) -> Option { - self.child.find_id(coord) + fn try_probe(&mut self, coord: Coord) -> Option { + self.child.try_probe(coord) } fn draw(&mut self, draw: DrawCx) { @@ -333,8 +333,8 @@ impl<'a, C: Visitable> Visitable for Pack<'a, C> { self.child.set_rect(cx, rect, hints); } - fn find_id(&mut self, coord: Coord) -> Option { - self.child.find_id(coord) + fn try_probe(&mut self, coord: Coord) -> Option { + self.child.try_probe(coord) } fn draw(&mut self, draw: DrawCx) { @@ -369,8 +369,8 @@ impl Visitable for Margins { self.child.set_rect(cx, rect, hints); } - fn find_id(&mut self, coord: Coord) -> Option { - self.child.find_id(coord) + fn try_probe(&mut self, coord: Coord) -> Option { + self.child.try_probe(coord) } fn draw(&mut self, draw: DrawCx) { @@ -402,8 +402,8 @@ impl<'a, C: Visitable> Visitable for Frame<'a, C> { self.child.set_rect(cx, child_rect, hints); } - fn find_id(&mut self, coord: Coord) -> Option { - self.child.find_id(coord) + fn try_probe(&mut self, coord: Coord) -> Option { + self.child.try_probe(coord) } fn draw(&mut self, mut draw: DrawCx) { @@ -435,7 +435,7 @@ impl<'a, C: Visitable> Visitable for Button<'a, C> { self.child.set_rect(cx, child_rect, AlignHints::CENTER); } - fn find_id(&mut self, _: Coord) -> Option { + fn try_probe(&mut self, _: Coord) -> Option { // Buttons steal clicks, hence Button never returns ID of content None } @@ -483,11 +483,11 @@ where } } - fn find_id(&mut self, coord: Coord) -> Option { + fn try_probe(&mut self, coord: Coord) -> Option { // TODO(opt): more efficient search strategy? for i in 0..self.children.len() { if let Some(child) = self.children.get_item(i) { - if let Some(id) = child.find_id(coord) { + if let Some(id) = child.try_probe(coord) { return Some(id); } } @@ -531,10 +531,10 @@ where } } - fn find_id(&mut self, coord: Coord) -> Option { + fn try_probe(&mut self, coord: Coord) -> Option { for i in 0..self.children.len() { if let Some(child) = self.children.get_item(i) { - if let Some(id) = child.find_id(coord) { + if let Some(id) = child.try_probe(coord) { return Some(id); } } @@ -587,11 +587,11 @@ where } } - fn find_id(&mut self, coord: Coord) -> Option { + fn try_probe(&mut self, coord: Coord) -> Option { // TODO(opt): more efficient search strategy? for i in 0..self.children.len() { if let Some(child) = self.children.get_item(i) { - if let Some(id) = child.find_id(coord) { + if let Some(id) = child.try_probe(coord) { return Some(id); } } diff --git a/crates/kas-core/src/root.rs b/crates/kas-core/src/root.rs index 293db07d0..d8c73ef6d 100644 --- a/crates/kas-core/src/root.rs +++ b/crates/kas-core/src/root.rs @@ -146,7 +146,7 @@ impl_scope! { self.inner.set_rect(cx, Rect::new(p_in, s_in), hints); } - fn l_find_id(&mut self, _: Coord) -> Id { + fn probe(&mut self, _: Coord) -> Id { unimplemented!() } @@ -156,29 +156,29 @@ impl_scope! { } impl Self { - pub(crate) fn find_id(&mut self, data: &Data, coord: Coord) -> Option { + pub(crate) fn try_probe(&mut self, data: &Data, coord: Coord) -> Option { if !self.core.rect.contains(coord) { return None; } for (_, popup, translation) in self.popups.iter_mut().rev() { - if let Some(Some(id)) = self.inner.as_node(data).find_node(&popup.id, |mut node| node.find_id(coord + *translation)) { + if let Some(Some(id)) = self.inner.as_node(data).find_node(&popup.id, |mut node| node.try_probe(coord + *translation)) { return Some(id); } } if self.bar_h > 0 { - if let Some(id) = self.title_bar.find_id(coord) { + if let Some(id) = self.title_bar.try_probe(coord) { return Some(id); } } - self.inner.find_id(coord) - .or_else(|| self.b_w.find_id(coord)) - .or_else(|| self.b_e.find_id(coord)) - .or_else(|| self.b_n.find_id(coord)) - .or_else(|| self.b_s.find_id(coord)) - .or_else(|| self.b_nw.find_id(coord)) - .or_else(|| self.b_ne.find_id(coord)) - .or_else(|| self.b_sw.find_id(coord)) - .or_else(|| self.b_se.find_id(coord)) + self.inner.try_probe(coord) + .or_else(|| self.b_w.try_probe(coord)) + .or_else(|| self.b_e.try_probe(coord)) + .or_else(|| self.b_n.try_probe(coord)) + .or_else(|| self.b_s.try_probe(coord)) + .or_else(|| self.b_nw.try_probe(coord)) + .or_else(|| self.b_ne.try_probe(coord)) + .or_else(|| self.b_sw.try_probe(coord)) + .or_else(|| self.b_se.try_probe(coord)) .or_else(|| Some(self.id())) } diff --git a/crates/kas-macros/src/make_layout.rs b/crates/kas-macros/src/make_layout.rs index 72bcc579d..072fcec98 100644 --- a/crates/kas-macros/src/make_layout.rs +++ b/crates/kas-macros/src/make_layout.rs @@ -195,14 +195,14 @@ impl Tree { ::kas::layout::LayoutVisitor::layout_visitor(self).set_rect(cx, rect, hints); } - fn l_find_id(&mut self, coord: ::kas::geom::Coord) -> ::kas::Id { + fn probe(&mut self, coord: ::kas::geom::Coord) -> ::kas::Id { use ::kas::{Layout, LayoutExt, layout::LayoutVisitor}; #[cfg(debug_assertions)] #core_path.status.require_rect(&#core_path.id); let coord = coord + self.translation(); self.layout_visitor() - .find_id(coord) + .try_probe(coord) .unwrap_or_else(|| self.id()) } diff --git a/crates/kas-macros/src/widget.rs b/crates/kas-macros/src/widget.rs index 8299bdf05..6708151d4 100644 --- a/crates/kas-macros/src/widget.rs +++ b/crates/kas-macros/src/widget.rs @@ -383,7 +383,7 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul let mut fn_nav_next_err = None; let mut fn_size_rules = None; let mut set_rect = quote! { self.#core.rect = rect; }; - let mut l_find_id = quote! { + let mut probe = quote! { use ::kas::{Layout, LayoutExt}; self.id() }; @@ -422,12 +422,12 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul #core_path.rect = rect; ::kas::layout::LayoutVisitor::layout_visitor(self).set_rect(cx, rect, hints); }; - l_find_id = quote! { + probe = quote! { use ::kas::{Layout, LayoutExt, layout::LayoutVisitor}; let coord = coord + self.translation(); self.layout_visitor() - .find_id(coord) + .try_probe(coord) .unwrap_or_else(|| self.id()) }; fn_draw = Some(quote! { @@ -457,12 +457,12 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul #set_rect } }; - let fn_l_find_id = quote! { - fn l_find_id(&mut self, coord: ::kas::geom::Coord) -> ::kas::Id { + let fn_probe = quote! { + fn probe(&mut self, coord: ::kas::geom::Coord) -> ::kas::Id { #[cfg(debug_assertions)] #core_path.status.require_rect(&#core_path.id); - #l_find_id + #probe } }; @@ -598,7 +598,7 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul } } - if let Some((index, _)) = item_idents.iter().find(|(_, ident)| *ident == "l_find_id") { + if let Some((index, _)) = item_idents.iter().find(|(_, ident)| *ident == "probe") { if let Some(ref core) = core_data { if let ImplItem::Fn(f) = &mut layout_impl.items[*index] { f.block.stmts.insert(0, parse_quote! { @@ -608,14 +608,14 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul } } } else { - layout_impl.items.push(Verbatim(fn_l_find_id)); + layout_impl.items.push(Verbatim(fn_probe)); } - if let Some((index, _)) = item_idents.iter().find(|(_, ident)| *ident == "find_id") { + if let Some((index, _)) = item_idents.iter().find(|(_, ident)| *ident == "try_probe") { if let ImplItem::Fn(f) = &mut layout_impl.items[*index] { emit_warning!( f, - "Implementations are expected to impl `fn l_find_id`, not `find_id`" + "Implementations are expected to impl `fn probe`, not `try_probe`" ); } } @@ -645,7 +645,7 @@ pub fn widget(attr_span: Span, mut args: WidgetArgs, scope: &mut Scope) -> Resul #fn_size_rules #fn_set_rect #fn_nav_next - #fn_l_find_id + #fn_probe #fn_draw } }); diff --git a/crates/kas-macros/src/widget_derive.rs b/crates/kas-macros/src/widget_derive.rs index 8cf339238..55b43cb5c 100644 --- a/crates/kas-macros/src/widget_derive.rs +++ b/crates/kas-macros/src/widget_derive.rs @@ -161,10 +161,10 @@ pub fn widget(_attr_span: Span, args: WidgetArgs, scope: &mut Scope) -> Result<( self.#inner.translation() } }; - let fn_find_id_forward = quote! { + let fn_try_probe_forward = quote! { #[inline] - fn find_id(&mut self, coord: ::kas::geom::Coord) -> Option<::kas::Id> { - self.#inner.find_id(coord) + fn try_probe(&mut self, coord: ::kas::geom::Coord) -> Option<::kas::Id> { + self.#inner.try_probe(coord) } }; let fn_draw = quote! { @@ -280,18 +280,18 @@ pub fn widget(_attr_span: Span, args: WidgetArgs, scope: &mut Scope) -> Result<( layout_impl.items.push(Verbatim(fn_translation)); } - if has_item("l_find_id") { - // Use default Layout::find_id impl + if has_item("probe") { + // Use default Layout::try_probe impl } else { - // Use default Layout::l_find_id (unimplemented) - layout_impl.items.push(Verbatim(fn_find_id_forward)); + // Use default Layout::probe (unimplemented) + layout_impl.items.push(Verbatim(fn_try_probe_forward)); } - if let Some((index, _)) = item_idents.iter().find(|(_, ident)| *ident == "find_id") { + if let Some((index, _)) = item_idents.iter().find(|(_, ident)| *ident == "try_probe") { if let syn::ImplItem::Fn(f) = &mut layout_impl.items[*index] { emit_warning!( f, - "Implementations are expected to impl `fn l_find_id`, not `find_id`" + "Implementations are expected to impl `fn probe`, not `try_probe`" ); } } @@ -307,7 +307,7 @@ pub fn widget(_attr_span: Span, args: WidgetArgs, scope: &mut Scope) -> Result<( #fn_set_rect #fn_nav_next #fn_translation - #fn_find_id_forward + #fn_try_probe_forward #fn_draw } }); diff --git a/crates/kas-view/src/list_view.rs b/crates/kas-view/src/list_view.rs index ad2d9a5e1..e3739747e 100644 --- a/crates/kas-view/src/list_view.rs +++ b/crates/kas-view/src/list_view.rs @@ -553,11 +553,11 @@ impl_scope! { self.scroll_offset() } - fn l_find_id(&mut self, coord: Coord) -> Id { + fn probe(&mut self, coord: Coord) -> Id { let coord = coord + self.scroll.offset(); for child in &mut self.widgets[..self.cur_len.cast()] { if child.key.is_some() { - if let Some(id) = child.widget.find_id(coord) { + if let Some(id) = child.widget.try_probe(coord) { return id; } } diff --git a/crates/kas-view/src/matrix_view.rs b/crates/kas-view/src/matrix_view.rs index 32e27ac28..3c0b08e42 100644 --- a/crates/kas-view/src/matrix_view.rs +++ b/crates/kas-view/src/matrix_view.rs @@ -487,12 +487,12 @@ impl_scope! { self.scroll_offset() } - fn l_find_id(&mut self, coord: Coord) -> Id { + fn probe(&mut self, coord: Coord) -> Id { let num = self.num_children(); let coord = coord + self.scroll.offset(); for child in &mut self.widgets[..num] { if child.key.is_some() { - if let Some(id) = child.widget.find_id(coord) { + if let Some(id) = child.widget.try_probe(coord) { return id; } } diff --git a/crates/kas-widgets/src/adapt/with_label.rs b/crates/kas-widgets/src/adapt/with_label.rs index c8f1c352f..436db984d 100644 --- a/crates/kas-widgets/src/adapt/with_label.rs +++ b/crates/kas-widgets/src/adapt/with_label.rs @@ -113,7 +113,7 @@ impl_scope! { } impl Layout for Self { - fn l_find_id(&mut self, _: Coord) -> Id { + fn probe(&mut self, _: Coord) -> Id { self.inner.id() } } diff --git a/crates/kas-widgets/src/check_box.rs b/crates/kas-widgets/src/check_box.rs index 69e4bb5a2..a9465a524 100644 --- a/crates/kas-widgets/src/check_box.rs +++ b/crates/kas-widgets/src/check_box.rs @@ -192,7 +192,7 @@ impl_scope! { shrink_to_text(&mut self.core.rect, dir, &self.label); } - fn l_find_id(&mut self, _: Coord) -> Id { + fn probe(&mut self, _: Coord) -> Id { self.inner.id() } } diff --git a/crates/kas-widgets/src/edit.rs b/crates/kas-widgets/src/edit.rs index f12c9d484..810b04491 100644 --- a/crates/kas-widgets/src/edit.rs +++ b/crates/kas-widgets/src/edit.rs @@ -396,9 +396,9 @@ impl_scope! { self.update_scroll_bar(cx); } - fn l_find_id(&mut self, coord: Coord) -> Id { + fn probe(&mut self, coord: Coord) -> Id { if self.max_scroll_offset().1 > 0 { - if let Some(id) = self.bar.find_id(coord) { + if let Some(id) = self.bar.try_probe(coord) { return id; } } @@ -688,7 +688,7 @@ impl_scope! { self.view_offset = self.view_offset.min(self.max_scroll_offset()); } - fn l_find_id(&mut self, _: Coord) -> Id { + fn probe(&mut self, _: Coord) -> Id { self.id() } diff --git a/crates/kas-widgets/src/grid.rs b/crates/kas-widgets/src/grid.rs index 7252daa5f..ec2452dbf 100644 --- a/crates/kas-widgets/src/grid.rs +++ b/crates/kas-widgets/src/grid.rs @@ -100,10 +100,10 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Id { + fn probe(&mut self, coord: Coord) -> Id { for n in 0..self.widgets.len() { if let Some(child) = self.widgets.get_mut_layout(n) { - if let Some(id) = child.find_id(coord) { + if let Some(id) = child.try_probe(coord) { return id; } } diff --git a/crates/kas-widgets/src/list.rs b/crates/kas-widgets/src/list.rs index 5644f47cf..50e1213f9 100644 --- a/crates/kas-widgets/src/list.rs +++ b/crates/kas-widgets/src/list.rs @@ -119,11 +119,11 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Id { + fn probe(&mut self, coord: Coord) -> Id { let solver = RowPositionSolver::new(self.direction); solver .find_child_mut(&mut self.widgets, coord) - .and_then(|child| child.find_id(coord)) + .and_then(|child| child.try_probe(coord)) .unwrap_or_else(|| self.id()) } diff --git a/crates/kas-widgets/src/menu/menu_entry.rs b/crates/kas-widgets/src/menu/menu_entry.rs index 5590c86c1..14f458cda 100644 --- a/crates/kas-widgets/src/menu/menu_entry.rs +++ b/crates/kas-widgets/src/menu/menu_entry.rs @@ -31,7 +31,7 @@ impl_scope! { } impl Layout for Self { - fn l_find_id(&mut self, _: Coord) -> Id { + fn probe(&mut self, _: Coord) -> Id { self.id() } @@ -120,7 +120,7 @@ impl_scope! { } impl Layout for Self { - fn l_find_id(&mut self, _: Coord) -> Id { + fn probe(&mut self, _: Coord) -> Id { self.checkbox.id() } diff --git a/crates/kas-widgets/src/menu/menubar.rs b/crates/kas-widgets/src/menu/menubar.rs index 617f2fdf6..047b47a23 100644 --- a/crates/kas-widgets/src/menu/menubar.rs +++ b/crates/kas-widgets/src/menu/menubar.rs @@ -99,11 +99,11 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Id { + fn probe(&mut self, coord: Coord) -> Id { let solver = RowPositionSolver::new(self.direction); solver .find_child_mut(&mut self.widgets, coord) - .and_then(|child| child.find_id(coord)) + .and_then(|child| child.try_probe(coord)) .unwrap_or_else(|| self.id()) } diff --git a/crates/kas-widgets/src/menu/mod.rs b/crates/kas-widgets/src/menu/mod.rs index edfd89883..17509c2c9 100644 --- a/crates/kas-widgets/src/menu/mod.rs +++ b/crates/kas-widgets/src/menu/mod.rs @@ -48,7 +48,7 @@ pub struct SubItems<'a> { /// Trait governing menus, sub-menus and menu-entries /// /// Implementations will automatically receive nav focus on mouse-hover, thus -/// should ensure that [`Layout::l_find_id`] returns the identifier of the widget +/// should ensure that [`Layout::probe`] returns the identifier of the widget /// which should be focussed, and that this widget has /// [`Events::navigable`] return true. #[autoimpl(for Box)] diff --git a/crates/kas-widgets/src/menu/submenu.rs b/crates/kas-widgets/src/menu/submenu.rs index c087d9338..66b078c90 100644 --- a/crates/kas-widgets/src/menu/submenu.rs +++ b/crates/kas-widgets/src/menu/submenu.rs @@ -101,7 +101,7 @@ impl_scope! { None } - fn l_find_id(&mut self, _: Coord) -> Id { + fn probe(&mut self, _: Coord) -> Id { self.id() } @@ -354,9 +354,9 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Id { + fn probe(&mut self, coord: Coord) -> Id { for child in self.list.iter_mut() { - if let Some(id) = child.find_id(coord) { + if let Some(id) = child.try_probe(coord) { return id; } } diff --git a/crates/kas-widgets/src/radio_box.rs b/crates/kas-widgets/src/radio_box.rs index 877eeaf6d..053d08c6c 100644 --- a/crates/kas-widgets/src/radio_box.rs +++ b/crates/kas-widgets/src/radio_box.rs @@ -153,7 +153,7 @@ impl_scope! { crate::check_box::shrink_to_text(&mut self.core.rect, dir, &self.label); } - fn l_find_id(&mut self, _: Coord) -> Id { + fn probe(&mut self, _: Coord) -> Id { self.inner.id() } } diff --git a/crates/kas-widgets/src/scroll.rs b/crates/kas-widgets/src/scroll.rs index 323ed2bbc..5d8395ffb 100644 --- a/crates/kas-widgets/src/scroll.rs +++ b/crates/kas-widgets/src/scroll.rs @@ -123,8 +123,8 @@ impl_scope! { self.scroll_offset() } - fn l_find_id(&mut self, coord: Coord) -> Id { - self.inner.find_id(coord + self.translation()) + fn probe(&mut self, coord: Coord) -> Id { + self.inner.try_probe(coord + self.translation()) .unwrap_or_else(|| self.id()) } diff --git a/crates/kas-widgets/src/scroll_bar.rs b/crates/kas-widgets/src/scroll_bar.rs index 3da9adca3..3fac1add1 100644 --- a/crates/kas-widgets/src/scroll_bar.rs +++ b/crates/kas-widgets/src/scroll_bar.rs @@ -290,11 +290,11 @@ impl_scope! { let _ = self.update_widgets(); } - fn l_find_id(&mut self, coord: Coord) -> Id { + fn probe(&mut self, coord: Coord) -> Id { if self.invisible && self.max_value == 0 { return self.id(); } - self.grip.find_id(coord).unwrap_or_else(|| self.id()) + self.grip.try_probe(coord).unwrap_or_else(|| self.id()) } fn draw(&mut self, mut draw: DrawCx) { @@ -497,10 +497,10 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Id { - self.vert_bar.find_id(coord) - .or_else(|| self.horiz_bar.find_id(coord)) - .or_else(|| self.inner.find_id(coord)) + fn probe(&mut self, coord: Coord) -> Id { + self.vert_bar.try_probe(coord) + .or_else(|| self.horiz_bar.try_probe(coord)) + .or_else(|| self.inner.try_probe(coord)) .unwrap_or_else(|| self.id()) } diff --git a/crates/kas-widgets/src/scroll_label.rs b/crates/kas-widgets/src/scroll_label.rs index 9420982ca..072eb5542 100644 --- a/crates/kas-widgets/src/scroll_label.rs +++ b/crates/kas-widgets/src/scroll_label.rs @@ -61,8 +61,8 @@ impl_scope! { self.bar.set_value(cx, self.view_offset.1); } - fn l_find_id(&mut self, coord: Coord) -> Id { - self.bar.find_id(coord).unwrap_or_else(|| self.id()) + fn probe(&mut self, coord: Coord) -> Id { + self.bar.try_probe(coord).unwrap_or_else(|| self.id()) } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/scroll_text.rs b/crates/kas-widgets/src/scroll_text.rs index 18a4510d8..d42d1a91e 100644 --- a/crates/kas-widgets/src/scroll_text.rs +++ b/crates/kas-widgets/src/scroll_text.rs @@ -61,8 +61,8 @@ impl_scope! { self.bar.set_value(cx, self.view_offset.1); } - fn l_find_id(&mut self, coord: Coord) -> Id { - self.bar.find_id(coord).unwrap_or_else(|| self.id()) + fn probe(&mut self, coord: Coord) -> Id { + self.bar.try_probe(coord).unwrap_or_else(|| self.id()) } fn draw(&mut self, mut draw: DrawCx) { diff --git a/crates/kas-widgets/src/slider.rs b/crates/kas-widgets/src/slider.rs index 90b12f64b..ebfa1906a 100644 --- a/crates/kas-widgets/src/slider.rs +++ b/crates/kas-widgets/src/slider.rs @@ -311,9 +311,9 @@ impl_scope! { let _ = self.grip.set_size_and_offset(size, self.offset()); } - fn l_find_id(&mut self, coord: Coord) -> Id { + fn probe(&mut self, coord: Coord) -> Id { if self.on_move.is_some() { - if let Some(id) = self.grip.find_id(coord) { + if let Some(id) = self.grip.try_probe(coord) { return id; } } diff --git a/crates/kas-widgets/src/spinner.rs b/crates/kas-widgets/src/spinner.rs index a635577d5..6d8e4dc23 100644 --- a/crates/kas-widgets/src/spinner.rs +++ b/crates/kas-widgets/src/spinner.rs @@ -286,9 +286,9 @@ impl_scope! { self.edit.set_outer_rect(rect, FrameStyle::EditBox); } - fn l_find_id(&mut self, coord: Coord) -> Id { - self.b_up.find_id(coord) - .or_else(|| self.b_down.find_id(coord)) + fn probe(&mut self, coord: Coord) -> Id { + self.b_up.try_probe(coord) + .or_else(|| self.b_down.try_probe(coord)) .unwrap_or_else(|| self.edit.id()) } diff --git a/crates/kas-widgets/src/splitter.rs b/crates/kas-widgets/src/splitter.rs index 391513b44..44241efbf 100644 --- a/crates/kas-widgets/src/splitter.rs +++ b/crates/kas-widgets/src/splitter.rs @@ -213,7 +213,7 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Id { + fn probe(&mut self, coord: Coord) -> Id { if !self.size_solved { debug_assert!(false); return self.id(); @@ -225,12 +225,12 @@ impl_scope! { let solver = layout::RowPositionSolver::new(self.direction); if let Some(child) = solver.find_child_mut(&mut self.widgets, coord) { - return child.find_id(coord).unwrap_or_else(|| self.id()); + return child.try_probe(coord).unwrap_or_else(|| self.id()); } let solver = layout::RowPositionSolver::new(self.direction); if let Some(child) = solver.find_child_mut(&mut self.grips, coord) { - return child.find_id(coord).unwrap_or_else(|| self.id()); + return child.try_probe(coord).unwrap_or_else(|| self.id()); } self.id() @@ -241,7 +241,7 @@ impl_scope! { debug_assert!(false); return; } - // as with l_find_id, there's not much harm in invoking the solver twice + // as with probe, there's not much harm in invoking the solver twice let solver = layout::RowPositionSolver::new(self.direction); solver.for_children_mut(&mut self.widgets, draw.get_clip_rect(), |w| { diff --git a/crates/kas-widgets/src/stack.rs b/crates/kas-widgets/src/stack.rs index c14943447..fefbe737b 100644 --- a/crates/kas-widgets/src/stack.rs +++ b/crates/kas-widgets/src/stack.rs @@ -127,10 +127,10 @@ impl_scope! { } } - fn l_find_id(&mut self, coord: Coord) -> Id { + fn probe(&mut self, coord: Coord) -> Id { if let Some(entry) = self.widgets.get_mut(self.active) { debug_assert_eq!(entry.1, State::Sized); - if let Some(id) = entry.0.find_id(coord) { + if let Some(id) = entry.0.try_probe(coord) { return id; } } diff --git a/crates/kas-widgets/src/tab_stack.rs b/crates/kas-widgets/src/tab_stack.rs index 3dc332d1b..e89d78794 100644 --- a/crates/kas-widgets/src/tab_stack.rs +++ b/crates/kas-widgets/src/tab_stack.rs @@ -44,7 +44,7 @@ impl_scope! { } impl Layout for Self { - fn l_find_id(&mut self, _: Coord) -> Id { + fn probe(&mut self, _: Coord) -> Id { self.id() } } diff --git a/examples/cursors.rs b/examples/cursors.rs index 3f405730c..de34e1db9 100644 --- a/examples/cursors.rs +++ b/examples/cursors.rs @@ -22,7 +22,7 @@ impl_scope! { cursor: CursorIcon, } impl Layout for Self { - fn l_find_id(&mut self, _: Coord) -> Id { + fn probe(&mut self, _: Coord) -> Id { // Steal mouse focus: hover points to self, not self.label self.id() }