Skip to main content

dioxus_native_dom/
write_once_attr.rs

1use 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}