#![allow(dead_code, unused_imports)]
use swiftui_native::{app, views, window, Color};
static TAPS: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
fn on_tap() {
TAPS.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
let s = switch_state();
s.set(!s.get());
refresh();
}
fn root_view() -> views::ViewHandle {
thread_local! {
static ROOT: std::cell::OnceCell<swiftui_native::state::StatefulView> =
const { std::cell::OnceCell::new() };
}
ROOT.with(|cell| {
let sv = cell.get_or_init(|| {
let sv = swiftui_native::state::StatefulView::new(0, |_generation| ui());
ROOT_ID.store(sv.id, std::sync::atomic::Ordering::Release);
sv
});
sv.as_view()
})
}
static ROOT_ID: std::sync::atomic::AtomicI64 = std::sync::atomic::AtomicI64::new(-1);
fn refresh() {
use std::sync::atomic::Ordering;
static GENERATION: std::sync::atomic::AtomicI64 = std::sync::atomic::AtomicI64::new(0);
let id = ROOT_ID.load(Ordering::Acquire);
if id >= 0 {
let n = GENERATION.fetch_add(1, Ordering::Relaxed) + 1;
swiftui_native::state::set_state(id, n);
}
}
fn slider_state() -> &'static views::BoundState<f64> {
static S: std::sync::OnceLock<views::BoundState<f64>> = std::sync::OnceLock::new();
S.get_or_init(|| views::BoundState::new(0.65))
}
fn stepper_state() -> &'static views::BoundState<f64> {
static S: std::sync::OnceLock<views::BoundState<f64>> = std::sync::OnceLock::new();
S.get_or_init(|| views::BoundState::new(3.0))
}
fn switch_state() -> &'static views::BoundState<bool> {
static S: std::sync::OnceLock<views::BoundState<bool>> = std::sync::OnceLock::new();
S.get_or_init(|| views::BoundState::new(false))
}
fn ui() -> views::ViewHandle {
views::zstack(&[
views::background_linear_gradient(
&views::color(0.0, 0.0, 0.0, 0.0),
&[Color::new(0.06, 0.07, 0.16, 1.0), Color::new(0.24, 0.07, 0.33, 1.0)],
(0.0, 0.0),
(1.0, 1.0),
),
views::scroll(&views::padding(
&views::vstack_spacing(
&[
header(),
section("Typography", typography()),
section("Shapes", shapes()),
section("Controls", controls()),
section("Symbols", symbols()),
section("Effects", effects()),
section("Layout", layout()),
],
18.0,
),
16.0,
)),
])
}
fn label_text(s: &str, size: f64, weight: Option<views::Weight>, alpha: f64) -> views::ViewHandle {
views::foreground_style_color(
&views::font_system(&views::text(s), size, weight, None),
1.0,
1.0,
1.0,
alpha,
)
}
fn header() -> views::ViewHandle {
views::vstack_spacing(
&[
label_text("SwiftUI from Rust", 30.0, Some(views::Weight::Bold), 1.0),
label_text(entry(), 13.0, None, 0.75),
label_text(
&format!("taps: {}", TAPS.load(std::sync::atomic::Ordering::Relaxed)),
13.0,
Some(views::Weight::Semibold),
0.9,
),
],
4.0,
)
}
fn section(title: &str, content: views::ViewHandle) -> views::ViewHandle {
views::vstack_spacing(
&[
label_text(title, 12.0, Some(views::Weight::Semibold), 0.55),
views::padding(
&views::corner_radius(
&views::background(&views::padding(&content, 12.0), 1.0, 1.0, 1.0, 0.07),
14.0,
),
0.0,
),
],
6.0,
)
}
fn typography() -> views::ViewHandle {
views::vstack_spacing(
&[
views::hstack_spacing(
&[
views::font_text_style(&views::text("Title"), views::TextStyle::Title3),
views::italic(&views::text("Italic")),
views::monospaced(&views::text("mono")),
],
14.0,
),
views::kerning(&label_text("K E R N E D", 15.0, None, 0.9), 2.0),
views::foreground_style_linear_gradient(
&views::font_system(&views::text("Gradient fill"), 22.0, Some(views::Weight::Bold), None),
&[
views::color_value_of(Color::new(1.0, 0.55, 0.25, 1.0)),
views::color_value_of(Color::new(1.0, 0.25, 0.6, 1.0)),
],
(0.0, 0.0),
(1.0, 0.0),
),
],
10.0,
)
}
fn shapes() -> views::ViewHandle {
let swatch = |shape: views::Shape, c: Color| {
views::frame(&shape.fill(views::color_value_of(c)), 58.0, 44.0)
};
views::hstack_spacing(
&[
swatch(views::Shape::circle(), Color::new(0.95, 0.35, 0.30, 1.0)),
swatch(views::Shape::capsule(), Color::new(0.98, 0.70, 0.20, 1.0)),
swatch(views::Shape::rounded_rectangle(10.0, true), Color::new(0.30, 0.65, 1.0, 1.0)),
swatch(views::Shape::ellipse(), Color::new(0.35, 0.85, 0.55, 1.0)),
],
10.0,
)
}
fn controls() -> views::ViewHandle {
views::vstack_spacing(
&[
views::toggle_bound("Bound to Rust state", switch_state()),
views::toggle("Constant false", false),
views::hstack_spacing(
&[
label_text(&format!("{:.2}", slider_state().get()), 14.0, None, 0.9),
views::slider_bound(slider_state(), 0.0, 1.0),
],
10.0,
),
views::stepper_bound(
&format!("Stepper: {:.0}", stepper_state().get()),
stepper_state(),
0.0,
10.0,
1.0,
),
views::progress(stepper_state().get(), 10.0),
views::hstack_spacing(
&[
views::button_style(
&views::button("Bordered", on_tap),
views::ButtonStyle::Bordered,
),
views::button_style(
&views::button("Glass", on_tap),
views::ButtonStyle::Glass,
),
],
12.0,
),
views::textfield("A text field", ""),
],
12.0,
)
}
fn symbols() -> views::ViewHandle {
let icon = |name: &str, c: Color| {
views::foreground_style_color(
&views::font_system(&views::system_image(name), 24.0, None, None),
c.r, c.g, c.b, c.a,
)
};
views::hstack_spacing(
&[
icon("star.fill", Color::new(1.0, 0.8, 0.2, 1.0)),
icon("heart.fill", Color::new(1.0, 0.35, 0.45, 1.0)),
icon("bolt.fill", Color::new(0.55, 0.8, 1.0, 1.0)),
icon("cloud.sun.fill", Color::new(0.8, 0.85, 1.0, 1.0)),
icon("checkmark.seal.fill", Color::new(0.4, 0.9, 0.6, 1.0)),
],
16.0,
)
}
fn effects() -> views::ViewHandle {
let tile = |c: Color| views::frame(&views::color(c.r, c.g, c.b, c.a), 48.0, 40.0);
views::hstack_spacing(
&[
views::blur(&tile(Color::new(0.95, 0.4, 0.3, 1.0)), 4.0),
views::shadow(
&tile(Color::new(0.3, 0.7, 1.0, 1.0)),
Color::new(0.0, 0.0, 0.0, 0.8),
8.0,
0.0,
4.0,
),
views::opacity(&tile(Color::new(0.5, 0.9, 0.5, 1.0)), 0.35),
views::corner_radius(&tile(Color::new(0.9, 0.7, 0.2, 1.0)), 12.0),
views::border(&tile(Color::new(0.0, 0.0, 0.0, 0.0)), 1.0, 1.0, 1.0, 2.0),
],
10.0,
)
}
fn layout() -> views::ViewHandle {
let chip = |s: &str, c: Color| {
views::corner_radius(
&views::background(&views::padding(&label_text(s, 13.0, None, 1.0), 8.0), c.r, c.g, c.b, c.a),
8.0,
)
};
views::vstack_spacing(
&[
views::hstack_spacing(
&[
chip("HStack", Color::new(0.35, 0.35, 0.8, 0.8)),
views::spacer(),
chip("Spacer", Color::new(0.8, 0.35, 0.5, 0.8)),
],
8.0,
),
views::divider(),
views::zstack(&[
views::frame(
&views::Shape::rounded_rectangle(8.0, true)
.fill(views::color_value_of(Color::new(0.2, 0.5, 0.9, 0.55))),
120.0,
34.0,
),
label_text("ZStack", 13.0, Some(views::Weight::Semibold), 1.0),
]),
],
10.0,
)
}
fn entry() -> &'static str {
if uses_window() {
"UIApplicationMain, synthesised delegate"
} else {
"App.main(), synthesised conformance"
}
}
fn uses_window() -> bool {
std::env::args().any(|a| a == "window")
}
#[cfg(not(target_os = "macos"))]
fn main() {
views::on_write(refresh);
#[cfg(feature = "uikit-entry")]
if uses_window() {
window::show_window(&root_view(), "RustUI", 0.0, 0.0);
}
app::run(root_view)
}
#[cfg(target_os = "macos")]
#[path = "common/simulator.rs"]
mod simulator;
#[cfg(target_os = "macos")]
fn main() {
simulator::main(&simulator::Bundle {
example: "ios_app",
bundle_id: "dev.rswift.RustUI",
executable: "RustUI",
display_name: "SwiftUI from Rust",
launch_args: if uses_window() { &["window"] } else { &[] },
});
}