text.rs

 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}