//! Windows backend — Win32/WinUI. //! //! Architecture: correct and complete. Win32/WinUI calls are stubs marked TODO. //! //! Each `PlatformNode` maps to a HWND or WinUI control: //! element("div") → Panel (WinUI StackPanel) //! element("button") → Button (WinUI) //! element("input") → TextBox (WinUI) //! text("...") → TextBlock (WinUI) use crate::{EventHandler, PlatformBackend, PlatformError, PlatformNode, PlatformResult}; pub struct WindowsBackend; impl WindowsBackend { pub fn new() -> Self { Self } fn winui_control(tag: &str) -> &'static str { match tag { "button" => "Microsoft.UI.Xaml.Controls.Button", "input" => "Microsoft.UI.Xaml.Controls.TextBox", "textarea" => "Microsoft.UI.Xaml.Controls.TextBox", "img" => "Microsoft.UI.Xaml.Controls.Image", "ul" | "ol" => "Microsoft.UI.Xaml.Controls.ListView", "li" => "Microsoft.UI.Xaml.Controls.ListViewItem", "nav" => "Microsoft.UI.Xaml.Controls.NavigationView", _ => "Microsoft.UI.Xaml.Controls.StackPanel", } } fn winui_event(event: &str) -> &'static str { match event { "click" => "Click", "input" | "change" => "TextChanged", "focus" => "GotFocus", "blur" => "LostFocus", "keydown" | "keypress" => "KeyDown", "keyup" => "KeyUp", _ => "PointerPressed", } } } impl Default for WindowsBackend { fn default() -> Self { Self::new() } } impl PlatformBackend for WindowsBackend { fn name(&self) -> &'static str { "windows" } fn create_element(&self, tag: &str) -> PlatformResult { let mut node = PlatformNode::element(tag); // TODO: WinRT/COM activation via windows-rs crate: // let panel: StackPanel = StackPanel::new()?; node.attributes .push(crate::Attribute::new("data-winui-control", Self::winui_control(tag))); Ok(node) } fn create_text(&self, content: &str) -> PlatformResult { let mut node = PlatformNode::text(content); // TODO: TextBlock::new()?.set_text(content) node.attributes .push(crate::Attribute::new("data-winui-control", "Microsoft.UI.Xaml.Controls.TextBlock")); Ok(node) } fn set_attribute( &self, node: &mut PlatformNode, name: &str, value: &str, ) -> PlatformResult<()> { // TODO: map to WinUI property setters node.attributes.retain(|a| a.name != name); node.attributes.push(crate::Attribute::new(name, value)); Ok(()) } fn remove_attribute(&self, node: &mut PlatformNode, name: &str) -> PlatformResult<()> { node.attributes.retain(|a| a.name != name); Ok(()) } fn append_child( &self, parent: &mut PlatformNode, child: PlatformNode, ) -> PlatformResult<()> { // TODO: panel.Children().Append(child_element) parent.children.push(child); Ok(()) } fn remove_child(&self, parent: &mut PlatformNode, child_index: usize) -> PlatformResult<()> { if child_index >= parent.children.len() { return Err(PlatformError::Render(format!( "windows: child index {} out of bounds", child_index ))); } // TODO: panel.Children().RemoveAt(child_index) parent.children.remove(child_index); Ok(()) } fn replace_child( &self, parent: &mut PlatformNode, index: usize, new_child: PlatformNode, ) -> PlatformResult<()> { if index >= parent.children.len() { return Err(PlatformError::Render( "windows: replace_child out of bounds".into(), )); } parent.children[index] = new_child; Ok(()) } fn bind_event( &self, node: &mut PlatformNode, event: &str, _handler: EventHandler, ) -> PlatformResult<()> { let winui_event = Self::winui_event(event); // TODO: button.Click(TypedEventHandler::new(|sender, args| { handler(...) })) node.attributes.push(crate::Attribute::new( format!("data-winui-event-{}", event), winui_event, )); Ok(()) } fn render_to_string(&self, node: &PlatformNode) -> PlatformResult { Ok(node.to_html()) } fn mount(&self, _root: PlatformNode, _container_id: &str) -> PlatformResult<()> { // TODO: get Window by container_id, set root as Content Ok(()) } fn patch(&self, _old: &PlatformNode, _new: &PlatformNode) -> PlatformResult<()> { // TODO: diff and apply WinUI mutations Ok(()) } }