simple_plugin/simple_plugin.rs
1//! Example of a simple plugin using the nemo-plugin builder API
2//!
3//! This example shows how to create a basic plugin with a UI template
4//! using the fluent builder pattern.
5
6use nemo_plugin::containers;
7use nemo_plugin::prelude::*;
8
9/// Build a simple temperature monitor UI
10fn build_temperature_monitor() -> PluginValue {
11 Panel::new()
12 .padding(20)
13 .border(1)
14 .border_color("theme.border")
15 .shadow("md")
16 .width(350)
17 .child(
18 "header",
19 Stack::vertical()
20 .spacing(4)
21 .child(
22 "title",
23 Label::new("Temperature Monitor").size("xl").weight("bold"),
24 )
25 .child(
26 "subtitle",
27 Label::new("Real-time sensor readings")
28 .size("sm")
29 .color("theme.muted"),
30 ),
31 )
32 .child(
33 "controls",
34 Stack::vertical()
35 .spacing(16)
36 // Temperature display
37 .child(
38 "temp_display",
39 Panel::new()
40 .padding(16)
41 .bg_color("theme.surface")
42 .border(1)
43 .child(
44 "content",
45 Stack::vertical()
46 .spacing(8)
47 .align("center")
48 .child("label", Label::new("Current Temperature"))
49 .child(
50 "value",
51 Label::new("--°C")
52 .size("xl")
53 .weight("bold")
54 .bind_text("data.temperature.display"),
55 ),
56 ),
57 )
58 // Settings
59 .child(
60 "settings",
61 Stack::vertical()
62 .spacing(12)
63 // Temperature unit selector
64 .child(
65 "unit_row",
66 Stack::horizontal()
67 .spacing(8)
68 .child("label", Label::new("Unit:").width(100))
69 .child(
70 "celsius_btn",
71 Button::new("°C")
72 .variant("secondary")
73 .on_click("set_celsius")
74 .width(60),
75 )
76 .child(
77 "fahrenheit_btn",
78 Button::new("°F")
79 .variant("secondary")
80 .on_click("set_fahrenheit")
81 .width(60),
82 ),
83 )
84 // Alert threshold
85 .child(
86 "threshold_row",
87 Stack::vertical()
88 .spacing(8)
89 .child("threshold_label", Label::new("Alert Threshold"))
90 .child(
91 "threshold_slider",
92 Slider::new()
93 .min(0.0)
94 .max(100.0)
95 .step(1.0)
96 .value(30.0)
97 .on_change("on_threshold_change")
98 .bind_value("settings.alert_threshold"),
99 ),
100 )
101 // Enable alerts switch
102 .child(
103 "alerts_switch",
104 Switch::new()
105 .label("Enable High Temperature Alerts")
106 .checked(true)
107 .on_click("toggle_alerts")
108 .bind_checked("settings.alerts_enabled"),
109 ),
110 )
111 // History chart placeholder
112 .child(
113 "history",
114 Panel::new()
115 .padding(12)
116 .bg_color("theme.surface")
117 .border(1)
118 .height(200)
119 .child(
120 "chart_label",
121 Label::new("Temperature History").weight("bold"),
122 ),
123 ),
124 )
125 .build()
126}
127
128/// Build a control panel with multiple inputs
129fn build_control_panel() -> PluginValue {
130 Panel::new()
131 .padding(16)
132 .border(2)
133 .border_color("theme.primary")
134 .child(
135 "form",
136 Stack::vertical()
137 .spacing(12)
138 .child("title", Label::new("Device Control Panel").size("lg"))
139 // Using the helper function for input rows
140 .child(
141 "name_row",
142 containers::input_row(
143 "Device Name",
144 Some(120),
145 Input::new()
146 .placeholder("Enter device name")
147 .on_change("on_name_change"),
148 Some(8),
149 ),
150 )
151 .child(
152 "id_row",
153 containers::input_row(
154 "Device ID",
155 Some(120),
156 Input::new()
157 .placeholder("Auto-generated")
158 .disabled(true)
159 .bind_value("device.id"),
160 Some(8),
161 ),
162 )
163 // Action buttons
164 .child(
165 "actions",
166 Stack::horizontal()
167 .spacing(8)
168 .justify("end")
169 .child(
170 "save_btn",
171 Button::new("Save")
172 .variant("primary")
173 .on_click("save_settings"),
174 )
175 .child(
176 "reset_btn",
177 Button::new("Reset")
178 .variant("secondary")
179 .on_click("reset_settings"),
180 )
181 .child(
182 "delete_btn",
183 Button::new("Delete")
184 .variant("danger")
185 .on_click("delete_device"),
186 ),
187 ),
188 )
189 .build()
190}
191
192/// Build a dashboard with grid layout
193fn build_dashboard() -> PluginValue {
194 Panel::new()
195 .padding(20)
196 .child(
197 "dashboard",
198 Stack::vertical()
199 .spacing(16)
200 .child(
201 "header",
202 Label::new("System Dashboard").size("xl").weight("bold"),
203 )
204 .child(
205 "metrics",
206 Grid::new(2)
207 .gap(16)
208 // Metric card 1
209 .child(
210 "cpu",
211 Panel::new().padding(16).border(1).child(
212 "content",
213 Stack::vertical()
214 .spacing(8)
215 .child("label", Label::new("CPU Usage"))
216 .child(
217 "value",
218 Label::new("--%")
219 .size("xl")
220 .weight("bold")
221 .bind_text("metrics.cpu.display"),
222 )
223 .child(
224 "bar",
225 Slider::new()
226 .min(0.0)
227 .max(100.0)
228 .bind_value("metrics.cpu.value"),
229 ),
230 ),
231 )
232 // Metric card 2
233 .child(
234 "memory",
235 Panel::new().padding(16).border(1).child(
236 "content",
237 Stack::vertical()
238 .spacing(8)
239 .child("label", Label::new("Memory Usage"))
240 .child(
241 "value",
242 Label::new("--%")
243 .size("xl")
244 .weight("bold")
245 .bind_text("metrics.memory.display"),
246 )
247 .child(
248 "bar",
249 Slider::new()
250 .min(0.0)
251 .max(100.0)
252 .bind_value("metrics.memory.value"),
253 ),
254 ),
255 )
256 // Metric card 3
257 .child(
258 "disk",
259 Panel::new().padding(16).border(1).child(
260 "content",
261 Stack::vertical()
262 .spacing(8)
263 .child("label", Label::new("Disk Usage"))
264 .child(
265 "value",
266 Label::new("--%")
267 .size("xl")
268 .weight("bold")
269 .bind_text("metrics.disk.display"),
270 )
271 .child(
272 "bar",
273 Slider::new()
274 .min(0.0)
275 .max(100.0)
276 .bind_value("metrics.disk.value"),
277 ),
278 ),
279 )
280 // Metric card 4
281 .child(
282 "network",
283 Panel::new().padding(16).border(1).child(
284 "content",
285 Stack::vertical()
286 .spacing(8)
287 .child("label", Label::new("Network"))
288 .child(
289 "value",
290 Label::new("-- MB/s")
291 .size("xl")
292 .weight("bold")
293 .bind_text("metrics.network.display"),
294 ),
295 ),
296 ),
297 ),
298 )
299 .build()
300}
301
302fn main() {
303 println!("Building temperature monitor...");
304 let temp_monitor = build_temperature_monitor();
305 println!("Temperature monitor: {:#?}", temp_monitor);
306
307 println!("\nBuilding control panel...");
308 let control_panel = build_control_panel();
309 println!("Control panel: {:#?}", control_panel);
310
311 println!("\nBuilding dashboard...");
312 let dashboard = build_dashboard();
313 println!("Dashboard: {:#?}", dashboard);
314}