blitz_dom/node/
custom_widget.rs1use std::any::Any;
2
3use anyrender::ResourceId;
4use blitz_traits::events::UiEvent;
5pub use style::properties::ComputedValues as ComputedStyles;
6pub use anyrender::{RenderContext, Scene};
10
11use crate::BaseDocument;
12
13impl BaseDocument {
14 pub fn can_create_surfaces(&mut self, render_context: &mut dyn RenderContext) {
15 for &node_id in self.custom_widget_nodes.iter() {
16 let node = &mut self.nodes[node_id];
17 if let Some(widget_data) = node
18 .element_data_mut()
19 .and_then(|el| el.custom_widget_data_mut())
20 {
21 let mut render_context = ProxyRenderContext {
22 resource_ids: &mut widget_data.active_resource_ids,
23 inner: render_context,
24 };
25
26 widget_data
27 .widget
28 .can_create_surfaces(&mut render_context as _);
29 }
30 }
31 }
32
33 pub fn destroy_surfaces(&mut self) {
34 for &node_id in self.custom_widget_nodes.iter() {
35 let node = &mut self.nodes[node_id];
36 if let Some(widget_data) = node
37 .element_data_mut()
38 .and_then(|el| el.custom_widget_data_mut())
39 {
40 widget_data.widget.destroy_surfaces();
41 }
42 }
43 }
44}
45
46pub struct ProxyRenderContext<'widget, 'rend> {
50 pub resource_ids: &'widget mut Vec<ResourceId>,
51 pub inner: &'rend mut dyn RenderContext,
52}
53
54impl anyrender::RenderContext for ProxyRenderContext<'_, '_> {
55 fn try_register_custom_resource(
56 &mut self,
57 resource: Box<dyn Any>,
58 ) -> Result<ResourceId, anyrender::RegisterResourceError> {
59 let id = self.inner.try_register_custom_resource(resource)?;
60 self.resource_ids.push(id);
61 Ok(id)
62 }
63
64 fn unregister_resource(&mut self, resource_id: ResourceId) {
65 self.resource_ids.retain(|id| *id != resource_id);
66 self.inner.unregister_resource(resource_id);
67 }
68
69 fn renderer_specific_context(&self) -> Option<Box<dyn std::any::Any>> {
70 self.inner.renderer_specific_context()
71 }
72}
73
74pub trait Widget {
75 fn connected(&mut self) {}
79 fn disconnected(&mut self) {}
81 fn attribute_changed(&mut self, name: &str, old_value: Option<&str>, new_value: Option<&str>) {
83 let _ = (name, old_value, new_value);
84 }
85
86 fn can_create_surfaces(&mut self, render_ctx: &mut dyn RenderContext) {
92 let _ = render_ctx;
93 }
94 fn destroy_surfaces(&mut self) {}
96
97 fn handle_event(&mut self, event: &UiEvent) {
101 let _ = event;
102 }
103
104 fn paint(
112 &mut self,
113 render_ctx: &mut dyn RenderContext,
114 styles: &ComputedStyles,
115 width: u32,
116 height: u32,
117 scale: f64,
118 ) -> Scene {
119 let _ = (render_ctx, styles, width, height, scale);
120 Scene::new()
121 }
122
123 }
129
130#[derive(Debug, Copy, Clone, Eq, PartialEq)]
131pub enum CustomWidgetStatus {
132 Suspended,
133 Active,
134 PendingRemoval,
135}
136
137pub struct CustomWidgetData {
138 pub widget: Box<dyn Widget>,
140 pub status: CustomWidgetStatus,
142 pub active_resource_ids: Vec<ResourceId>,
145}
146
147impl CustomWidgetData {
148 pub(crate) fn new(widget: Box<dyn Widget>) -> Self {
149 Self {
150 widget,
151 status: CustomWidgetStatus::Suspended,
152 active_resource_ids: Vec::new(),
153 }
154 }
155
156 pub(crate) fn take_resource_ids(&mut self) -> Vec<ResourceId> {
157 core::mem::take(&mut self.active_resource_ids)
158 }
159}