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 requires_redraw(&self) -> bool {
104 false
105 }
106
107 fn handle_event(&mut self, event: &UiEvent) {
109 let _ = event;
110 }
111
112 fn paint(
120 &mut self,
121 render_ctx: &mut dyn RenderContext,
122 styles: &ComputedStyles,
123 width: u32,
124 height: u32,
125 scale: f64,
126 ) -> Scene {
127 let _ = (render_ctx, styles, width, height, scale);
128 Scene::new()
129 }
130
131 }
137
138#[derive(Debug, Copy, Clone, Eq, PartialEq)]
139pub enum CustomWidgetStatus {
140 Suspended,
141 Active,
142 PendingRemoval,
143}
144
145pub struct CustomWidgetData {
146 pub widget: Box<dyn Widget>,
148 pub status: CustomWidgetStatus,
150 pub active_resource_ids: Vec<ResourceId>,
153}
154
155impl CustomWidgetData {
156 pub(crate) fn new(widget: Box<dyn Widget>) -> Self {
157 Self {
158 widget,
159 status: CustomWidgetStatus::Suspended,
160 active_resource_ids: Vec::new(),
161 }
162 }
163
164 pub(crate) fn take_resource_ids(&mut self) -> Vec<ResourceId> {
165 core::mem::take(&mut self.active_resource_ids)
166 }
167}