reactivity base
This commit is contained in:
157
src/layout/widget.rs
Normal file
157
src/layout/widget.rs
Normal file
@@ -0,0 +1,157 @@
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
use crate::{primitive::Painter, util::ID, UIBuilder};
|
||||
|
||||
pub trait Widget: 'static + Any {
|
||||
fn draw(&self, painter: &mut Painter);
|
||||
}
|
||||
|
||||
impl<W: Widget> Widget for (W,) {
|
||||
fn draw(&self, painter: &mut Painter) {
|
||||
self.0.draw(painter);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, Hash, PartialEq, Debug)]
|
||||
pub struct WidgetId<W = ()> {
|
||||
pub(super) ty: TypeId,
|
||||
pub(super) id: ID,
|
||||
_pd: PhantomData<W>,
|
||||
}
|
||||
|
||||
// TODO: temp
|
||||
impl Clone for WidgetId {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
ty: self.ty,
|
||||
id: self.id.duplicate(),
|
||||
_pd: self._pd,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> WidgetId<W> {
|
||||
pub(super) fn new(id: ID, ty: TypeId) -> Self {
|
||||
Self {
|
||||
ty,
|
||||
id,
|
||||
_pd: PhantomData,
|
||||
}
|
||||
}
|
||||
pub fn erase_type(self) -> WidgetId<()> {
|
||||
self.cast_type()
|
||||
}
|
||||
|
||||
fn cast_type<W2>(self) -> WidgetId<W2> {
|
||||
WidgetId {
|
||||
ty: self.ty,
|
||||
id: self.id,
|
||||
_pd: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait WidgetLike<W> {
|
||||
fn id(self, ui: &mut UIBuilder) -> WidgetId<W>;
|
||||
}
|
||||
|
||||
/// wouldn't be needed if negative trait bounds & disjoint impls existed
|
||||
pub struct WidgetFn<F: FnOnce(&mut UIBuilder) -> W, W>(pub F);
|
||||
|
||||
impl<W: Widget, F: FnOnce(&mut UIBuilder) -> W> WidgetLike<W> for WidgetFn<F, W> {
|
||||
fn id(self, ui: &mut UIBuilder) -> WidgetId<W> {
|
||||
let w = (self.0)(ui);
|
||||
ui.add(w).to_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Widget> WidgetLike<W> for W {
|
||||
fn id(self, ui: &mut UIBuilder) -> WidgetId<W> {
|
||||
ui.add(self).to_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> WidgetLike<W> for WidgetId<W> {
|
||||
fn id(self, _: &mut UIBuilder) -> WidgetId<W> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> WidgetLike<W> for WidgetArr<1, (W,)> {
|
||||
fn id(self, _: &mut UIBuilder) -> WidgetId<W> {
|
||||
let [id] = self.arr;
|
||||
id.cast_type()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WidgetArr<const LEN: usize, Ws> {
|
||||
pub ui: UIBuilder,
|
||||
pub arr: [WidgetId<()>; LEN],
|
||||
_pd: PhantomData<Ws>,
|
||||
}
|
||||
|
||||
impl<const LEN: usize, Ws> WidgetArr<LEN, Ws> {
|
||||
pub fn new(ui: UIBuilder, arr: [WidgetId<()>; LEN]) -> Self {
|
||||
Self {
|
||||
ui,
|
||||
arr,
|
||||
_pd: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type WidgetRef<W> = WidgetArr<1, (W,)>;
|
||||
|
||||
impl<W> WidgetRef<W> {
|
||||
pub fn handle(&self) -> WidgetId<W> {
|
||||
let [id] = &self.arr;
|
||||
id.clone().cast_type()
|
||||
}
|
||||
pub fn to_id(self) -> WidgetId<W> {
|
||||
let [id] = self.arr;
|
||||
id.cast_type()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait WidgetArrLike<const LEN: usize, Ws> {
|
||||
fn ui(self, ui: &mut UIBuilder) -> WidgetArr<LEN, Ws>;
|
||||
}
|
||||
|
||||
impl<const LEN: usize, Ws> WidgetArrLike<LEN, Ws> for WidgetArr<LEN, Ws> {
|
||||
fn ui(self, _: &mut UIBuilder) -> WidgetArr<LEN, Ws> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// I hate this language it's so bad why do I even use it
|
||||
macro_rules! impl_node_arr {
|
||||
($n:expr;$($T:tt)*) => {
|
||||
impl<$($T,${concat($T,$T)}: WidgetLike<$T>,)*> WidgetArrLike<$n, ($($T,)*)> for ($(${concat($T,$T)},)*) {
|
||||
#[allow(unused_variables)]
|
||||
fn ui(self, ui: &mut UIBuilder) -> WidgetArr<$n, ($($T,)*)> {
|
||||
#[allow(non_snake_case)]
|
||||
let ($($T,)*) = self;
|
||||
WidgetArr::new(
|
||||
ui.clone(),
|
||||
[$($T.id(ui).cast_type(),)*],
|
||||
)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_node_arr!(1;A);
|
||||
impl_node_arr!(2;A B);
|
||||
impl_node_arr!(3;A B C);
|
||||
impl_node_arr!(4;A B C D);
|
||||
impl_node_arr!(5;A B C D E);
|
||||
impl_node_arr!(6;A B C D E F);
|
||||
impl_node_arr!(7;A B C D E F G);
|
||||
impl_node_arr!(8;A B C D E F G H);
|
||||
impl_node_arr!(9;A B C D E F G H I);
|
||||
impl_node_arr!(10;A B C D E F G H I J);
|
||||
impl_node_arr!(11;A B C D E F G H I J K);
|
||||
impl_node_arr!(12;A B C D E F G H I J K L);
|
||||
Reference in New Issue
Block a user