Skip to main content

cranpose_ui/widgets/
scopes.rs

1//! Scope traits and implementations for Box, Column, and Row
2
3use crate::modifier::Modifier;
4use cranpose_ui_graphics::Dp;
5use cranpose_ui_layout::{Alignment, Constraints, HorizontalAlignment, VerticalAlignment};
6
7/// Marker trait matching Jetpack Compose's `BoxScope` API.
8///
9/// Future API - methods will be enabled as alignment modifiers are implemented.
10pub trait BoxScope {
11    /// Align content within the Box using 2D alignment.
12    fn align(&self, alignment: Alignment) -> Modifier;
13}
14
15/// Marker trait for Column scope - provides horizontal alignment.
16///
17/// Future API - methods will be enabled as alignment and weight modifiers are implemented.
18pub trait ColumnScope {
19    /// Align content horizontally within the Column.
20    fn align(&self, alignment: HorizontalAlignment) -> Modifier;
21    /// Apply weight to distribute remaining space proportionally.
22    fn weight(&self, weight: f32, fill: bool) -> Modifier;
23}
24
25/// Marker trait for Row scope - provides vertical alignment.
26///
27/// Future API - methods will be enabled as alignment and weight modifiers are implemented.
28pub trait RowScope {
29    /// Align content vertically within the Row.
30    fn align(&self, alignment: VerticalAlignment) -> Modifier;
31    /// Apply weight to distribute remaining space proportionally.
32    fn weight(&self, weight: f32, fill: bool) -> Modifier;
33}
34
35/// Scope exposed to [`BoxWithConstraints`] content.
36pub trait BoxWithConstraintsScope: BoxScope {
37    fn constraints(&self) -> Constraints;
38    fn min_width(&self) -> Dp;
39    fn max_width(&self) -> Dp;
40    fn min_height(&self) -> Dp;
41    fn max_height(&self) -> Dp;
42}
43
44/// Concrete implementation of [`BoxWithConstraintsScope`].
45#[derive(Clone, Copy, Debug, PartialEq)]
46pub struct BoxWithConstraintsScopeImpl {
47    constraints: Constraints,
48    density: f32,
49}
50
51impl BoxWithConstraintsScopeImpl {
52    pub fn new(constraints: Constraints) -> Self {
53        Self {
54            constraints,
55            density: 1.0,
56        }
57    }
58
59    pub fn with_density(constraints: Constraints, density: f32) -> Self {
60        Self {
61            constraints,
62            density,
63        }
64    }
65
66    fn to_dp(self, raw: f32) -> Dp {
67        Dp::from_px(raw, self.density)
68    }
69
70    pub fn to_px(&self, dp: Dp) -> f32 {
71        dp.to_px(self.density)
72    }
73
74    pub fn density(&self) -> f32 {
75        self.density
76    }
77}
78
79impl BoxScope for BoxWithConstraintsScopeImpl {
80    fn align(&self, alignment: Alignment) -> Modifier {
81        BoxScopeImpl.align(alignment)
82    }
83}
84
85/// Concrete implementation of BoxScope.
86#[derive(Clone, Copy, Debug, PartialEq)]
87pub struct BoxScopeImpl;
88
89impl BoxScope for BoxScopeImpl {
90    fn align(&self, alignment: Alignment) -> Modifier {
91        Modifier::empty().alignInBox(alignment)
92    }
93}
94
95/// Concrete implementation of ColumnScope.
96///
97/// Future API - will be used once Column accepts a scoped content parameter.
98#[derive(Clone, Copy, Debug, PartialEq)]
99pub struct ColumnScopeImpl;
100
101impl ColumnScope for ColumnScopeImpl {
102    fn align(&self, alignment: HorizontalAlignment) -> Modifier {
103        Modifier::empty().alignInColumn(alignment)
104    }
105
106    fn weight(&self, weight: f32, fill: bool) -> Modifier {
107        Modifier::empty().columnWeight(weight, fill)
108    }
109}
110
111/// Concrete implementation of RowScope.
112///
113/// Future API - will be used once Row accepts a scoped content parameter.
114#[derive(Clone, Copy, Debug, PartialEq)]
115pub struct RowScopeImpl;
116
117impl RowScope for RowScopeImpl {
118    fn align(&self, alignment: VerticalAlignment) -> Modifier {
119        Modifier::empty().alignInRow(alignment)
120    }
121
122    fn weight(&self, weight: f32, fill: bool) -> Modifier {
123        Modifier::empty().rowWeight(weight, fill)
124    }
125}
126
127impl BoxWithConstraintsScope for BoxWithConstraintsScopeImpl {
128    fn constraints(&self) -> Constraints {
129        self.constraints
130    }
131
132    fn min_width(&self) -> Dp {
133        self.to_dp(self.constraints.min_width)
134    }
135
136    fn max_width(&self) -> Dp {
137        self.to_dp(self.constraints.max_width)
138    }
139
140    fn min_height(&self) -> Dp {
141        self.to_dp(self.constraints.min_height)
142    }
143
144    fn max_height(&self) -> Dp {
145        self.to_dp(self.constraints.max_height)
146    }
147}