text.rs

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