30
30
align_y : alignment:: Vertical ,
31
31
wrapping : Wrapping ,
32
32
class : Theme :: Class < ' a > ,
33
+ hovered_link : Option < usize > ,
33
34
}
34
35
35
36
impl < ' a , Link , Theme , Renderer > Rich < ' a , Link , Theme , Renderer >
52
53
align_y : alignment:: Vertical :: Top ,
53
54
wrapping : Wrapping :: default ( ) ,
54
55
class : Theme :: default ( ) ,
56
+ hovered_link : None ,
55
57
}
56
58
}
57
59
@@ -236,7 +238,7 @@ where
236
238
theme : & Theme ,
237
239
defaults : & renderer:: Style ,
238
240
layout : Layout < ' _ > ,
239
- cursor : mouse:: Cursor ,
241
+ _cursor : mouse:: Cursor ,
240
242
viewport : & Rectangle ,
241
243
) {
242
244
if !layout. bounds ( ) . intersects ( viewport) {
@@ -249,13 +251,8 @@ where
249
251
250
252
let style = theme. style ( & self . class ) ;
251
253
252
- let hovered_span = cursor
253
- . position_in ( layout. bounds ( ) )
254
- . and_then ( |position| state. paragraph . hit_span ( position) ) ;
255
-
256
254
for ( index, span) in self . spans . as_ref ( ) . as_ref ( ) . iter ( ) . enumerate ( ) {
257
- let is_hovered_link =
258
- span. link . is_some ( ) && Some ( index) == hovered_span;
255
+ let is_hovered_link = Some ( index) == self . hovered_link ;
259
256
260
257
if span. highlight . is_some ( )
261
258
|| span. underline
@@ -369,83 +366,77 @@ where
369
366
shell : & mut Shell < ' _ , Link > ,
370
367
_viewport : & Rectangle ,
371
368
) {
369
+ let was_hovered = self . hovered_link . is_some ( ) ;
370
+
371
+ if let Some ( position) = cursor. position_in ( layout. bounds ( ) ) {
372
+ let state = tree
373
+ . state
374
+ . downcast_ref :: < State < Link , Renderer :: Paragraph > > ( ) ;
375
+
376
+ self . hovered_link =
377
+ state. paragraph . hit_span ( position) . and_then ( |span| {
378
+ if self . spans . as_ref ( ) . as_ref ( ) . get ( span) ?. link . is_some ( ) {
379
+ Some ( span)
380
+ } else {
381
+ None
382
+ }
383
+ } ) ;
384
+ } else {
385
+ self . hovered_link = None ;
386
+ }
387
+
388
+ if was_hovered != self . hovered_link . is_some ( ) {
389
+ shell. request_redraw ( ) ;
390
+ }
391
+
372
392
match event {
373
393
Event :: Mouse ( mouse:: Event :: ButtonPressed ( mouse:: Button :: Left ) ) => {
374
- if let Some ( position) = cursor. position_in ( layout. bounds ( ) ) {
375
- let state = tree
376
- . state
377
- . downcast_mut :: < State < Link , Renderer :: Paragraph > > ( ) ;
394
+ let state = tree
395
+ . state
396
+ . downcast_mut :: < State < Link , Renderer :: Paragraph > > ( ) ;
378
397
379
- if let Some ( span) = state. paragraph . hit_span ( position) {
380
- if self
381
- . spans
382
- . as_ref ( )
383
- . as_ref ( )
384
- . get ( span)
385
- . is_some_and ( |span| span. link . is_some ( ) )
386
- {
387
- state. span_pressed = Some ( span) ;
388
- shell. capture_event ( ) ;
389
- }
390
- }
391
- }
398
+ state. span_pressed = self . hovered_link ;
399
+ shell. capture_event ( ) ;
392
400
}
393
401
Event :: Mouse ( mouse:: Event :: ButtonReleased ( mouse:: Button :: Left ) ) => {
394
402
let state = tree
395
403
. state
396
404
. downcast_mut :: < State < Link , Renderer :: Paragraph > > ( ) ;
397
405
398
- if let Some ( span_pressed) = state. span_pressed {
399
- state. span_pressed = None ;
400
-
401
- if let Some ( position) = cursor. position_in ( layout. bounds ( ) )
402
- {
403
- match state. paragraph . hit_span ( position) {
404
- Some ( span) if span == span_pressed => {
405
- if let Some ( link) = self
406
- . spans
407
- . as_ref ( )
408
- . as_ref ( )
409
- . get ( span)
410
- . and_then ( |span| span. link . clone ( ) )
411
- {
412
- shell. publish ( link) ;
413
- }
414
- }
415
- _ => { }
406
+ match state. span_pressed {
407
+ Some ( span) if Some ( span) == self . hovered_link => {
408
+ if let Some ( link) = self
409
+ . spans
410
+ . as_ref ( )
411
+ . as_ref ( )
412
+ . get ( span)
413
+ . and_then ( |span| span. link . clone ( ) )
414
+ {
415
+ shell. publish ( link) ;
416
416
}
417
417
}
418
+ _ => { }
418
419
}
420
+
421
+ state. span_pressed = None ;
419
422
}
420
423
_ => { }
421
424
}
422
425
}
423
426
424
427
fn mouse_interaction (
425
428
& self ,
426
- tree : & Tree ,
427
- layout : Layout < ' _ > ,
428
- cursor : mouse:: Cursor ,
429
+ _tree : & Tree ,
430
+ _layout : Layout < ' _ > ,
431
+ _cursor : mouse:: Cursor ,
429
432
_viewport : & Rectangle ,
430
433
_renderer : & Renderer ,
431
434
) -> mouse:: Interaction {
432
- if let Some ( position) = cursor. position_in ( layout. bounds ( ) ) {
433
- let state = tree
434
- . state
435
- . downcast_ref :: < State < Link , Renderer :: Paragraph > > ( ) ;
436
-
437
- if let Some ( span) = state
438
- . paragraph
439
- . hit_span ( position)
440
- . and_then ( |span| self . spans . as_ref ( ) . as_ref ( ) . get ( span) )
441
- {
442
- if span. link . is_some ( ) {
443
- return mouse:: Interaction :: Pointer ;
444
- }
445
- }
435
+ if self . hovered_link . is_some ( ) {
436
+ mouse:: Interaction :: Pointer
437
+ } else {
438
+ mouse:: Interaction :: None
446
439
}
447
-
448
- mouse:: Interaction :: None
449
440
}
450
441
}
451
442
0 commit comments