Skip to main content

nemo_plugin/
containers.rs

1//! Container builders for layout management
2
3use crate::builder::{Builder, LayoutBuilder};
4use nemo_plugin_api::PluginValue;
5
6/// Builder for a Panel container
7pub struct Panel(LayoutBuilder);
8
9impl Panel {
10    /// Create a new panel
11    pub fn new() -> Self {
12        Self(LayoutBuilder::new("panel"))
13    }
14
15    /// Set the padding
16    pub fn padding(mut self, padding: i64) -> Self {
17        self.0 = self.0.padding(padding);
18        self
19    }
20
21    /// Set the margin
22    pub fn margin(mut self, margin: i64) -> Self {
23        self.0 = self.0.margin(margin);
24        self
25    }
26
27    /// Set the border width
28    pub fn border(mut self, border: i64) -> Self {
29        self.0 = self.0.border(border);
30        self
31    }
32
33    /// Set the border color
34    pub fn border_color(mut self, color: impl Into<String>) -> Self {
35        self.0 = self.0.border_color(color);
36        self
37    }
38
39    /// Set the background color
40    pub fn bg_color(mut self, color: impl Into<String>) -> Self {
41        self.0 = self.0.bg_color(color);
42        self
43    }
44
45    /// Set the shadow
46    pub fn shadow(mut self, shadow: impl Into<String>) -> Self {
47        self.0 = self.0.shadow(shadow);
48        self
49    }
50
51    /// Set the width
52    pub fn width(mut self, width: i64) -> Self {
53        self.0 = self.0.width(width);
54        self
55    }
56
57    /// Set the height
58    pub fn height(mut self, height: i64) -> Self {
59        self.0 = self.0.height(height);
60        self
61    }
62
63    /// Add a child component
64    pub fn child(mut self, id: impl Into<String>, child: impl Builder) -> Self {
65        self.0 = self.0.child(id, child);
66        self
67    }
68
69    /// Add multiple children
70    pub fn children(mut self, children: impl IntoIterator<Item = (String, PluginValue)>) -> Self {
71        self.0 = self.0.children(children);
72        self
73    }
74}
75
76impl Default for Panel {
77    fn default() -> Self {
78        Self::new()
79    }
80}
81
82impl Builder for Panel {
83    fn build(self) -> PluginValue {
84        self.0.build()
85    }
86}
87
88/// Builder for a Stack container (horizontal or vertical)
89pub struct Stack(LayoutBuilder);
90
91impl Stack {
92    /// Create a new vertical stack
93    pub fn vertical() -> Self {
94        Self(
95            LayoutBuilder::new("stack")
96                .attr("direction", PluginValue::String("vertical".to_string())),
97        )
98    }
99
100    /// Create a new horizontal stack
101    pub fn horizontal() -> Self {
102        Self(
103            LayoutBuilder::new("stack")
104                .attr("direction", PluginValue::String("horizontal".to_string())),
105        )
106    }
107
108    /// Set the spacing between children
109    pub fn spacing(mut self, spacing: i64) -> Self {
110        self.0 = self.0.attr("spacing", PluginValue::Integer(spacing));
111        self
112    }
113
114    /// Set the padding
115    pub fn padding(mut self, padding: i64) -> Self {
116        self.0 = self.0.padding(padding);
117        self
118    }
119
120    /// Set the alignment (start, center, end, stretch)
121    pub fn align(mut self, align: impl Into<String>) -> Self {
122        self.0 = self.0.attr("align", PluginValue::String(align.into()));
123        self
124    }
125
126    /// Set the justification (start, center, end, space-between, space-around)
127    pub fn justify(mut self, justify: impl Into<String>) -> Self {
128        self.0 = self.0.attr("justify", PluginValue::String(justify.into()));
129        self
130    }
131
132    /// Set the width
133    pub fn width(mut self, width: i64) -> Self {
134        self.0 = self.0.width(width);
135        self
136    }
137
138    /// Set the height
139    pub fn height(mut self, height: i64) -> Self {
140        self.0 = self.0.height(height);
141        self
142    }
143
144    /// Add a child component
145    pub fn child(mut self, id: impl Into<String>, child: impl Builder) -> Self {
146        self.0 = self.0.child(id, child);
147        self
148    }
149
150    /// Add multiple children
151    pub fn children(mut self, children: impl IntoIterator<Item = (String, PluginValue)>) -> Self {
152        self.0 = self.0.children(children);
153        self
154    }
155}
156
157impl Builder for Stack {
158    fn build(self) -> PluginValue {
159        self.0.build()
160    }
161}
162
163/// Builder for a Grid container
164pub struct Grid(LayoutBuilder);
165
166impl Grid {
167    /// Create a new grid with columns
168    pub fn new(columns: i64) -> Self {
169        Self(LayoutBuilder::new("grid").attr("columns", PluginValue::Integer(columns)))
170    }
171
172    /// Set the number of columns
173    pub fn columns(mut self, columns: i64) -> Self {
174        self.0 = self.0.attr("columns", PluginValue::Integer(columns));
175        self
176    }
177
178    /// Set the gap between cells
179    pub fn gap(mut self, gap: i64) -> Self {
180        self.0 = self.0.attr("gap", PluginValue::Integer(gap));
181        self
182    }
183
184    /// Set the padding
185    pub fn padding(mut self, padding: i64) -> Self {
186        self.0 = self.0.padding(padding);
187        self
188    }
189
190    /// Set the width
191    pub fn width(mut self, width: i64) -> Self {
192        self.0 = self.0.width(width);
193        self
194    }
195
196    /// Set the height
197    pub fn height(mut self, height: i64) -> Self {
198        self.0 = self.0.height(height);
199        self
200    }
201
202    /// Add a child component
203    pub fn child(mut self, id: impl Into<String>, child: impl Builder) -> Self {
204        self.0 = self.0.child(id, child);
205        self
206    }
207
208    /// Add multiple children
209    pub fn children(mut self, children: impl IntoIterator<Item = (String, PluginValue)>) -> Self {
210        self.0 = self.0.children(children);
211        self
212    }
213}
214
215impl Builder for Grid {
216    fn build(self) -> PluginValue {
217        self.0.build()
218    }
219}
220
221/// Builder for a ScrollView container
222pub struct ScrollView(LayoutBuilder);
223
224impl ScrollView {
225    /// Create a new scroll view
226    pub fn new() -> Self {
227        Self(LayoutBuilder::new("scroll"))
228    }
229
230    /// Set the direction (vertical, horizontal, both)
231    pub fn direction(mut self, direction: impl Into<String>) -> Self {
232        self.0 = self
233            .0
234            .attr("direction", PluginValue::String(direction.into()));
235        self
236    }
237
238    /// Set the width
239    pub fn width(mut self, width: i64) -> Self {
240        self.0 = self.0.width(width);
241        self
242    }
243
244    /// Set the height
245    pub fn height(mut self, height: i64) -> Self {
246        self.0 = self.0.height(height);
247        self
248    }
249
250    /// Add a child component
251    pub fn child(mut self, id: impl Into<String>, child: impl Builder) -> Self {
252        self.0 = self.0.child(id, child);
253        self
254    }
255}
256
257impl Default for ScrollView {
258    fn default() -> Self {
259        Self::new()
260    }
261}
262
263impl Builder for ScrollView {
264    fn build(self) -> PluginValue {
265        self.0.build()
266    }
267}
268
269/// Helper to create a horizontal row with a label and another component
270pub fn input_row(
271    label_text: impl Into<String>,
272    label_width: Option<i64>,
273    component: impl Builder,
274    spacing: Option<i64>,
275) -> Stack {
276    let mut label = crate::components::Label::new(label_text);
277    if let Some(width) = label_width {
278        label = label.width(width);
279    }
280
281    let mut stack = Stack::horizontal()
282        .child("label", label)
283        .child("component", component);
284
285    if let Some(spacing) = spacing {
286        stack = stack.spacing(spacing);
287    }
288
289    stack
290}
291
292/// Helper to create a row with custom children
293pub fn row(spacing: i64) -> Stack {
294    Stack::horizontal().spacing(spacing)
295}
296
297/// Helper to create a column
298pub fn column(spacing: i64) -> Stack {
299    Stack::vertical().spacing(spacing)
300}