guido 0.11.0

A reactive Rust GUI library using wgpu for Wayland layer shell widgets
Documentation
//! Example demonstrating the create_service API for background tasks.
//!
//! This example shows:
//! - Creating a bidirectional service that handles commands
//! - Creating a read-only service for periodic updates
//! - Using `.writer()` to get Send-able signal handles for background threads
//! - Automatic cleanup when components unmount

use std::time::Duration;

use guido::prelude::*;

/// Commands that can be sent to the workspace service
#[derive(Clone)]
enum WorkspaceCmd {
    Switch(i32),
}

#[tokio::main]
async fn main() {
    App::new().run(|app| {
        // Clock signal - updated by a read-only service
        let time = create_signal(get_current_time());
        let time_w = time.writer(); // WriteSignal is Send — can be captured by service

        // Clock service - read-only (ignore the receiver)
        create_task(move |ctx| async move {
            log::info!("Clock service started");

            while ctx.is_running() {
                time_w.set(get_current_time());
                tokio::time::sleep(Duration::from_secs(1)).await;
            }

            log::info!("Clock service stopped");
        });

        // Workspace signals
        let active = create_signal(1i32);
        let active_w = active.writer(); // WriteSignal is Send
        let workspaces: Vec<i32> = vec![1, 2, 3, 4, 5];

        // Workspace service - bidirectional
        let service = create_service(move |mut rx, ctx| async move {
            log::info!("Workspace service started");

            while ctx.is_running() {
                // Handle commands from UI
                while let Ok(cmd) = rx.try_recv() {
                    match cmd {
                        WorkspaceCmd::Switch(id) => {
                            log::info!("Switching to workspace {}", id);
                            active_w.set(id);
                        }
                    }
                }

                tokio::time::sleep(Duration::from_millis(16)).await;
            }

            log::info!("Workspace service stopped");
        });

        app.add_surface(
            SurfaceConfig::new()
                .height(40)
                .anchor(Anchor::TOP | Anchor::LEFT | Anchor::RIGHT)
                .background_color(Color::rgb(0.1, 0.1, 0.15)),
            move || {
                let svc = service;

                container()
                    .layout(
                        Flex::row()
                            .spacing(16.0)
                            .main_alignment(MainAlignment::SpaceBetween),
                    )
                    .padding(4.0)
                    // Workspace buttons
                    .child(container().layout(Flex::row().spacing(4.0)).children(
                        workspaces.clone().into_iter().map(move |id| {
                            container()
                                .width(32.0)
                                .height(32.0)
                                .background(move || {
                                    if active.get() == id {
                                        Color::rgb(0.3, 0.5, 0.8)
                                    } else {
                                        Color::rgb(0.2, 0.2, 0.3)
                                    }
                                })
                                .corners(4.0)
                                .when_hovered(|s| s.lighter(0.1))
                                .when_pressed(|s| s.ripple())
                                .on_click(move || svc.send(WorkspaceCmd::Switch(id)))
                                .child(
                                    container()
                                        .layout(Flex::row().center())
                                        .child(text(format!("{}", id)).color(Color::WHITE)),
                                )
                        }),
                    ))
                    // Clock display
                    .child(
                        container()
                            .padding(8.0)
                            .background(Color::rgb(0.2, 0.2, 0.3))
                            .corners(4.0)
                            .child(text(move || time.get()).color(Color::WHITE)),
                    )
            },
        );
    });
}

fn get_current_time() -> String {
    use std::time::{SystemTime, UNIX_EPOCH};

    let now = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs();

    // Simple time formatting (HH:MM:SS)
    let hours = (now % 86400) / 3600;
    let minutes = (now % 3600) / 60;
    let seconds = now % 60;

    format!("{:02}:{:02}:{:02}", hours, minutes, seconds)
}