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