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}