markdown preview: Allow toggling checkbox by click (#10364)

Release Notes:

- Added support for toggling a checkbox in markdown preview by clicking
on it (cmd+click)
([#5226](https://github.com/zed-industries/zed/issues/5226)).

---------

Co-authored-by: Remco Smits <62463826+RemcoSmitsDev@users.noreply.github.com>
This commit is contained in:
Bennet Bo Fenner 2024-04-11 13:09:21 +02:00 committed by GitHub
parent eb6f7c1240
commit fef0516f5b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 117 additions and 37 deletions

View file

@ -5,17 +5,22 @@ use crate::markdown_elements::{
};
use gpui::{
div, px, rems, AbsoluteLength, AnyElement, DefiniteLength, Div, Element, ElementId,
HighlightStyle, Hsla, InteractiveText, IntoElement, ParentElement, SharedString, Styled,
StyledText, TextStyle, WeakView, WindowContext,
HighlightStyle, Hsla, InteractiveText, IntoElement, Keystroke, Modifiers, ParentElement,
SharedString, Styled, StyledText, TextStyle, WeakView, WindowContext,
};
use std::{
ops::{Mul, Range},
sync::Arc,
};
use theme::{ActiveTheme, SyntaxTheme};
use ui::{h_flex, v_flex, Checkbox, LinkPreview, Selection};
use ui::{
h_flex, v_flex, Checkbox, FluentBuilder, InteractiveElement, LinkPreview, Selection,
StatefulInteractiveElement, Tooltip,
};
use workspace::Workspace;
type CheckboxClickedCallback = Arc<Box<dyn Fn(bool, Range<usize>, &mut WindowContext)>>;
pub struct RenderContext {
workspace: Option<WeakView<Workspace>>,
next_id: usize,
@ -27,6 +32,7 @@ pub struct RenderContext {
code_span_background_color: Hsla,
syntax_theme: Arc<SyntaxTheme>,
indent: usize,
checkbox_clicked_callback: Option<CheckboxClickedCallback>,
}
impl RenderContext {
@ -44,9 +50,18 @@ impl RenderContext {
text_muted_color: theme.colors().text_muted,
code_block_background_color: theme.colors().surface_background,
code_span_background_color: theme.colors().editor_document_highlight_read_background,
checkbox_clicked_callback: None,
}
}
pub fn with_checkbox_clicked_callback(
mut self,
callback: impl Fn(bool, Range<usize>, &mut WindowContext) + 'static,
) -> Self {
self.checkbox_clicked_callback = Some(Arc::new(Box::new(callback)));
self
}
fn next_id(&mut self, span: &Range<usize>) -> ElementId {
let id = format!("markdown-{}-{}-{}", self.next_id, span.start, span.end);
self.next_id += 1;
@ -138,19 +153,53 @@ fn render_markdown_list(parsed: &ParsedMarkdownList, cx: &mut RenderContext) ->
for item in &parsed.children {
let padding = rems((item.depth - 1) as f32 * 0.25);
let bullet = match item.item_type {
let bullet = match &item.item_type {
Ordered(order) => format!("{}.", order).into_any_element(),
Unordered => "".into_any_element(),
Task(checked) => div()
Task(checked, range) => div()
.id(cx.next_id(range))
.mt(px(3.))
.child(Checkbox::new(
"checkbox",
if checked {
Selection::Selected
} else {
Selection::Unselected
},
))
.child(
Checkbox::new(
"checkbox",
if *checked {
Selection::Selected
} else {
Selection::Unselected
},
)
.when_some(
cx.checkbox_clicked_callback.clone(),
|this, callback| {
this.on_click({
let range = range.clone();
move |selection, cx| {
let checked = match selection {
Selection::Selected => true,
Selection::Unselected => false,
_ => return,
};
if cx.modifiers().secondary() {
callback(checked, range.clone(), cx);
}
}
})
},
),
)
.hover(|s| s.cursor_pointer())
.tooltip(|cx| {
let secondary_modifier = Keystroke {
key: "".to_string(),
modifiers: Modifiers::secondary_key(),
ime_key: None,
};
Tooltip::text(
format!("{}-click to toggle the checkbox", secondary_modifier),
cx,
)
})
.into_any_element(),
};
let bullet = div().mr_2().child(bullet);