text.rs

  1use gpui::{
  2    color::Color,
  3    fonts::{Properties, Weight},
  4    text_layout::RunStyle,
  5    AnyElement, Element, Quad, SceneBuilder, View, ViewContext,
  6};
  7use log::LevelFilter;
  8use pathfinder_geometry::rect::RectF;
  9use simplelog::SimpleLogger;
 10use std::ops::Range;
 11
 12fn main() {
 13    SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
 14
 15    gpui::App::new(()).unwrap().run(|cx| {
 16        cx.platform().activate(true);
 17        cx.add_window(Default::default(), |_| TextView);
 18    });
 19}
 20
 21struct TextView;
 22struct TextElement;
 23
 24impl gpui::Entity for TextView {
 25    type Event = ();
 26}
 27
 28impl gpui::View for TextView {
 29    fn ui_name() -> &'static str {
 30        "View"
 31    }
 32
 33    fn render(&mut self, _: &mut gpui::ViewContext<Self>) -> AnyElement<TextView> {
 34        TextElement.into_any()
 35    }
 36}
 37
 38impl<V: View> Element<V> for TextElement {
 39    type LayoutState = ();
 40
 41    type PaintState = ();
 42
 43    fn layout(
 44        &mut self,
 45        constraint: gpui::SizeConstraint,
 46        _: &mut V,
 47        _: &mut ViewContext<V>,
 48    ) -> (pathfinder_geometry::vector::Vector2F, Self::LayoutState) {
 49        (constraint.max, ())
 50    }
 51
 52    fn paint(
 53        &mut self,
 54        scene: &mut SceneBuilder,
 55        bounds: RectF,
 56        visible_bounds: RectF,
 57        _: &mut Self::LayoutState,
 58        _: &mut V,
 59        cx: &mut ViewContext<V>,
 60    ) -> Self::PaintState {
 61        let font_size = 12.;
 62        let family = cx
 63            .font_cache
 64            .load_family(&["SF Pro Display"], &Default::default())
 65            .unwrap();
 66        let normal = RunStyle {
 67            font_id: cx
 68                .font_cache
 69                .select_font(family, &Default::default())
 70                .unwrap(),
 71            color: Color::default(),
 72            underline: Default::default(),
 73        };
 74        let bold = RunStyle {
 75            font_id: cx
 76                .font_cache
 77                .select_font(
 78                    family,
 79                    &Properties {
 80                        weight: Weight::BOLD,
 81                        ..Default::default()
 82                    },
 83                )
 84                .unwrap(),
 85            color: Color::default(),
 86            underline: Default::default(),
 87        };
 88
 89        let text = "Hello world!";
 90        let line = cx.text_layout_cache().layout_str(
 91            text,
 92            font_size,
 93            &[
 94                (1, normal),
 95                (1, bold),
 96                (1, normal),
 97                (1, bold),
 98                (text.len() - 4, normal),
 99            ],
100        );
101
102        scene.push_quad(Quad {
103            bounds,
104            background: Some(Color::white()),
105            ..Default::default()
106        });
107        line.paint(scene, bounds.origin(), visible_bounds, bounds.height(), cx);
108    }
109
110    fn rect_for_text_range(
111        &self,
112        _: Range<usize>,
113        _: RectF,
114        _: RectF,
115        _: &Self::LayoutState,
116        _: &Self::PaintState,
117        _: &V,
118        _: &ViewContext<V>,
119    ) -> Option<RectF> {
120        None
121    }
122
123    fn debug(
124        &self,
125        _: RectF,
126        _: &Self::LayoutState,
127        _: &Self::PaintState,
128        _: &V,
129        _: &ViewContext<V>,
130    ) -> gpui::json::Value {
131        todo!()
132    }
133}