use std::{marker::Unsize, mem::MaybeUninit, ops::CoerceUnsized}; use crate::{ layout::{EventManager, IdFnTag, IdTag, Ui, WIDGETS, Widget, WidgetData, WidgetLike}, util::{ Handle, MappedRefGuard, MappedRefGuardMut, Ref, RefGuard, RefGuardMut, RefMap, RefMapMut, RefMut, WeakHandle, }, }; pub(super) type SlotTy = u32; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct WidgetId { pub(super) i: SlotTy, pub(super) genr: SlotTy, } /// A strong handle to a widget. Cannot be cloned, only one may exist /// Use .weak() to obtain weak references to this pub struct WidgetHandle(WidgetId, Handle>); /// A weak handle to a widget. Implements Copy so you can easily pass into closures pub struct WidgetRef(WidgetId, *const W); pub type WidgetUpdate = WidgetId; impl WidgetHandle { pub(super) fn new(id: WidgetId, widget: W) -> Self { let mut label = std::any::type_name::().to_string(); if let (Some(first), Some(last)) = (label.find(":"), label.rfind(":")) { label = label.split_at(first).0.to_string() + "::" + label.split_at(last + 1).1; } Self( id, WidgetData { id, widget, send: None, label, event_managers: Default::default(), } .into(), ) } } impl> WidgetHandle { pub(super) fn weak_inner(&self) -> WeakHandle> { self.1.weak() } pub fn any(self) -> WidgetHandle { self } /// DO NOT CALL OTHER THAN TEMP IN PAINTER pub(crate) fn as_any(&self) -> WidgetHandle { WidgetHandle(self.0, self.1.clone()) } } impl WidgetHandle { pub fn id(&self) -> WidgetId { self.0 } pub fn get(&self) -> RefMap<'_, W> { Ref::map(self.1.get(), |i| &mut i.widget) } pub fn get_mut(&self) -> RefMapMut<'_, W> { let inner = self.1.get_mut(); if let Some(send) = &inner.send { let _ = send.send(self.0); } RefMut::map(inner, |i| &mut i.widget) } pub fn data(&self) -> Ref<'_, WidgetData> { self.1.get() } pub(crate) fn data_mut(&self) -> RefMut<'_, WidgetData> { self.1.get_mut() } pub(crate) fn get_mut_quiet(&self) -> RefMapMut<'_, W> { RefMut::map(self.1.get_mut(), |i| &mut i.widget) } pub fn get_label(&self) -> RefMap<'_, String> { Ref::map(self.1.get(), |i| &mut i.label) } pub fn set_label(&self, label: impl Into) { self.1.get_mut().label = label.into(); } /// TODO: THIS SHOULD ALWAYS BE 1, remove this probably (weak count might be nice though) pub fn refs(&self) -> usize { self.1.refs() } pub fn weak(&self) -> WidgetRef { WidgetRef::new(self.0) } } pub type WRef<'a, W> = MappedRefGuard<'a, WidgetData, W>; pub type WRefMut<'a, W> = MappedRefGuardMut<'a, WidgetData, W>; impl WidgetRef { fn handle(&self) -> Handle> { WIDGETS.get_type(self.0).unwrap() } pub fn get<'a>(&self) -> WRef<'a, W> { RefGuard::map(self.handle().get_take(), |i| &mut i.widget) } pub fn get_mut<'a>(&self) -> WRefMut<'a, W> { let inner = self.handle().get_take_mut(); if let Some(send) = &inner.send { let _ = send.send(self.0); } RefGuardMut::map(inner, |i| &mut i.widget) } } impl WidgetRef { pub fn data<'a>(&self) -> Option>> { Some(WIDGETS.get(self.0)?.get_take()) } pub(crate) fn data_mut(&self) -> Option>> { Some(WIDGETS.get(self.0)?.get_take_mut()) } } impl> WidgetRef { pub fn any(self) -> WidgetRef { WidgetRef::new(self.0) } } impl WidgetRef { fn new(id: WidgetId) -> Self { Self(id, unsafe { MaybeUninit::zeroed().assume_init() }) } pub fn id(&self) -> WidgetId { self.0 } } impl WidgetId { /// THIS SHOULD ONLY BE CALLED FOR TEMP STUFF DURING PAINTING pub(crate) fn strong(self) -> Option { Some(WidgetHandle(self, WIDGETS.get(self)?)) } pub fn weak(self) -> WidgetRef { WidgetRef::new(self) } pub(crate) fn map_event_managers(&self, f: impl Fn(Handle)) { let Some(data) = self.weak().data() else { return; }; for m in data.event_managers() { f(m) } } } pub trait WidgetIdFn: FnOnce(&mut Ui) -> WidgetHandle {} impl WidgetHandle> WidgetIdFn for F {} pub trait WidgetRet: FnOnce(&mut Ui) -> WidgetHandle {} impl WidgetHandle> WidgetRet for F {} impl + 'static> WidgetLike for WidgetHandle { type Widget = W; fn add(self, _: &mut Ui) -> WidgetHandle { self } } impl + 'static, F: FnOnce(&mut Ui) -> WidgetHandle> WidgetLike for F { type Widget = W; fn add(self, ui: &mut Ui) -> WidgetHandle { self(ui) } } pub trait IdLike { fn id(&self) -> WidgetId; } impl IdLike for WidgetHandle { fn id(&self) -> WidgetId { self.id() } } impl IdLike for WidgetRef { fn id(&self) -> WidgetId { self.id() } } impl, U: ?Sized> CoerceUnsized> for WidgetHandle {} impl, U: ?Sized> CoerceUnsized> for WidgetRef {} impl PartialEq for WidgetHandle { fn eq(&self, other: &Self) -> bool { self.id() == other.id() } } impl std::fmt::Debug for WidgetHandle { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.id().fmt(f) } } impl Clone for WidgetRef { fn clone(&self) -> Self { *self } } impl Copy for WidgetRef {} impl PartialEq for WidgetRef { fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } unsafe impl Send for WidgetRef {} unsafe impl Sync for WidgetRef {}