1use crate::{
2 element::{Element, IntoElement, Layout},
3 layout_context::LayoutContext,
4 paint_context::PaintContext,
5 ArcCow,
6};
7use anyhow::Result;
8use gpui::{geometry::Size, text_layout::LineLayout, LayoutId};
9use parking_lot::Mutex;
10use std::sync::Arc;
11
12impl<V: 'static, S: Into<ArcCow<'static, str>>> IntoElement<V> for S {
13 type Element = Text;
14
15 fn into_element(self) -> Self::Element {
16 Text { text: self.into() }
17 }
18}
19
20pub struct Text {
21 text: ArcCow<'static, str>,
22}
23
24impl<V: 'static> Element<V> for Text {
25 type PaintState = Arc<Mutex<Option<TextLayout>>>;
26
27 fn layout(
28 &mut self,
29 _view: &mut V,
30 cx: &mut LayoutContext<V>,
31 ) -> Result<(LayoutId, Self::PaintState)> {
32 let fonts = cx.platform().fonts();
33 let text_style = cx.text_style();
34 let line_height = cx.font_cache().line_height(text_style.font_size);
35 let text = self.text.clone();
36 let paint_state = Arc::new(Mutex::new(None));
37
38 let layout_id = cx.add_measured_layout_node(Default::default(), {
39 let paint_state = paint_state.clone();
40 move |_params| {
41 let line_layout = fonts.layout_line(
42 text.as_ref(),
43 text_style.font_size,
44 &[(text.len(), text_style.to_run())],
45 );
46
47 let size = Size {
48 width: line_layout.width,
49 height: line_height,
50 };
51
52 paint_state.lock().replace(TextLayout {
53 line_layout: Arc::new(line_layout),
54 line_height,
55 });
56
57 size
58 }
59 });
60
61 Ok((layout_id?, paint_state))
62 }
63
64 fn paint<'a>(
65 &mut self,
66 _view: &mut V,
67 layout: &Layout,
68 paint_state: &mut Self::PaintState,
69 cx: &mut PaintContext<V>,
70 ) {
71 let line_layout;
72 let line_height;
73 {
74 let paint_state = paint_state.lock();
75 let paint_state = paint_state
76 .as_ref()
77 .expect("measurement has not been performed");
78 line_layout = paint_state.line_layout.clone();
79 line_height = paint_state.line_height;
80 }
81
82 let text_style = cx.text_style();
83 let line =
84 gpui::text_layout::Line::new(line_layout, &[(self.text.len(), text_style.to_run())]);
85
86 let origin = layout.bounds.origin();
87 // TODO: We haven't added visible bounds to the new element system yet, so this is a placeholder.
88 let visible_bounds = layout.bounds;
89 line.paint(cx.scene, origin, visible_bounds, line_height, cx.legacy_cx);
90 }
91}
92
93pub struct TextLayout {
94 line_layout: Arc<LineLayout>,
95 line_height: f32,
96}