refcount ids and delete unused
This commit is contained in:
@@ -1,72 +1,12 @@
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
use crate::{Painter, Ui, util::Id};
|
||||
use crate::{Painter, Ui, WidgetId, WidgetIdFnRet};
|
||||
use std::{any::Any, marker::PhantomData};
|
||||
|
||||
pub trait Widget<Ctx>: Any {
|
||||
fn draw(&self, painter: &mut Painter<Ctx>);
|
||||
}
|
||||
|
||||
pub struct AnyWidget;
|
||||
|
||||
/// An identifier for a widget.
|
||||
/// Can index a UI to get the associated widget.
|
||||
///
|
||||
/// W does not need to implement widget so that AnyWidget is valid;
|
||||
/// Instead, add generic bounds on methods that take an ID if they need specific data.
|
||||
#[repr(C)]
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
pub struct WidgetId<W = AnyWidget> {
|
||||
pub(super) ty: TypeId,
|
||||
pub(super) id: Id,
|
||||
_pd: PhantomData<W>,
|
||||
}
|
||||
|
||||
impl<W> std::fmt::Debug for WidgetId<W> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.id.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: temp
|
||||
impl<W> Clone for WidgetId<W> {
|
||||
fn clone(&self) -> Self {
|
||||
Self::new(self.id.duplicate(), self.ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> WidgetId<W> {
|
||||
pub(super) fn new(id: Id, ty: TypeId) -> Self {
|
||||
Self {
|
||||
ty,
|
||||
id,
|
||||
_pd: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn erase_type(self) -> WidgetId<AnyWidget> {
|
||||
self.cast_type()
|
||||
}
|
||||
|
||||
pub fn as_any(&self) -> &WidgetId<AnyWidget> {
|
||||
// safety: self is repr(C) and generic only used for phantom data
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
fn cast_type<W2>(self) -> WidgetId<W2> {
|
||||
WidgetId {
|
||||
ty: self.ty,
|
||||
id: self.id,
|
||||
_pd: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WidgetTag;
|
||||
pub struct FnTag;
|
||||
pub struct IdTag;
|
||||
|
||||
pub trait WidgetLike<Ctx, Tag> {
|
||||
type Widget: 'static;
|
||||
@@ -85,63 +25,18 @@ pub trait WidgetLike<Ctx, Tag> {
|
||||
}
|
||||
}
|
||||
|
||||
// A function that returns a widget given a UI.
|
||||
// Useful for defining trait functions on widgets that create a parent widget so that the children
|
||||
// don't need to be IDs yet
|
||||
// pub trait WidgetFn<W: Widget<Ctx>, Ctx> = FnOnce(&mut Ui<Ctx>) -> W;
|
||||
// pub trait WidgetIdFn<W, Ctx> = FnOnce(&mut Ui<Ctx>) -> WidgetId<W>;
|
||||
|
||||
// copium for rust analyzer
|
||||
/// A function that returns a widget given a UI.
|
||||
/// Useful for defining trait functions on widgets that create a parent widget so that the children
|
||||
/// don't need to be IDs yet
|
||||
/// currently a macro for rust analyzer (doesn't support trait aliases atm)
|
||||
macro_rules! WidgetFnRet {
|
||||
($W:ty, $Ctx:ty) => {
|
||||
impl FnOnce(&mut $crate::Ui<$Ctx>) -> $W
|
||||
};
|
||||
}
|
||||
pub(crate) use WidgetFnRet;
|
||||
macro_rules! WidgetIdFnRet {
|
||||
($W:ty, $Ctx:ty) => {
|
||||
impl FnOnce(&mut $crate::Ui<$Ctx>) -> $crate::WidgetId<$W>
|
||||
};
|
||||
($W:ty, $Ctx:ty, $($use:tt)*) => {
|
||||
impl FnOnce(&mut $crate::Ui<$Ctx>) -> $crate::WidgetId<$W> + use<$($use)*>
|
||||
};
|
||||
}
|
||||
pub(crate) use WidgetIdFnRet;
|
||||
|
||||
pub trait Idable<Ctx, Tag> {
|
||||
type Widget: Widget<Ctx>;
|
||||
fn set(self, ui: &mut Ui<Ctx>, id: &WidgetId<Self::Widget>);
|
||||
fn id<'a>(
|
||||
self,
|
||||
id: &WidgetId<Self::Widget>,
|
||||
) -> WidgetIdFnRet!(Self::Widget, Ctx, 'a, Self, Ctx, Tag)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let id = id.clone();
|
||||
move |ui| {
|
||||
self.set(ui, &id);
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Widget<Ctx>, Ctx> Idable<Ctx, WidgetTag> for W {
|
||||
type Widget = W;
|
||||
|
||||
fn set(self, ui: &mut Ui<Ctx>, id: &WidgetId<Self::Widget>) {
|
||||
ui.set(id, self);
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FnOnce(&mut Ui<Ctx>) -> W, W: Widget<Ctx>, Ctx> Idable<Ctx, FnTag> for F {
|
||||
type Widget = W;
|
||||
|
||||
fn set(self, ui: &mut Ui<Ctx>, id: &WidgetId<Self::Widget>) {
|
||||
let w = self(ui);
|
||||
ui.set(id, w);
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Widget<Ctx>, Ctx, F: FnOnce(&mut Ui<Ctx>) -> W> WidgetLike<Ctx, FnTag> for F {
|
||||
type Widget = W;
|
||||
@@ -151,13 +46,6 @@ impl<W: Widget<Ctx>, Ctx, F: FnOnce(&mut Ui<Ctx>) -> W> WidgetLike<Ctx, FnTag> f
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: 'static, F: FnOnce(&mut Ui<Ctx>) -> WidgetId<W>, Ctx> WidgetLike<Ctx, IdTag> for F {
|
||||
type Widget = W;
|
||||
fn add(self, ui: &mut Ui<Ctx>) -> WidgetId<W> {
|
||||
self(ui)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Widget<Ctx>, Ctx> WidgetLike<Ctx, WidgetTag> for W {
|
||||
type Widget = W;
|
||||
fn add(self, ui: &mut Ui<Ctx>) -> WidgetId<W> {
|
||||
@@ -165,13 +53,6 @@ impl<W: Widget<Ctx>, Ctx> WidgetLike<Ctx, WidgetTag> for W {
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: 'static, Ctx> WidgetLike<Ctx, FnTag> for WidgetId<W> {
|
||||
type Widget = W;
|
||||
fn add(self, _: &mut Ui<Ctx>) -> WidgetId<W> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WidgetArr<const LEN: usize, Ws> {
|
||||
pub arr: [WidgetId; LEN],
|
||||
_pd: PhantomData<Ws>,
|
||||
|
||||
Reference in New Issue
Block a user