1use crate::{
2 AnyElement, Element, IntoAnyElement, Layout, LayoutId, Line, LineLayout, Pixels, Result, Size,
3 ViewContext,
4};
5use parking_lot::Mutex;
6use std::{marker::PhantomData, sync::Arc};
7use util::arc_cow::ArcCow;
8
9impl<S: 'static> IntoAnyElement<S> for ArcCow<'static, str> {
10 fn into_any(self) -> AnyElement<S> {
11 Text {
12 text: self,
13 state_type: PhantomData,
14 }
15 .into_any()
16 }
17}
18
19impl<V: 'static> IntoAnyElement<V> for &'static str {
20 fn into_any(self) -> AnyElement<V> {
21 Text {
22 text: ArcCow::from(self),
23 state_type: PhantomData,
24 }
25 .into_any()
26 }
27}
28
29pub struct Text<S> {
30 text: ArcCow<'static, str>,
31 state_type: PhantomData<S>,
32}
33
34impl<S: 'static> Element for Text<S> {
35 type State = S;
36 type FrameState = Arc<Mutex<Option<TextLayout>>>;
37
38 fn layout(
39 &mut self,
40 _view: &mut S,
41 cx: &mut ViewContext<S>,
42 ) -> Result<(LayoutId, Self::FrameState)> {
43 let text_system = cx.text_system().clone();
44 let text_style = cx.text_style();
45 let line_height = cx.text_system().line_height(text_style.font_size);
46 let text = self.text.clone();
47 let paint_state = Arc::new(Mutex::new(None));
48
49 let layout_id = cx.request_measured_layout(Default::default(), cx.rem_size(), {
50 let frame_state = paint_state.clone();
51 move |_, _| {
52 let line_layout = text_system.layout_str(
53 text.as_ref(),
54 text_style.font_size,
55 &[(text.len(), text_style.to_run())],
56 );
57
58 let size = Size {
59 width: line_layout.width(),
60 height: line_height,
61 };
62
63 frame_state.lock().replace(TextLayout {
64 line: Arc::new(line_layout),
65 line_height,
66 });
67
68 size
69 }
70 });
71
72 Ok((layout_id?, paint_state))
73 }
74
75 fn paint<'a>(
76 &mut self,
77 layout: Layout,
78 _: &mut Self::State,
79 paint_state: &mut Self::FrameState,
80 cx: &mut ViewContext<S>,
81 ) {
82 let bounds = layout.bounds;
83
84 let line;
85 let line_height;
86 {
87 let paint_state = paint_state.lock();
88 let paint_state = paint_state
89 .as_ref()
90 .expect("measurement has not been performed");
91 line = paint_state.line.clone();
92 line_height = paint_state.line_height;
93 }
94
95 let text_style = cx.text_style();
96
97 // todo!("We haven't added visible bounds to the new element system yet, so this is a placeholder.");
98 let visible_bounds = bounds;
99 line.paint(bounds.origin, visible_bounds, line_height, cx.legacy_cx);
100 }
101}
102
103pub struct TextLayout {
104 line: Arc<Line>,
105 line_height: Pixels,
106}