Skip to main content

cranpose_ui/widgets/
scopes.rs

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