StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.
| 1 | //! Counter example demonstrating state management in StratoUI |
| 2 | |
| 3 | use parking_lot::RwLock; |
| 4 | use std::sync::Arc; |
| 5 | use strato_core::inspector::{inspector, InspectorConfig}; |
| 6 | use strato_core::{error::Result, types::Color}; |
| 7 | use strato_platform::{ApplicationBuilder, WindowBuilder}; |
| 8 | use strato_widgets::prelude::*; |
| 9 | use strato_widgets::ButtonStyle; |
| 10 | use strato_widgets::InspectorOverlay; |
| 11 | |
| 12 | struct CounterApp { |
| 13 | count: Arc<RwLock<i32>>, |
| 14 | } |
| 15 | |
| 16 | impl CounterApp { |
| 17 | fn new() -> Self { |
| 18 | Self { |
| 19 | count: Arc::new(RwLock::new(0)), |
| 20 | } |
| 21 | } |
| 22 | |
| 23 | fn increment(&self) { |
| 24 | *self.count.write() += 1; |
| 25 | } |
| 26 | |
| 27 | fn decrement(&self) { |
| 28 | *self.count.write() -= 1; |
| 29 | } |
| 30 | |
| 31 | fn reset(&self) { |
| 32 | *self.count.write() = 0; |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | fn main() -> Result<()> { |
| 37 | // Initialize all StratoUI modules |
| 38 | strato_core::init()?; |
| 39 | strato_widgets::init()?; |
| 40 | strato_platform::init() |
| 41 | .map_err(|e| strato_core::error::StratoError::platform(format!("{:?}", e)))?; |
| 42 | |
| 43 | // Keep the inspector active even outside debug builds so the example surfaces diagnostics. |
| 44 | inspector().configure(InspectorConfig { |
| 45 | enabled: true, |
| 46 | ..Default::default() |
| 47 | }); |
| 48 | |
| 49 | let app = Arc::new(CounterApp::new()); |
| 50 | |
| 51 | // Create and run the application |
| 52 | ApplicationBuilder::new() |
| 53 | .title("Counter Example") |
| 54 | .window( |
| 55 | WindowBuilder::new() |
| 56 | .with_size(350.0, 250.0) |
| 57 | .resizable(false), |
| 58 | ) |
| 59 | .run(InspectorOverlay::new(build_ui(app))); |
| 60 | |
| 61 | Ok(()) |
| 62 | } |
| 63 | |
| 64 | fn build_ui(app: Arc<CounterApp>) -> impl Widget { |
| 65 | let app_inc = app.clone(); |
| 66 | let app_dec = app.clone(); |
| 67 | let app_reset = app.clone(); |
| 68 | |
| 69 | Container::new() |
| 70 | .background(Color::WHITE) |
| 71 | .padding(30.0) |
| 72 | .child( |
| 73 | Column::new() |
| 74 | .spacing(20.0) |
| 75 | .main_axis_alignment(MainAxisAlignment::Center) |
| 76 | .cross_axis_alignment(CrossAxisAlignment::Center) |
| 77 | .children(vec![ |
| 78 | Box::new( |
| 79 | Text::new("Counter App") |
| 80 | .size(28.0) |
| 81 | .color(Color::rgb(0.2, 0.2, 0.2)), |
| 82 | ), |
| 83 | Box::new( |
| 84 | Container::new() |
| 85 | .padding(20.0) |
| 86 | .background(Color::rgba(0.0, 0.0, 0.0, 0.05)) |
| 87 | .border_radius(8.0) |
| 88 | .child( |
| 89 | Text::new(format!("{}", *app.count.read())) |
| 90 | .size(48.0) |
| 91 | .color(Color::BLACK), |
| 92 | ), |
| 93 | ), |
| 94 | Box::new( |
| 95 | Row::new() |
| 96 | .spacing(10.0) |
| 97 | .main_axis_alignment(MainAxisAlignment::Center) |
| 98 | .children(vec![ |
| 99 | Box::new( |
| 100 | Button::new("-") |
| 101 | .style(ButtonStyle::secondary()) |
| 102 | .size(50.0, 40.0) |
| 103 | .on_click(move || { |
| 104 | app_dec.decrement(); |
| 105 | println!("Count: {}", *app_dec.count.read()); |
| 106 | }), |
| 107 | ), |
| 108 | Box::new(Button::new("Reset").style(ButtonStyle::text()).on_click( |
| 109 | move || { |
| 110 | app_reset.reset(); |
| 111 | println!("Count reset to 0"); |
| 112 | }, |
| 113 | )), |
| 114 | Box::new( |
| 115 | Button::new("+") |
| 116 | .style(ButtonStyle::primary()) |
| 117 | .size(50.0, 40.0) |
| 118 | .on_click(move || { |
| 119 | app_inc.increment(); |
| 120 | println!("Count: {}", *app_inc.count.read()); |
| 121 | }), |
| 122 | ), |
| 123 | ]), |
| 124 | ), |
| 125 | ]), |
| 126 | ) |
| 127 | } |
| 128 |