1use anyhow::{anyhow, Result};
2use derive_more::{Deref, DerefMut};
3use gpui::{geometry::Size, MeasureParams, RenderContext, ViewContext};
4pub use gpui::{taffy::tree::NodeId, LayoutContext as LegacyLayoutContext};
5
6use crate::{element::Layout, style::Style};
7
8#[derive(Deref, DerefMut)]
9pub struct LayoutContext<'a, 'b, 'c, 'd, V> {
10 #[deref]
11 #[deref_mut]
12 pub(crate) legacy_cx: &'d mut LegacyLayoutContext<'a, 'b, 'c, V>,
13}
14
15impl<'a, 'b, V> RenderContext<'a, 'b, V> for LayoutContext<'a, 'b, '_, '_, V> {
16 fn text_style(&self) -> gpui::fonts::TextStyle {
17 self.legacy_cx.text_style()
18 }
19
20 fn push_text_style(&mut self, style: gpui::fonts::TextStyle) {
21 self.legacy_cx.push_text_style(style)
22 }
23
24 fn pop_text_style(&mut self) {
25 self.legacy_cx.pop_text_style()
26 }
27
28 fn as_view_context(&mut self) -> &mut ViewContext<'a, 'b, V> {
29 &mut self.view_context
30 }
31}
32
33impl<'a, 'b, 'c, 'd, V: 'static> LayoutContext<'a, 'b, 'c, 'd, V> {
34 pub fn new(legacy_cx: &'d mut LegacyLayoutContext<'a, 'b, 'c, V>) -> Self {
35 Self { legacy_cx }
36 }
37
38 pub fn add_layout_node<D>(
39 &mut self,
40 style: Style,
41 element_data: D,
42 children: impl IntoIterator<Item = NodeId>,
43 ) -> Result<Layout<V, D>> {
44 let rem_size = self.rem_pixels();
45 let id = self
46 .legacy_cx
47 .layout_engine()
48 .ok_or_else(|| anyhow!("no layout engine"))?
49 .add_node(style.to_taffy(rem_size), children)?;
50
51 Ok(Layout::new(id, element_data))
52 }
53
54 pub fn add_measured_layout_node<D, F>(
55 &mut self,
56 style: Style,
57 element_data: D,
58 measure: F,
59 ) -> Result<Layout<V, D>>
60 where
61 F: Fn(MeasureParams) -> Size<f32> + Sync + Send + 'static,
62 {
63 let rem_size = self.rem_pixels();
64 let layout_id = self
65 .layout_engine()
66 .ok_or_else(|| anyhow!("no layout engine"))?
67 .add_measured_node(style.to_taffy(rem_size), measure)?;
68
69 Ok(Layout::new(layout_id, element_data))
70 }
71}