Fix rich_text reactive rendering when hovering links
This commit is contained in:
parent
eb81679e60
commit
7493b83031
1 changed files with 52 additions and 61 deletions
|
|
@ -30,6 +30,7 @@ where
|
|||
align_y: alignment::Vertical,
|
||||
wrapping: Wrapping,
|
||||
class: Theme::Class<'a>,
|
||||
hovered_link: Option<usize>,
|
||||
}
|
||||
|
||||
impl<'a, Link, Theme, Renderer> Rich<'a, Link, Theme, Renderer>
|
||||
|
|
@ -52,6 +53,7 @@ where
|
|||
align_y: alignment::Vertical::Top,
|
||||
wrapping: Wrapping::default(),
|
||||
class: Theme::default(),
|
||||
hovered_link: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +238,7 @@ where
|
|||
theme: &Theme,
|
||||
defaults: &renderer::Style,
|
||||
layout: Layout<'_>,
|
||||
cursor: mouse::Cursor,
|
||||
_cursor: mouse::Cursor,
|
||||
viewport: &Rectangle,
|
||||
) {
|
||||
if !layout.bounds().intersects(viewport) {
|
||||
|
|
@ -249,13 +251,8 @@ where
|
|||
|
||||
let style = theme.style(&self.class);
|
||||
|
||||
let hovered_span = cursor
|
||||
.position_in(layout.bounds())
|
||||
.and_then(|position| state.paragraph.hit_span(position));
|
||||
|
||||
for (index, span) in self.spans.as_ref().as_ref().iter().enumerate() {
|
||||
let is_hovered_link =
|
||||
span.link.is_some() && Some(index) == hovered_span;
|
||||
let is_hovered_link = Some(index) == self.hovered_link;
|
||||
|
||||
if span.highlight.is_some()
|
||||
|| span.underline
|
||||
|
|
@ -369,39 +366,45 @@ where
|
|||
shell: &mut Shell<'_, Link>,
|
||||
_viewport: &Rectangle,
|
||||
) {
|
||||
let was_hovered = self.hovered_link.is_some();
|
||||
|
||||
if let Some(position) = cursor.position_in(layout.bounds()) {
|
||||
let state = tree
|
||||
.state
|
||||
.downcast_ref::<State<Link, Renderer::Paragraph>>();
|
||||
|
||||
self.hovered_link =
|
||||
state.paragraph.hit_span(position).and_then(|span| {
|
||||
if self.spans.as_ref().as_ref().get(span)?.link.is_some() {
|
||||
Some(span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
} else {
|
||||
self.hovered_link = None;
|
||||
}
|
||||
|
||||
if was_hovered != self.hovered_link.is_some() {
|
||||
shell.request_redraw();
|
||||
}
|
||||
|
||||
match event {
|
||||
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
|
||||
if let Some(position) = cursor.position_in(layout.bounds()) {
|
||||
let state = tree
|
||||
.state
|
||||
.downcast_mut::<State<Link, Renderer::Paragraph>>();
|
||||
|
||||
if let Some(span) = state.paragraph.hit_span(position) {
|
||||
if self
|
||||
.spans
|
||||
.as_ref()
|
||||
.as_ref()
|
||||
.get(span)
|
||||
.is_some_and(|span| span.link.is_some())
|
||||
{
|
||||
state.span_pressed = Some(span);
|
||||
state.span_pressed = self.hovered_link;
|
||||
shell.capture_event();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) => {
|
||||
let state = tree
|
||||
.state
|
||||
.downcast_mut::<State<Link, Renderer::Paragraph>>();
|
||||
|
||||
if let Some(span_pressed) = state.span_pressed {
|
||||
state.span_pressed = None;
|
||||
|
||||
if let Some(position) = cursor.position_in(layout.bounds())
|
||||
{
|
||||
match state.paragraph.hit_span(position) {
|
||||
Some(span) if span == span_pressed => {
|
||||
match state.span_pressed {
|
||||
Some(span) if Some(span) == self.hovered_link => {
|
||||
if let Some(link) = self
|
||||
.spans
|
||||
.as_ref()
|
||||
|
|
@ -414,8 +417,8 @@ where
|
|||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.span_pressed = None;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -423,31 +426,19 @@ where
|
|||
|
||||
fn mouse_interaction(
|
||||
&self,
|
||||
tree: &Tree,
|
||||
layout: Layout<'_>,
|
||||
cursor: mouse::Cursor,
|
||||
_tree: &Tree,
|
||||
_layout: Layout<'_>,
|
||||
_cursor: mouse::Cursor,
|
||||
_viewport: &Rectangle,
|
||||
_renderer: &Renderer,
|
||||
) -> mouse::Interaction {
|
||||
if let Some(position) = cursor.position_in(layout.bounds()) {
|
||||
let state = tree
|
||||
.state
|
||||
.downcast_ref::<State<Link, Renderer::Paragraph>>();
|
||||
|
||||
if let Some(span) = state
|
||||
.paragraph
|
||||
.hit_span(position)
|
||||
.and_then(|span| self.spans.as_ref().as_ref().get(span))
|
||||
{
|
||||
if span.link.is_some() {
|
||||
return mouse::Interaction::Pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.hovered_link.is_some() {
|
||||
mouse::Interaction::Pointer
|
||||
} else {
|
||||
mouse::Interaction::None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn layout<Link, Renderer>(
|
||||
state: &mut State<Link, Renderer::Paragraph>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue