line_box.rs

 1use super::{AppContext, Element, MutableAppContext};
 2use crate::{
 3    fonts::{FamilyId, FontId, Properties},
 4    geometry::vector::{vec2f, Vector2F},
 5    AfterLayoutContext, Event, EventContext, LayoutContext, PaintContext, SizeConstraint,
 6};
 7
 8pub struct LineBox {
 9    child: Box<dyn Element>,
10    family_id: FamilyId,
11    font_size: f32,
12    font_properties: Properties,
13    font_id: Option<FontId>,
14    size: Option<Vector2F>,
15}
16
17impl LineBox {
18    pub fn new(family_id: FamilyId, font_size: f32, child: Box<dyn Element>) -> Self {
19        Self {
20            child,
21            family_id,
22            font_size,
23            font_properties: Properties::default(),
24            font_id: None,
25            size: None,
26        }
27    }
28}
29
30impl Element for LineBox {
31    fn layout(
32        &mut self,
33        constraint: SizeConstraint,
34        ctx: &mut LayoutContext,
35        app: &AppContext,
36    ) -> Vector2F {
37        match ctx
38            .font_cache
39            .select_font(self.family_id, &self.font_properties)
40        {
41            Ok(font_id) => {
42                self.font_id = Some(font_id);
43                let line_height = ctx.font_cache.bounding_box(font_id, self.font_size).y();
44                let child_max = vec2f(
45                    constraint.max.x(),
46                    ctx.font_cache.ascent(font_id, self.font_size)
47                        - ctx.font_cache.descent(font_id, self.font_size),
48                );
49                let child_size = self.child.layout(
50                    SizeConstraint::new(constraint.min.min(child_max), child_max),
51                    ctx,
52                    app,
53                );
54                let size = vec2f(child_size.x(), line_height);
55                self.size = Some(size);
56                size
57            }
58            Err(error) => {
59                log::error!("can't layout LineBox: {}", error);
60                self.size = Some(constraint.min);
61                constraint.min
62            }
63        }
64    }
65
66    fn after_layout(&mut self, ctx: &mut AfterLayoutContext, app: &mut MutableAppContext) {
67        self.child.after_layout(ctx, app);
68    }
69
70    fn paint(&mut self, origin: Vector2F, ctx: &mut PaintContext, app: &AppContext) {
71        if let Some(font_id) = self.font_id {
72            let descent = ctx.font_cache.descent(font_id, self.font_size);
73            self.child.paint(origin + vec2f(0.0, -descent), ctx, app);
74        }
75    }
76
77    fn size(&self) -> Option<Vector2F> {
78        self.size
79    }
80
81    fn dispatch_event(&self, event: &Event, ctx: &mut EventContext, app: &AppContext) -> bool {
82        self.child.dispatch_event(event, ctx, app)
83    }
84}