{ let window = gtk::ApplicationWindow::builder() .application(app) .title("Lesavka") .default_width(LAUNCHER_DEFAULT_WIDTH) .default_height(LAUNCHER_DEFAULT_HEIGHT) .resizable(false) .build(); install_css(&window); install_window_icon(&window); let root = gtk::Box::new(gtk::Orientation::Vertical, 8); root.add_css_class("launcher-root"); root.set_margin_start(10); root.set_margin_end(10); root.set_margin_top(10); root.set_margin_bottom(10); let hero = gtk::Box::new(gtk::Orientation::Horizontal, 8); hero.set_hexpand(true); let brand_box = gtk::Box::new(gtk::Orientation::Vertical, 0); brand_box.set_valign(gtk::Align::Center); let brand_row = gtk::Box::new(gtk::Orientation::Horizontal, 8); brand_row.set_halign(gtk::Align::Start); brand_row.set_valign(gtk::Align::Center); let brand_icon = gtk::Image::from_icon_name(LESAVKA_ICON_NAME); brand_icon.add_css_class("app-logo"); brand_icon.set_pixel_size(44); brand_icon.set_valign(gtk::Align::Center); let heading = gtk::Label::new(Some("Lesavka")); heading.add_css_class("title-2"); heading.set_halign(gtk::Align::Start); heading.set_valign(gtk::Align::Center); let version_tag = gtk::Label::new(Some(&format!("v{}", crate::VERSION))); version_tag.add_css_class("version-tag"); version_tag.set_halign(gtk::Align::Start); version_tag.set_valign(gtk::Align::Center); brand_row.append(&brand_icon); brand_row.append(&heading); brand_row.append(&version_tag); brand_box.append(&brand_row); hero.append(&brand_box); let chips = gtk::Box::new(gtk::Orientation::Horizontal, 6); chips.set_halign(gtk::Align::End); chips.set_hexpand(true); let (relay_chip, relay_light, relay_value) = build_status_chip_with_light("Server", ""); let (routing_chip, routing_light, routing_value) = build_status_chip_with_light("Inputs", "Local"); let (gpio_chip, gpio_light, gpio_value) = build_status_chip_with_light("GPIO", "Unknown"); let (shortcut_chip, shortcut_value) = build_status_chip("Swap Key", "Pause"); chips.append(&relay_chip); chips.append(&routing_chip); chips.append(&gpio_chip); chips.append(&shortcut_chip); hero.append(&chips); root.append(&hero); let content = gtk::Box::new(gtk::Orientation::Horizontal, 8); content.set_hexpand(true); content.set_vexpand(true); root.append(&content); let workspace = gtk::Box::new(gtk::Orientation::Vertical, 8); workspace.set_hexpand(true); workspace.set_vexpand(true); content.append(&workspace); let operations = gtk::Box::new(gtk::Orientation::Vertical, 8); operations.set_size_request(OPERATIONS_RAIL_WIDTH, -1); operations.set_hexpand(false); operations.set_vexpand(true); operations.set_valign(gtk::Align::Fill); content.append(&operations); let display_row = gtk::Box::new(gtk::Orientation::Horizontal, 8); display_row.set_hexpand(true); display_row.set_vexpand(false); display_row.set_valign(gtk::Align::Start); display_row.set_homogeneous(true); let left_pane = build_display_pane("Left Eye", "/dev/lesavka_l_eye"); let right_pane = build_display_pane("Right Eye", "/dev/lesavka_r_eye"); display_row.append(&left_pane.root); display_row.append(&right_pane.root); workspace.append(&display_row); let staging_row = gtk::Box::new(gtk::Orientation::Horizontal, 8); staging_row.set_hexpand(true); staging_row.set_vexpand(false); staging_row.set_valign(gtk::Align::Start); staging_row.set_homogeneous(true); workspace.append(&staging_row); LauncherShellContext { window, root, staging_row, operations, left_pane, right_pane, relay_light, relay_value, routing_light, routing_value, gpio_light, gpio_value, shortcut_value, } }