Disambiguate text selectors when recording with a coordinate fallback

This commit is contained in:
Héctor Ramón Jiménez 2025-08-27 04:43:46 +02:00
parent d64cb0d9c1
commit ebaf0238a9
No known key found for this signature in database
GPG key ID: 7CC46565708259A7

View file

@ -106,19 +106,13 @@ where
layout.bounds(), layout.bounds(),
&mut state.last_hovered, &mut state.last_hovered,
on_record, on_record,
|position| { |operation| {
use widget::Operation;
let mut selector = position.find_all();
self.content.as_widget_mut().operate( self.content.as_widget_mut().operate(
&mut tree.children[0], &mut tree.children[0],
layout, layout,
renderer, renderer,
&mut operation::black_box(&mut selector), operation,
); );
selector.finish()
}, },
); );
} }
@ -322,18 +316,10 @@ where
self.bounds, self.bounds,
self.last_hovered, self.last_hovered,
on_event, on_event,
|position| { |operation| {
use widget::Operation; self.raw
.as_overlay_mut()
let mut selector = position.find_all(); .operate(layout, renderer, operation);
self.raw.as_overlay_mut().operate(
layout,
renderer,
&mut operation::black_box(&mut selector),
);
selector.finish()
}, },
); );
} }
@ -384,7 +370,7 @@ fn record<Message>(
bounds: Rectangle, bounds: Rectangle,
last_hovered: &mut Option<Rectangle>, last_hovered: &mut Option<Rectangle>,
on_record: impl Fn(Interaction) -> Message, on_record: impl Fn(Interaction) -> Message,
find: impl FnOnce(Point) -> operation::Outcome<Vec<target::Match>>, operate: impl FnMut(&mut dyn widget::Operation),
) { ) {
if let Event::Mouse(_) = event if let Event::Mouse(_) = event
&& !cursor.is_over(bounds) && !cursor.is_over(bounds)
@ -401,43 +387,80 @@ fn record<Message>(
Interaction::from_event(event) Interaction::from_event(event)
}; };
if let Some(mut interaction) = interaction { let Some(mut interaction) = interaction else {
if let Interaction::Mouse( return;
Mouse::Move(at) };
| Mouse::Press { at: Some(at), .. }
| Mouse::Release { at: Some(at), .. }
| Mouse::Click { at: Some(at), .. },
) = &mut interaction
{
if let Target::Point(position) = *at
&& let operation::Outcome::Some(targets) =
find(position + (bounds.position() - Point::ORIGIN))
&& let Some((content, visible_bounds)) =
targets.into_iter().rev().find_map(|target| {
if let target::Match::Text {
content,
visible_bounds,
..
}
| target::Match::TextInput {
content,
visible_bounds,
..
} = target
{
Some((content, visible_bounds))
} else {
None
}
})
{
*at = Target::Text(content);
*last_hovered = visible_bounds;
} else {
*last_hovered = None;
}
}
let Interaction::Mouse(
Mouse::Move(at)
| Mouse::Press { at: Some(at), .. }
| Mouse::Release { at: Some(at), .. }
| Mouse::Click { at: Some(at), .. },
) = &mut interaction
else {
shell.publish(on_record(interaction)); shell.publish(on_record(interaction));
return;
};
let Target::Point(position) = *at else {
shell.publish(on_record(interaction));
return;
};
if let Some((content, visible_bounds)) =
find_text(position + (bounds.position() - Point::ORIGIN), operate)
{
*at = Target::Text(content);
*last_hovered = visible_bounds;
} else {
*last_hovered = None;
} }
shell.publish(on_record(interaction));
}
fn find_text(
position: Point,
mut operate: impl FnMut(&mut dyn widget::Operation),
) -> Option<(String, Option<Rectangle>)> {
use widget::Operation;
let mut by_position = position.find_all();
operate(&mut operation::black_box(&mut by_position));
let operation::Outcome::Some(targets) = by_position.finish() else {
return None;
};
let (content, visible_bounds) =
targets.into_iter().rev().find_map(|target| {
if let target::Match::Text {
content,
visible_bounds,
..
}
| target::Match::TextInput {
content,
visible_bounds,
..
} = target
{
Some((content, visible_bounds))
} else {
None
}
})?;
let mut by_text = content.clone().find_all();
operate(&mut operation::black_box(&mut by_text));
let operation::Outcome::Some(texts) = by_text.finish() else {
return None;
};
if texts.len() > 1 {
return None;
}
Some((content, visible_bounds))
} }