Files
ruin/lib/ruin_app/example/00_bootstrap_and_counter.rs
2026-05-16 16:38:10 -04:00

118 lines
3.5 KiB
Rust

use ruin_app::{PartialTextStyle, prelude::*};
use ruin_ui::{BoxShadow, BoxShadowKind, Point};
use tracing_subscriber::EnvFilter;
#[ruin_runtime::async_main]
async fn main() -> ruin_app::Result<()> {
let _ = tracing_subscriber::fmt()
.with_env_filter(
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
)
.with_target(true)
.without_time()
.try_init();
let title = "RUIN Counter";
App::new()
.window(
Window::new()
.title(title)
.app_id("dev.ruin.counter")
.base_color(Color::rgba(255, 255, 255, 80))
.min_size(320.0, 240.0)
.size(960.0, 640.0),
)
.mount(view! {
CounterApp(title = title) {}
})
.run()
.await
}
#[component]
fn CounterApp(title: &'static str) -> impl IntoView {
let count = use_signal(|| 0_i32);
let doubled = use_memo({
let count = count.clone();
move || count.get() * 2
});
use_window_title({
let count = count.clone();
move || format!("{title} ({})", count.get())
});
let text_style = PartialTextStyle {
color: Some(Color::BLACK),
weight: Some(FontWeight::Bold),
..Default::default()
};
view! {
column(gap = 16.0, padding = 24.0, align_items = AlignItems::Center, text_style = text_style) {
text(role = TextRole::Heading(1), size = 32.0, weight = FontWeight::Semibold, color = Color::rgba(0, 0, 0, 255)) {
title
}
CounterActions(count = count.clone()) {}
block(
padding = 16.0,
gap = 8.0,
align_self = AlignItems::Stretch,
background = Color::rgba(255, 255, 255, 200),
border_radius = 12.0,
border = Border::new(2.0, Color::rgba(0, 0, 0, 120)),
shadow = BoxShadow::new(Point::new(2.0, 2.0), 8.0, 2.0, Color::rgba(0, 0, 0, 60), BoxShadowKind::Outer),
) {
text(size = 18.0, color = Color::rgb(0, 0, 0)) { "count = "; count.clone() }
text(color = Color::rgba(0, 0, 0, 200)) { "double = "; doubled.clone() }
}
}
}
}
#[component]
fn CounterActions(count: Signal<i32>) -> impl IntoView {
view! {
row(gap = 16.0) {
button(
background = Color::rgba(255, 255, 255, 90),
on_press = {
let count = count.clone();
move |_| {
count.update(|value| *value -= 1);
}
},
) {
text(selectable = false, pointer_events = false) { "-1" }
}
button(
background = Color::rgba(255, 255, 255, 90),
on_press = {
let count = count.clone();
move |_| {
let _ = count.set(0);
}
},
) {
text(selectable = false, pointer_events = false) { "Reset" }
}
button(
background = Color::rgba(255, 255, 255, 90),
on_press = {
let count = count.clone();
move |_| {
count.update(|value| *value += 1);
}
},
) {
text(selectable = false, pointer_events = false) { "+1" }
}
}
}
}