use std::{
any::{Any, TypeId},
cell::{Cell, Ref, RefCell, RefMut, UnsafeCell},
collections::{HashMap, HashSet},
hash::Hash,
rc::Rc,
sync::Arc,
};
use druid_shell::IdleToken;
use crate::{
api::{
contexts::{render_ctx::AnyRenderContext, Context},
events::Event,
local_key::LocalKeyAny,
IntoWidgetPtr, WidgetPtr,
},
app::runner::handler::{APP_HANDLE, NEED_REBUILD},
prelude::{Constraints, Offset, PaintContext, Size, WidgetKind},
};
pub struct WidgetTree {
dummy_root: UnsafeCell<Box<WidgetNode>>,
}
impl WidgetTree {
pub fn new(root_widget: WidgetPtr) -> Self {
let mut dummy_root = WidgetNode::default();
let root = WidgetNode::new(root_widget, None, WidgetNode::node_ref(&dummy_root));
unsafe { (&mut *dummy_root.children_ptr_mut()).push(root) };
Self { dummy_root }
}
pub(crate) fn layout(&mut self, constraints: Constraints) {
AnyRenderContext::new(self.get_root()).layout(constraints);
}
pub(crate) fn paint(&mut self, piet: &mut PaintContext) {
AnyRenderContext::new(self.get_root()).paint(piet, &Offset::default());
}
pub(crate) fn handle_event(&mut self, event: Event) {
self.get_root().handle_event(event);
}
fn get_root(&mut self) -> WidgetNodeRef {
unsafe { WidgetNode::node_ref(&(&*self.dummy_root.children_ptr_mut())[0]) }
}
}
impl Default for WidgetTree {
fn default() -> Self {
Self {
dummy_root: WidgetNode::default(),
}
}
}
impl Drop for WidgetTree {
fn drop(&mut self) {
unsafe { WidgetNode::drop_mut(&mut self.dummy_root) };
}
}
#[derive(Clone)]
pub struct IsAlive(pub Arc<Cell<bool>>);
impl IsAlive {
pub fn new() -> Self {
IsAlive(Arc::new(Cell::new(true)))
}
}
pub(crate) enum Inheritance {
Inheritor {
active_inheritors: HashMap<TypeId, WidgetNodeRef>,
inheriting_widgets: HashSet<WidgetNodeRef>,
},
Inheritee {
inherited_ancestor: WidgetNodeRef,
inherits_from: HashSet<WidgetNodeRef>,
},
}
pub(crate) struct WidgetInner {
pub dirty: bool,
pub state: Box<dyn Any>,
pub render_data: RenderData,
pub inheritance: Inheritance,
}
pub(crate) struct WidgetNode {
widget_ptr: WidgetPtr<'static>,
context: Context,
inner: RefCell<WidgetInner>,
parent: Option<WidgetNodeRef>,
children: Vec<UnsafeCell<Box<WidgetNode>>>,
}
impl WidgetNode {
fn new(
widget: WidgetPtr,
parent: Option<WidgetNodeRef>,
mut inherited_ancestor: WidgetNodeRef,
) -> UnsafeCell<Box<Self>> {
let widget_ptr =
unsafe { std::mem::transmute::<WidgetPtr, WidgetPtr<'static>>(widget.clone()) };
let mut this = UnsafeCell::new(Box::new(WidgetNode {
widget_ptr,
context: Context {
node: WidgetNodeRef {
is_alive: Rc::new(Cell::new(true)),
ptr: std::ptr::null_mut(), },
},
inner: RefCell::new(WidgetInner {
dirty: false,
state: widget.create_state(),
render_data: RenderData::new(&widget),
inheritance: Inheritance::new(&widget, &inherited_ancestor),
}),
parent,
children: Vec::new(),
}));
let (inner_ref, context_ref_mut, children_ref_mut) = (
unsafe { &*this.inner_ptr() },
unsafe { &mut *this.context_ptr_mut() },
unsafe { &mut *this.children_ptr_mut() },
);
context_ref_mut.node.ptr = this.node_ptr_mut();
let node_ref = WidgetNode::node_ref(&this);
let mut inner = inner_ref.borrow_mut();
if let Inheritance::Inheritor {
ref mut active_inheritors,
..
} = inner.inheritance
{
inherited_ancestor = node_ref.clone();
active_inheritors.insert(widget.inherited_key(), node_ref.clone());
}
drop(inner);
let children = unsafe {
widget
.build(&*this.context_ptr())
.into_iter()
.map(|child_widget_ptr| {
WidgetNode::new(
child_widget_ptr,
Some(node_ref.clone()),
inherited_ancestor.clone(),
)
})
.collect::<Vec<_>>()
};
*children_ref_mut = children;
WidgetNode::mount(&this);
this
}
pub fn update_subtree(s: &UnsafeCell<Box<Self>>) {
unsafe { Self::update_subtree_ptr(std::ptr::addr_of_mut!(*(*s.get()))) }
}
pub unsafe fn update_subtree_ptr(s: *mut WidgetNode) {
let (inner_ref, widget_ref, context_ref, old_children_ref) = (
&*s.inner_ptr(),
&*s.widget_ptr(),
&*s.context_ptr(),
&mut *s.children_ptr_mut(),
);
inner_ref.borrow_mut().dirty = false;
let inherited_ancestor = &inner_ref
.borrow_mut()
.inheritance
.inherited_ancestor(&context_ref.node);
let mut old_children = std::mem::take(old_children_ref)
.into_iter()
.map(|c| Some(c))
.collect::<Vec<_>>();
let new_children_build = widget_ref.build(context_ref);
let mut new_children = Vec::with_capacity(new_children_build.len());
for (n, new_child) in new_children_build.into_iter().enumerate() {
if new_child.has_key() {
if let Some(n) = old_children.find_key(&new_child) {
let old_child = std::mem::take(old_children.get_mut(n).unwrap()).unwrap();
new_children.push(WidgetNode::update(old_child, new_child));
} else {
let child = WidgetNode::new(
new_child,
Some(context_ref.node.clone()),
inherited_ancestor.clone(),
);
new_children.push(child);
}
} else {
if let Some(Some(old_child)) = old_children.get(n) {
if (&*old_child.widget_ptr()).has_key() {
let child = WidgetNode::new(
new_child,
Some(context_ref.node.clone()),
inherited_ancestor.clone(),
);
new_children.push(child);
} else {
let old_child = std::mem::take(old_children.get_mut(n).unwrap()).unwrap();
new_children.push(WidgetNode::update(old_child, new_child));
}
} else {
let child = WidgetNode::new(
new_child,
Some(context_ref.node.clone()),
inherited_ancestor.clone(),
);
new_children.push(child);
}
}
}
for old_child in old_children.into_iter() {
if let Some(old_child) = old_child {
WidgetNode::drop(old_child);
}
}
*old_children_ref = new_children;
}
pub fn update(mut s: UnsafeCell<Box<Self>>, new_widget: WidgetPtr) -> UnsafeCell<Box<Self>> {
let new_widget =
unsafe { std::mem::transmute::<WidgetPtr, WidgetPtr<'static>>(new_widget) };
let (widget_ref, parent_ref, context_ref) =
unsafe { (&*s.widget_ptr(), &*s.parent_ptr(), &*s.context_ptr()) };
if widget_ref.can_update(&new_widget) {
if widget_ref.eq(&new_widget) {
unsafe { WidgetPtr::drop(new_widget) };
return s;
} else {
WidgetNode::unmount(&s);
let old_widget_ptr =
unsafe { std::mem::replace(&mut *s.widget_ptr_mut(), new_widget) };
WidgetNode::update_subtree(&s);
unsafe { WidgetPtr::drop(old_widget_ptr) };
WidgetNode::mount(&s);
return s;
}
} else {
let parent = parent_ref.clone();
let inherited_ancestor = parent
.as_ref()
.unwrap()
.borrow()
.inheritance
.inherited_ancestor(&context_ref.node);
WidgetNode::drop(s);
return WidgetNode::new(new_widget, parent, inherited_ancestor);
}
}
pub unsafe fn handle_event(s: &WidgetNodeRef, event: &Event) {
let widget_ref = &*s.ptr.widget_ptr();
let children_ref = &*s.ptr.children_ptr();
let mut render_ctx = AnyRenderContext::new(s.clone());
if !widget_ref.handle_event(&mut render_ctx, event) {
for child in children_ref.iter() {
let child = WidgetNode::node_ref(child);
WidgetNode::handle_event(&child, event);
}
}
}
pub fn drop(mut s: UnsafeCell<Box<Self>>) {
unsafe { WidgetNode::drop_mut(&mut s) };
}
pub unsafe fn drop_mut(s: &mut UnsafeCell<Box<Self>>) {
let s_ptr_mut = std::ptr::addr_of_mut!(**s.get());
let inner_ref = std::ptr::addr_of!((*s_ptr_mut).inner);
let children_ref_mut = std::ptr::addr_of_mut!((*s_ptr_mut).children);
let mut children = std::mem::take(&mut *children_ref_mut).into_iter();
while let Some(child) = children.next() {
WidgetNode::drop(child);
}
WidgetNode::unmount(&s);
match &(&*inner_ref).borrow().inheritance {
Inheritance::Inheritee {
inherited_ancestor: _,
inherits_from,
} => {
let node_ref = &WidgetNode::node_ref(s);
for inheritor in inherits_from.iter() {
let mut inheritor_ref = inheritor.borrow_mut();
let inheriting_widgets = inheritor_ref.inheritance.inheriting_widgets();
inheriting_widgets.remove(node_ref);
}
}
Inheritance::Inheritor { .. } => {}
};
let s = &mut *s_ptr_mut;
if let Some(ptr) = s.widget_ptr.owned {
drop(Box::from_raw(ptr));
}
s.context.node.is_alive.set(false);
}
#[allow(unused)]
pub fn debug_name_short(s: &UnsafeCell<Box<Self>>) -> &'static str {
let widget = unsafe { &*s.widget_ptr() };
widget.debug_name_short()
}
pub fn mount(s: &UnsafeCell<Box<Self>>) {
let widget = unsafe { &*s.widget_ptr() };
let context = unsafe { &*s.context_ptr() };
widget.mount(context)
}
pub fn unmount(s: &UnsafeCell<Box<Self>>) {
let widget = unsafe { &*s.widget_ptr() };
let context = unsafe { &*s.context_ptr() };
widget.unmount(context)
}
pub fn node_ref(s: &UnsafeCell<Box<Self>>) -> WidgetNodeRef {
unsafe { (&*s.context_ptr()).node.clone() }
}
pub fn local_key<'a>(s: &UnsafeCell<Box<WidgetNode>>) -> Option<LocalKeyAny<'a>> {
unsafe { (&*s.widget_ptr()).local_key() }
}
}
#[derive(Clone)]
pub(crate) struct WidgetNodeRef {
is_alive: Rc<Cell<bool>>,
ptr: *mut WidgetNode,
}
impl WidgetNodeRef {
#[track_caller]
pub fn borrow(&self) -> Ref<'_, WidgetInner> {
assert_eq!(self.is_alive.get(), true);
unsafe { (&*self.ptr.inner_ptr()).borrow() }
}
#[track_caller]
pub fn borrow_mut(&self) -> RefMut<'_, WidgetInner> {
assert_eq!(self.is_alive.get(), true);
unsafe { (&*self.ptr.inner_ptr()).borrow_mut() }
}
pub fn update_subtree(&self) {
assert_eq!(self.is_alive.get(), true);
unsafe { WidgetNode::update_subtree_ptr(self.ptr) }
}
pub fn handle_event(&self, event: Event) {
assert_eq!(self.is_alive.get(), true);
unsafe { WidgetNode::handle_event(self, &event) }
}
pub fn mark_dirty(&self) {
assert_eq!(self.is_alive.get(), true);
APP_HANDLE.with(|handle| {
handle
.borrow_mut()
.as_mut()
.expect("APP_HANDLE wasn't set")
.schedule_idle(IdleToken::new(0));
});
if !self.borrow_mut().dirty {
self.borrow_mut().dirty = true;
NEED_REBUILD.with(|dirty| {
dirty.lock().unwrap().push(self.clone());
});
}
}
pub fn mark_dependent_widgets_as_dirty(&self) {
assert_eq!(self.is_alive.get(), true);
match &self.borrow().inheritance {
Inheritance::Inheritor {
inheriting_widgets, ..
} => {
for widget in inheriting_widgets.iter() {
widget.mark_dirty()
}
}
_ => unreachable!(),
}
}
pub fn depend_on_inherited_widget_of_key<'a, K>(&'a self) -> Option<WidgetNodeRef>
where
K: 'static,
{
assert_eq!(self.is_alive.get(), true);
let key = TypeId::of::<K>();
let mut node_ref = self.borrow_mut();
let (inherited_ancestor, inherits_from) = match &mut node_ref.inheritance {
Inheritance::Inheritee {
inherited_ancestor,
inherits_from,
} => (inherited_ancestor, inherits_from),
_ => unreachable!(),
};
let inherited_ref = inherited_ancestor.borrow();
let active_inheritors = match &inherited_ref.inheritance {
Inheritance::Inheritor {
active_inheritors, ..
} => active_inheritors,
_ => unreachable!(),
};
let inherited_widget = active_inheritors.get(&key)?.clone();
drop(inherited_ref);
let mut inherited_widget_ref = inherited_widget.borrow_mut();
let inheriting_widgets = match &mut inherited_widget_ref.inheritance {
Inheritance::Inheritor {
inheriting_widgets, ..
} => inheriting_widgets,
_ => unreachable!(),
};
inheriting_widgets.insert(self.clone());
inherits_from.insert(inherited_widget.clone());
Some(inherited_widget.clone())
}
pub fn is_alive(&self) -> bool {
self.is_alive.get()
}
#[track_caller]
pub fn widget<'a>(&'a self) -> &'a WidgetPtr<'static> {
assert!(self.is_alive.get());
unsafe { &*self.ptr.widget_ptr() }
}
#[track_caller]
pub fn children<'a>(&'a self) -> &'a [UnsafeCell<Box<WidgetNode>>] {
assert!(self.is_alive.get());
unsafe { &*self.ptr.children_ptr() }
}
}
impl PartialEq for WidgetNodeRef {
fn eq(&self, other: &Self) -> bool {
self.is_alive.as_ptr() == other.is_alive.as_ptr()
}
}
impl Eq for WidgetNodeRef {}
impl Hash for WidgetNodeRef {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.is_alive.as_ptr().hash(state);
}
}
pub(crate) struct RenderData {
pub state: Box<dyn Any>,
pub size: Size,
pub offset: Offset,
pub laid_out: bool,
}
impl RenderData {
fn new(widget: &WidgetPtr) -> RenderData {
RenderData {
state: widget.create_render_state(),
size: Size::default(),
offset: Offset::default(),
laid_out: false,
}
}
}
impl Inheritance {
fn new(widget: &WidgetPtr, inherited_ancestor: &WidgetNodeRef) -> Self {
match widget.kind {
WidgetKind::Inherited(_) => Inheritance::Inheritor {
active_inheritors: inherited_ancestor
.borrow()
.inheritance
.active_inheritors()
.clone(),
inheriting_widgets: HashSet::new(),
},
_ => Inheritance::Inheritee {
inherited_ancestor: inherited_ancestor.clone(),
inherits_from: HashSet::new(),
},
}
}
fn active_inheritors(&self) -> &HashMap<TypeId, WidgetNodeRef> {
match self {
Self::Inheritor {
active_inheritors, ..
} => active_inheritors,
Self::Inheritee { .. } => unreachable!(),
}
}
fn inherited_ancestor(&self, self_node: &WidgetNodeRef) -> WidgetNodeRef {
match self {
Inheritance::Inheritor { .. } => self_node.clone(),
Inheritance::Inheritee {
inherited_ancestor, ..
} => inherited_ancestor.clone(),
}
}
fn inheriting_widgets(&mut self) -> &mut HashSet<WidgetNodeRef> {
match self {
Inheritance::Inheritor {
inheriting_widgets, ..
} => inheriting_widgets,
Inheritance::Inheritee { .. } => unreachable!(),
}
}
}
impl Default for Inheritance {
fn default() -> Self {
Inheritance::Inheritor {
active_inheritors: HashMap::new(),
inheriting_widgets: HashSet::new(),
}
}
}
trait FindKey {
fn find_key(&mut self, key: &WidgetPtr) -> Option<usize>;
}
impl FindKey for Vec<Option<UnsafeCell<Box<WidgetNode>>>> {
fn find_key(&mut self, key: &WidgetPtr) -> Option<usize> {
if let None = key.local_key() {
return None;
}
self.iter_mut()
.enumerate()
.find(|(_, w)| match w {
Some(w) => match WidgetNode::local_key(w) {
Some(k) => k == key.local_key().unwrap(),
None => false,
},
None => false,
})
.map(|(n, _)| n)
}
}
impl WidgetNode {
fn default() -> UnsafeCell<Box<Self>> {
let widget_ptr =
unsafe { std::mem::transmute::<WidgetPtr, WidgetPtr<'static>>(().into_widget_ptr()) };
let mut this = UnsafeCell::new(Box::new(WidgetNode {
widget_ptr: widget_ptr.clone(),
context: Context {
node: WidgetNodeRef {
is_alive: Rc::new(Cell::new(true)),
ptr: std::ptr::null_mut(), },
},
inner: RefCell::new(WidgetInner {
dirty: false,
state: widget_ptr.create_state(),
render_data: RenderData::new(&widget_ptr),
inheritance: Inheritance::Inheritor {
active_inheritors: HashMap::new(),
inheriting_widgets: HashSet::new(),
},
}),
parent: None,
children: Vec::new(),
}));
unsafe {
(&mut *this.context_ptr_mut()).node.ptr = this.node_ptr_mut(); };
this
}
}
trait WidgetNodePtrExt {
fn inner_ptr(&self) -> *const RefCell<WidgetInner>;
fn widget_ptr(&self) -> *const WidgetPtr<'static>;
fn parent_ptr(&self) -> *const Option<WidgetNodeRef>;
fn context_ptr(&self) -> *const Context;
fn children_ptr(&self) -> *const Vec<UnsafeCell<Box<WidgetNode>>>;
fn inner_ptr_mut(&self) -> *mut RefCell<WidgetInner>;
fn widget_ptr_mut(&self) -> *mut WidgetPtr<'static>;
fn parent_ptr_mut(&self) -> *mut Option<WidgetNodeRef>;
fn context_ptr_mut(&self) -> *mut Context;
fn children_ptr_mut(&self) -> *mut Vec<UnsafeCell<Box<WidgetNode>>>;
}
impl WidgetNodePtrExt for *mut WidgetNode {
fn context_ptr(&self) -> *const Context {
unsafe { std::ptr::addr_of!((**self).context) }
}
fn widget_ptr(&self) -> *const WidgetPtr<'static> {
unsafe { std::ptr::addr_of!((**self).widget_ptr) }
}
fn inner_ptr(&self) -> *const RefCell<WidgetInner> {
unsafe { std::ptr::addr_of!((**self).inner) }
}
fn parent_ptr(&self) -> *const Option<WidgetNodeRef> {
unsafe { std::ptr::addr_of!((**self).parent) }
}
fn children_ptr(&self) -> *const Vec<UnsafeCell<Box<WidgetNode>>> {
unsafe { std::ptr::addr_of!((**self).children) }
}
fn context_ptr_mut(&self) -> *mut Context {
unsafe { std::ptr::addr_of_mut!((**self).context) }
}
fn widget_ptr_mut(&self) -> *mut WidgetPtr<'static> {
unsafe { std::ptr::addr_of_mut!((**self).widget_ptr) }
}
fn inner_ptr_mut(&self) -> *mut RefCell<WidgetInner> {
unsafe { std::ptr::addr_of_mut!((**self).inner) }
}
fn parent_ptr_mut(&self) -> *mut Option<WidgetNodeRef> {
unsafe { std::ptr::addr_of_mut!((**self).parent) }
}
fn children_ptr_mut(&self) -> *mut Vec<UnsafeCell<Box<WidgetNode>>> {
unsafe { std::ptr::addr_of_mut!((**self).children) }
}
}
trait UnsafeCellWidgetNodePtrExt {
fn node_ptr(&self) -> *const WidgetNode;
fn inner_ptr(&self) -> *const RefCell<WidgetInner>;
fn widget_ptr(&self) -> *const WidgetPtr<'static>;
fn parent_ptr(&self) -> *const Option<WidgetNodeRef>;
fn context_ptr(&self) -> *const Context;
fn children_ptr(&self) -> *const Vec<UnsafeCell<Box<WidgetNode>>>;
fn node_ptr_mut(&self) -> *mut WidgetNode;
fn inner_ptr_mut(&mut self) -> *mut RefCell<WidgetInner>;
fn widget_ptr_mut(&mut self) -> *mut WidgetPtr<'static>;
fn parent_ptr_mut(&mut self) -> *mut Option<WidgetNodeRef>;
fn context_ptr_mut(&mut self) -> *mut Context;
fn children_ptr_mut(&mut self) -> *mut Vec<UnsafeCell<Box<WidgetNode>>>;
}
impl UnsafeCellWidgetNodePtrExt for UnsafeCell<Box<WidgetNode>> {
fn node_ptr(&self) -> *const WidgetNode {
unsafe { std::ptr::addr_of!(**self.get()) }
}
fn inner_ptr(&self) -> *const RefCell<WidgetInner> {
unsafe { std::ptr::addr_of!((*self.get()).inner) }
}
fn widget_ptr(&self) -> *const WidgetPtr<'static> {
unsafe { std::ptr::addr_of!((*self.get()).widget_ptr) }
}
fn parent_ptr(&self) -> *const Option<WidgetNodeRef> {
unsafe { std::ptr::addr_of!((*self.get()).parent) }
}
fn context_ptr(&self) -> *const Context {
unsafe { std::ptr::addr_of!((*self.get()).context) }
}
fn children_ptr(&self) -> *const Vec<UnsafeCell<Box<WidgetNode>>> {
unsafe { std::ptr::addr_of!((*self.get()).children) }
}
fn node_ptr_mut(&self) -> *mut WidgetNode {
unsafe { std::ptr::addr_of_mut!(**self.get()) }
}
fn inner_ptr_mut(&mut self) -> *mut RefCell<WidgetInner> {
unsafe { std::ptr::addr_of_mut!((*self.get()).inner) }
}
fn widget_ptr_mut(&mut self) -> *mut WidgetPtr<'static> {
unsafe { std::ptr::addr_of_mut!((*self.get()).widget_ptr) }
}
fn parent_ptr_mut(&mut self) -> *mut Option<WidgetNodeRef> {
unsafe { std::ptr::addr_of_mut!((*self.get()).parent) }
}
fn context_ptr_mut(&mut self) -> *mut Context {
unsafe { std::ptr::addr_of_mut!((*self.get()).context) }
}
fn children_ptr_mut(&mut self) -> *mut Vec<UnsafeCell<Box<WidgetNode>>> {
unsafe { std::ptr::addr_of_mut!((*self.get()).children) }
}
}