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,
|
align_y: alignment::Vertical,
|
||||||
wrapping: Wrapping,
|
wrapping: Wrapping,
|
||||||
class: Theme::Class<'a>,
|
class: Theme::Class<'a>,
|
||||||
|
hovered_link: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Link, Theme, Renderer> Rich<'a, Link, Theme, Renderer>
|
impl<'a, Link, Theme, Renderer> Rich<'a, Link, Theme, Renderer>
|
||||||
|
|
@ -52,6 +53,7 @@ where
|
||||||
align_y: alignment::Vertical::Top,
|
align_y: alignment::Vertical::Top,
|
||||||
wrapping: Wrapping::default(),
|
wrapping: Wrapping::default(),
|
||||||
class: Theme::default(),
|
class: Theme::default(),
|
||||||
|
hovered_link: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,7 +238,7 @@ where
|
||||||
theme: &Theme,
|
theme: &Theme,
|
||||||
defaults: &renderer::Style,
|
defaults: &renderer::Style,
|
||||||
layout: Layout<'_>,
|
layout: Layout<'_>,
|
||||||
cursor: mouse::Cursor,
|
_cursor: mouse::Cursor,
|
||||||
viewport: &Rectangle,
|
viewport: &Rectangle,
|
||||||
) {
|
) {
|
||||||
if !layout.bounds().intersects(viewport) {
|
if !layout.bounds().intersects(viewport) {
|
||||||
|
|
@ -249,13 +251,8 @@ where
|
||||||
|
|
||||||
let style = theme.style(&self.class);
|
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() {
|
for (index, span) in self.spans.as_ref().as_ref().iter().enumerate() {
|
||||||
let is_hovered_link =
|
let is_hovered_link = Some(index) == self.hovered_link;
|
||||||
span.link.is_some() && Some(index) == hovered_span;
|
|
||||||
|
|
||||||
if span.highlight.is_some()
|
if span.highlight.is_some()
|
||||||
|| span.underline
|
|| span.underline
|
||||||
|
|
@ -369,53 +366,59 @@ where
|
||||||
shell: &mut Shell<'_, Link>,
|
shell: &mut Shell<'_, Link>,
|
||||||
_viewport: &Rectangle,
|
_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 {
|
match event {
|
||||||
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
|
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => {
|
||||||
if let Some(position) = cursor.position_in(layout.bounds()) {
|
let state = tree
|
||||||
let state = tree
|
.state
|
||||||
.state
|
.downcast_mut::<State<Link, Renderer::Paragraph>>();
|
||||||
.downcast_mut::<State<Link, Renderer::Paragraph>>();
|
|
||||||
|
|
||||||
if let Some(span) = state.paragraph.hit_span(position) {
|
state.span_pressed = self.hovered_link;
|
||||||
if self
|
shell.capture_event();
|
||||||
.spans
|
|
||||||
.as_ref()
|
|
||||||
.as_ref()
|
|
||||||
.get(span)
|
|
||||||
.is_some_and(|span| span.link.is_some())
|
|
||||||
{
|
|
||||||
state.span_pressed = Some(span);
|
|
||||||
shell.capture_event();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) => {
|
Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) => {
|
||||||
let state = tree
|
let state = tree
|
||||||
.state
|
.state
|
||||||
.downcast_mut::<State<Link, Renderer::Paragraph>>();
|
.downcast_mut::<State<Link, Renderer::Paragraph>>();
|
||||||
|
|
||||||
if let Some(span_pressed) = state.span_pressed {
|
match state.span_pressed {
|
||||||
state.span_pressed = None;
|
Some(span) if Some(span) == self.hovered_link => {
|
||||||
|
if let Some(link) = self
|
||||||
if let Some(position) = cursor.position_in(layout.bounds())
|
.spans
|
||||||
{
|
.as_ref()
|
||||||
match state.paragraph.hit_span(position) {
|
.as_ref()
|
||||||
Some(span) if span == span_pressed => {
|
.get(span)
|
||||||
if let Some(link) = self
|
.and_then(|span| span.link.clone())
|
||||||
.spans
|
{
|
||||||
.as_ref()
|
shell.publish(link);
|
||||||
.as_ref()
|
|
||||||
.get(span)
|
|
||||||
.and_then(|span| span.link.clone())
|
|
||||||
{
|
|
||||||
shell.publish(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.span_pressed = None;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
@ -423,29 +426,17 @@ where
|
||||||
|
|
||||||
fn mouse_interaction(
|
fn mouse_interaction(
|
||||||
&self,
|
&self,
|
||||||
tree: &Tree,
|
_tree: &Tree,
|
||||||
layout: Layout<'_>,
|
_layout: Layout<'_>,
|
||||||
cursor: mouse::Cursor,
|
_cursor: mouse::Cursor,
|
||||||
_viewport: &Rectangle,
|
_viewport: &Rectangle,
|
||||||
_renderer: &Renderer,
|
_renderer: &Renderer,
|
||||||
) -> mouse::Interaction {
|
) -> mouse::Interaction {
|
||||||
if let Some(position) = cursor.position_in(layout.bounds()) {
|
if self.hovered_link.is_some() {
|
||||||
let state = tree
|
mouse::Interaction::Pointer
|
||||||
.state
|
} else {
|
||||||
.downcast_ref::<State<Link, Renderer::Paragraph>>();
|
mouse::Interaction::None
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mouse::Interaction::None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue