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