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