Use pointer cursor style for clickable ranges in InteractiveText

This commit is contained in:
Max Brunsfeld 2023-11-29 12:42:09 -08:00
parent fc2251e7ed
commit 2bd428102b
2 changed files with 20 additions and 3 deletions

View file

@ -154,7 +154,6 @@ pub fn render_parsed_markdown(
); );
let runs = text_runs_for_highlights(&parsed.text, &editor_style.text, highlights); let runs = text_runs_for_highlights(&parsed.text, &editor_style.text, highlights);
// todo!("add the ability to change cursor style for link ranges")
let mut links = Vec::new(); let mut links = Vec::new();
let mut link_ranges = Vec::new(); let mut link_ranges = Vec::new();
for (range, region) in parsed.region_ranges.iter().zip(&parsed.regions) { for (range, region) in parsed.region_ranges.iter().zip(&parsed.regions) {

View file

@ -265,7 +265,9 @@ impl TextState {
pub struct InteractiveText { pub struct InteractiveText {
element_id: ElementId, element_id: ElementId,
text: StyledText, text: StyledText,
click_listener: Option<Box<dyn Fn(InteractiveTextClickEvent, &mut WindowContext<'_>)>>, click_listener:
Option<Box<dyn Fn(&[Range<usize>], InteractiveTextClickEvent, &mut WindowContext<'_>)>>,
clickable_ranges: Vec<Range<usize>>,
} }
struct InteractiveTextClickEvent { struct InteractiveTextClickEvent {
@ -284,6 +286,7 @@ impl InteractiveText {
element_id: id.into(), element_id: id.into(),
text, text,
click_listener: None, click_listener: None,
clickable_ranges: Vec::new(),
} }
} }
@ -292,7 +295,7 @@ impl InteractiveText {
ranges: Vec<Range<usize>>, ranges: Vec<Range<usize>>,
listener: impl Fn(usize, &mut WindowContext<'_>) + 'static, listener: impl Fn(usize, &mut WindowContext<'_>) + 'static,
) -> Self { ) -> Self {
self.click_listener = Some(Box::new(move |event, cx| { self.click_listener = Some(Box::new(move |ranges, event, cx| {
for (range_ix, range) in ranges.iter().enumerate() { for (range_ix, range) in ranges.iter().enumerate() {
if range.contains(&event.mouse_down_index) && range.contains(&event.mouse_up_index) if range.contains(&event.mouse_down_index) && range.contains(&event.mouse_up_index)
{ {
@ -300,6 +303,7 @@ impl InteractiveText {
} }
} }
})); }));
self.clickable_ranges = ranges;
self self
} }
} }
@ -334,6 +338,19 @@ impl Element for InteractiveText {
fn paint(self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) { fn paint(self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext) {
if let Some(click_listener) = self.click_listener { if let Some(click_listener) = self.click_listener {
if let Some(ix) = state
.text_state
.index_for_position(bounds, cx.mouse_position())
{
if self
.clickable_ranges
.iter()
.any(|range| range.contains(&ix))
{
cx.set_cursor_style(crate::CursorStyle::PointingHand)
}
}
let text_state = state.text_state.clone(); let text_state = state.text_state.clone();
let mouse_down = state.mouse_down_index.clone(); let mouse_down = state.mouse_down_index.clone();
if let Some(mouse_down_index) = mouse_down.get() { if let Some(mouse_down_index) = mouse_down.get() {
@ -343,6 +360,7 @@ impl Element for InteractiveText {
text_state.index_for_position(bounds, event.position) text_state.index_for_position(bounds, event.position)
{ {
click_listener( click_listener(
&self.clickable_ranges,
InteractiveTextClickEvent { InteractiveTextClickEvent {
mouse_down_index, mouse_down_index,
mouse_up_index, mouse_up_index,