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;
12use crate::layout::replaced::IntrinsicSizes;
13
14impl BaseDocument {
15 pub fn can_create_surfaces(&mut self, render_context: &mut dyn RenderContext) {
16 for &node_id in self.custom_widget_nodes.iter() {
17 let node = &mut self.nodes[node_id];
18 if let Some(widget_data) = node
19 .element_data_mut()
20 .and_then(|el| el.custom_widget_data_mut())
21 {
22 let mut render_context = ProxyRenderContext {
23 resource_ids: &mut widget_data.active_resource_ids,
24 inner: render_context,
25 };
26
27 widget_data
28 .widget
29 .can_create_surfaces(&mut render_context as _);
30 }
31 }
32 }
33
34 pub fn destroy_surfaces(&mut self) {
35 for &node_id in self.custom_widget_nodes.iter() {
36 let node = &mut self.nodes[node_id];
37 if let Some(widget_data) = node
38 .element_data_mut()
39 .and_then(|el| el.custom_widget_data_mut())
40 {
41 widget_data.widget.destroy_surfaces();
42 }
43 }
44 }
45}
46
47pub struct ProxyRenderContext<'widget, 'rend> {
51 pub resource_ids: &'widget mut Vec<ResourceId>,
52 pub inner: &'rend mut dyn RenderContext,
53}
54
55impl anyrender::RenderContext for ProxyRenderContext<'_, '_> {
56 fn try_register_custom_resource(
57 &mut self,
58 resource: Box<dyn Any>,
59 ) -> Result<ResourceId, anyrender::RegisterResourceError> {
60 let id = self.inner.try_register_custom_resource(resource)?;
61 self.resource_ids.push(id);
62 Ok(id)
63 }
64
65 fn unregister_resource(&mut self, resource_id: ResourceId) {
66 self.resource_ids.retain(|id| *id != resource_id);
67 self.inner.unregister_resource(resource_id);
68 }
69
70 fn renderer_specific_context(&self) -> Option<Box<dyn std::any::Any>> {
71 self.inner.renderer_specific_context()
72 }
73}
74
75pub trait Widget {
76 fn connected(&mut self) {}
80 fn disconnected(&mut self) {}
82 fn attribute_changed(&mut self, name: &str, old_value: Option<&str>, new_value: Option<&str>) {
84 let _ = (name, old_value, new_value);
85 }
86
87 fn can_create_surfaces(&mut self, render_ctx: &mut dyn RenderContext) {
93 let _ = render_ctx;
94 }
95 fn destroy_surfaces(&mut self) {}
97
98 fn requires_redraw(&self) -> bool {
105 false
106 }
107
108 fn handle_event(&mut self, event: &UiEvent) {
110 let _ = event;
111 }
112
113 fn intrinsic_sizes(&self) -> IntrinsicSizes {
120 IntrinsicSizes::default()
121 }
122
123 fn paint(
131 &mut self,
132 render_ctx: &mut dyn RenderContext,
133 styles: &ComputedStyles,
134 width: u32,
135 height: u32,
136 scale: f64,
137 ) -> Scene {
138 let _ = (render_ctx, styles, width, height, scale);
139 Scene::new()
140 }
141
142 }
148
149#[derive(Debug, Copy, Clone, Eq, PartialEq)]
150pub enum CustomWidgetStatus {
151 Suspended,
152 Active,
153 PendingRemoval,
154}
155
156pub struct CustomWidgetData {
157 pub widget: Box<dyn Widget>,
159 pub status: CustomWidgetStatus,
161 pub active_resource_ids: Vec<ResourceId>,
164}
165
166impl CustomWidgetData {
167 pub(crate) fn new(widget: Box<dyn Widget>) -> Self {
168 Self {
169 widget,
170 status: CustomWidgetStatus::Suspended,
171 active_resource_ids: Vec::new(),
172 }
173 }
174
175 pub(crate) fn take_resource_ids(&mut self) -> Vec<ResourceId> {
176 core::mem::take(&mut self.active_resource_ids)
177 }
178}