freya_markdown/
code_editor.rs1use std::borrow::Cow;
2
3use freya_code_editor::prelude::{
4 CodeEditor,
5 CodeEditorData,
6 EditorLanguage,
7 Rope,
8};
9use freya_core::prelude::*;
10use torin::prelude::*;
11
12pub type LanguageResolver = Callback<String, Option<EditorLanguage>>;
14
15#[derive(PartialEq)]
16pub(crate) struct CodeBlockEditor {
17 code: NoArgCallback<Cow<'static, str>>,
18 language: Option<String>,
19 resolver: Option<LanguageResolver>,
20 font_size: f32,
21 font_family: Cow<'static, str>,
22 key: DiffKey,
23}
24
25impl CodeBlockEditor {
26 pub(crate) fn new(
27 code: impl Into<NoArgCallback<Cow<'static, str>>>,
28 language: Option<String>,
29 resolver: Option<LanguageResolver>,
30 font_size: f32,
31 font_family: Cow<'static, str>,
32 ) -> Self {
33 Self {
34 code: code.into(),
35 language,
36 resolver,
37 font_size,
38 font_family,
39 key: DiffKey::None,
40 }
41 }
42}
43
44impl KeyExt for CodeBlockEditor {
45 fn write_key(&mut self) -> &mut DiffKey {
46 &mut self.key
47 }
48}
49
50impl Component for CodeBlockEditor {
51 fn render(&self) -> impl IntoElement {
52 let code = self.code.clone();
53 let language = self.language.clone();
54 let resolver = self.resolver.clone();
55 let font_size = self.font_size;
56 let font_family = self.font_family.clone();
57
58 let a11y_id = use_a11y();
59
60 let editor = use_state({
61 let font_family = font_family.clone();
62 move || {
63 let code = code.call();
64 let language = language
65 .zip(resolver)
66 .and_then(|(language, resolve)| resolve.call(language));
67 let mut editor = CodeEditorData::new(Rope::from_str(&code), language);
68 editor.parse();
69 editor.measure(font_size, &font_family);
70 editor
71 }
72 });
73
74 let line_height = (font_size * 1.4).floor();
75 let lines = editor.read().rope.len_lines().max(1);
76
77 rect()
78 .width(Size::fill())
79 .height(Size::px(lines as f32 * line_height))
80 .corner_radius(6.)
81 .overflow(Overflow::Clip)
82 .child(
83 CodeEditor::new(editor, a11y_id)
84 .read_only(true)
85 .gutter(false)
86 .show_whitespace(false)
87 .font_size(font_size)
88 .line_height(1.4)
89 .font_family(font_family),
90 )
91 }
92
93 fn render_key(&self) -> DiffKey {
94 self.key.clone().or(self.default_key())
95 }
96}