dioxus_native_dom/
write_once_attr.rs1use std::{cell::RefCell, rc::Rc, sync::atomic::AtomicUsize};
2
3use blitz_dom::{Document, Widget};
4use dioxus_core::{AttributeValue, IntoAttributeValue};
5
6#[derive(Clone, PartialEq)]
7pub struct SubDocumentAttr(WriteOnceAttr<Box<dyn Document>>);
8
9impl SubDocumentAttr {
10 pub fn new(doc: impl Document) -> Self {
12 let id = doc.id();
13 Self(WriteOnceAttr::new(id, Box::new(doc) as Box<dyn Document>))
14 }
15}
16
17impl IntoAttributeValue for SubDocumentAttr {
18 fn into_value(self) -> AttributeValue {
19 AttributeValue::Any(Rc::new(self.0))
20 }
21}
22
23static ID_COUNTER: AtomicUsize = AtomicUsize::new(0);
24
25#[derive(Clone, PartialEq)]
26pub struct CustomWidgetAttr(WriteOnceAttr<Box<dyn Widget>>);
27
28impl CustomWidgetAttr {
29 pub fn new<T: Widget + 'static>(widget: T) -> Self {
30 let id = ID_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
31 let boxed = Box::new(widget) as Box<dyn Widget>;
32 Self(WriteOnceAttr::new(id, boxed))
33 }
34}
35
36impl IntoAttributeValue for CustomWidgetAttr {
37 fn into_value(self) -> AttributeValue {
38 AttributeValue::Any(Rc::new(self.0))
39 }
40}
41
42pub(crate) struct WriteOnceAttr<T> {
43 id: usize,
44 value: Rc<RefCell<Option<T>>>,
45}
46
47impl<T> WriteOnceAttr<T> {
48 pub(crate) fn new(id: usize, value: T) -> Self {
49 let value = Rc::new(RefCell::new(Some(value)));
50 Self { id, value }
51 }
52 pub(crate) fn take(&self) -> Option<T> {
53 self.value.borrow_mut().take()
54 }
55}
56
57impl<T> Clone for WriteOnceAttr<T> {
58 fn clone(&self) -> Self {
59 Self {
60 id: self.id,
61 value: Rc::clone(&self.value),
62 }
63 }
64}
65
66impl<T> PartialEq for WriteOnceAttr<T> {
67 fn eq(&self, other: &Self) -> bool {
68 self.id == other.id
69 }
70}