157 lines
4.8 KiB
Rust
157 lines
4.8 KiB
Rust
//! 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<PlatformNode> {
|
|
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<PlatformNode> {
|
|
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<String> {
|
|
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(())
|
|
}
|
|
}
|