macro goodness
This commit is contained in:
@@ -19,6 +19,7 @@ mod orientation;
|
||||
mod painter;
|
||||
mod primitive;
|
||||
mod render;
|
||||
mod state;
|
||||
mod ui;
|
||||
mod widget;
|
||||
|
||||
|
||||
8
core/src/state.rs
Normal file
8
core/src/state.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
#[macro_export]
|
||||
macro_rules! core_state {
|
||||
($vis: vis $state: ty) => {
|
||||
$vis type WidgetHandle<W = dyn Widget<$state>> = $crate::WidgetHandle<$state, W>;
|
||||
$vis type WidgetRef<W = dyn Widget<$state>> = $crate::WidgetRef<$state, W>;
|
||||
$vis type Ui = $crate::Ui<$state>;
|
||||
};
|
||||
}
|
||||
@@ -5,7 +5,7 @@ fn main() {
|
||||
App::<State>::run();
|
||||
}
|
||||
|
||||
#[derive(HasUi, HasUiState)]
|
||||
#[derive(DefaultUiState)]
|
||||
struct State {
|
||||
ui: Ui<Self>,
|
||||
ui_state: UiState<Self>,
|
||||
|
||||
@@ -145,9 +145,16 @@ pub fn derive_global_state(input: TokenStream) -> TokenStream {
|
||||
|
||||
#[proc_macro_derive(HasUi)]
|
||||
pub fn derive_has_ui(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as ItemStruct);
|
||||
let name = input.ident;
|
||||
let Some(field) = input.fields.iter().find(|f| f.ty == parse_quote!(Ui<Self>)) else {
|
||||
has_ui(&parse_macro_input!(input))
|
||||
}
|
||||
|
||||
fn has_ui(input: &ItemStruct) -> TokenStream {
|
||||
let name = &input.ident;
|
||||
let Some(field) = input
|
||||
.fields
|
||||
.iter()
|
||||
.find(|f| f.ty == parse_quote!(Ui<Self>) || f.ty == parse_quote!(Ui))
|
||||
else {
|
||||
return Error::new(name.span(), "could not find a Ui<Self> field for HasUi")
|
||||
.into_compile_error()
|
||||
.into();
|
||||
@@ -155,11 +162,11 @@ pub fn derive_has_ui(input: TokenStream) -> TokenStream {
|
||||
let field = &field.ident;
|
||||
quote! {
|
||||
impl HasUi for #name {
|
||||
fn ui_ref(&self) -> &Ui<Self> {
|
||||
fn ui_ref(&self) -> &iris::iris_core::Ui<Self> {
|
||||
&self.#field
|
||||
}
|
||||
|
||||
fn ui(&mut self) -> &mut Ui<Self> {
|
||||
fn ui(&mut self) -> &mut iris::iris_core::Ui<Self> {
|
||||
&mut self.#field
|
||||
}
|
||||
}
|
||||
@@ -167,14 +174,15 @@ pub fn derive_has_ui(input: TokenStream) -> TokenStream {
|
||||
.into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(HasUiState)]
|
||||
pub fn derive_has_ui_state(input: TokenStream) -> TokenStream {
|
||||
#[proc_macro_derive(DefaultUiState)]
|
||||
pub fn derive_default_ui_state(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as ItemStruct);
|
||||
let mut output = has_ui(&input);
|
||||
let name = input.ident;
|
||||
let Some(field) = input
|
||||
.fields
|
||||
.iter()
|
||||
.find(|f| f.ty == parse_quote!(UiState<Self>))
|
||||
.find(|f| f.ty == parse_quote!(UiState<Self>) || f.ty == parse_quote!(UiState))
|
||||
else {
|
||||
return Error::new(
|
||||
name.span(),
|
||||
@@ -184,12 +192,15 @@ pub fn derive_has_ui_state(input: TokenStream) -> TokenStream {
|
||||
.into();
|
||||
};
|
||||
let field = &field.ident;
|
||||
output.extend::<TokenStream>(
|
||||
quote! {
|
||||
impl HasUiState for #name {
|
||||
fn ui_state(&mut self) -> &mut UiState<Self> {
|
||||
fn ui_state(&mut self) -> &mut iris::default::UiState<Self> {
|
||||
&mut self.#field
|
||||
}
|
||||
}
|
||||
}
|
||||
.into()
|
||||
.into(),
|
||||
);
|
||||
output
|
||||
}
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use cosmic_text::Family;
|
||||
use iris::prelude::*;
|
||||
use len_fns::*;
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::WindowAttributes};
|
||||
|
||||
iris::state_prelude!(Client);
|
||||
|
||||
fn main() {
|
||||
App::<Client>::run();
|
||||
}
|
||||
|
||||
#[derive(HasUi, HasUiState)]
|
||||
#[derive(DefaultUiState)]
|
||||
pub struct Client {
|
||||
ui: Ui<Self>,
|
||||
ui_state: UiState<Self>,
|
||||
info: WidgetRef<Self, Text<Self>>,
|
||||
ui: Ui,
|
||||
ui_state: UiState,
|
||||
info: WidgetRef<Text>,
|
||||
}
|
||||
|
||||
event_ctx!(Client);
|
||||
|
||||
impl DefaultAppState for Client {
|
||||
fn new(event_loop: &ActiveEventLoop, _proxy: Proxy<Self::Event>) -> Self {
|
||||
let mut ui = Ui::new();
|
||||
@@ -153,7 +150,7 @@ impl DefaultAppState for Client {
|
||||
let main = WidgetPtr::new().handles(ui);
|
||||
|
||||
let vals = Rc::new(RefCell::new((0, Vec::new())));
|
||||
let mut switch_button = |color, to: WidgetHandle<Self>, label| {
|
||||
let mut switch_button = |color, to: WidgetHandle, label| {
|
||||
let vec = &mut vals.borrow_mut().1;
|
||||
let i = vec.len();
|
||||
if vec.is_empty() {
|
||||
|
||||
@@ -52,7 +52,10 @@ pub trait HasUiState: Sized + 'static + HasUi {
|
||||
fn ui_state(&mut self) -> &mut UiState<Self>;
|
||||
fn ui_with_ui_state(&mut self) -> (&mut Ui<Self>, &mut UiState<Self>) {
|
||||
// as long as you're not doing anything actually unhinged this should always work safely
|
||||
(unsafe { std::mem::transmute(self.ui()) }, self.ui_state())
|
||||
(
|
||||
unsafe { std::mem::transmute::<&mut Ui<Self>, &mut Ui<Self>>(self.ui()) },
|
||||
self.ui_state(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
31
src/event.rs
31
src/event.rs
@@ -23,34 +23,3 @@ pub mod eventable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: naming in here is a bit weird like eventable
|
||||
#[macro_export]
|
||||
macro_rules! event_ctx {
|
||||
($ty: ty) => {
|
||||
mod local_event_trait {
|
||||
use super::*;
|
||||
#[allow(unused_imports)]
|
||||
use $crate::prelude::*;
|
||||
|
||||
pub trait EventableCtx<WL: WidgetLike<$ty, Tag>, Tag> {
|
||||
fn on<E: EventLike>(
|
||||
self,
|
||||
event: E,
|
||||
f: impl for<'a> WidgetEventFn<$ty, <E::Event as Event>::Data<'a>, WL::Widget>,
|
||||
) -> impl WidgetIdFn<$ty, WL::Widget>;
|
||||
}
|
||||
impl<WL: WidgetLike<$ty, Tag>, Tag> EventableCtx<WL, Tag> for WL {
|
||||
fn on<E: EventLike>(
|
||||
self,
|
||||
event: E,
|
||||
f: impl for<'a> WidgetEventFn<Client, <E::Event as Event>::Data<'a>, WL::Widget>,
|
||||
) -> impl WidgetIdFn<Client, WL::Widget> {
|
||||
eventable::Eventable::on(self, event, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
use local_event_trait::*;
|
||||
};
|
||||
}
|
||||
pub use event_ctx;
|
||||
|
||||
27
src/lib.rs
27
src/lib.rs
@@ -4,9 +4,29 @@
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(unsize)]
|
||||
|
||||
mod default;
|
||||
mod event;
|
||||
mod widget;
|
||||
pub mod default;
|
||||
pub mod event;
|
||||
pub mod state;
|
||||
pub mod widget;
|
||||
|
||||
pub use iris_core;
|
||||
pub use iris_macro;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! state_prelude {
|
||||
($state:ty) => {
|
||||
iris::event_state!($state);
|
||||
iris::iris_core::core_state!($state);
|
||||
iris::default_state!($state);
|
||||
iris::widget_state!($state);
|
||||
pub use iris::{
|
||||
default::*,
|
||||
iris_core::{len_fns::*, util::Vec2, *},
|
||||
iris_macro::*,
|
||||
widget::*,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
pub mod prelude {
|
||||
use super::*;
|
||||
@@ -17,4 +37,5 @@ pub mod prelude {
|
||||
pub use widget::*;
|
||||
|
||||
pub use iris_core::util::Vec2;
|
||||
pub use state::*;
|
||||
}
|
||||
|
||||
60
src/state.rs
Normal file
60
src/state.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
#[macro_export]
|
||||
macro_rules! default_state {
|
||||
($vis:vis $state:ty) => {
|
||||
$vis type UiState = $crate::default::UiState<$state>;
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! widget_state {
|
||||
($vis:vis $state:ty) => {
|
||||
$crate::widget_state!(
|
||||
$vis $state;
|
||||
Aligned,
|
||||
LayerOffset,
|
||||
MaxSize,
|
||||
Offset,
|
||||
Scroll,
|
||||
Sized,
|
||||
Span,
|
||||
Stack,
|
||||
Text,
|
||||
TextEdit,
|
||||
Masked,
|
||||
WidgetPtr,
|
||||
);
|
||||
};
|
||||
($vis:vis $state:ty; $($ty:ident,)*) => {
|
||||
$($vis type $ty = $crate::widget::$ty<$state>;)*
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! event_state {
|
||||
($state:ty) => {
|
||||
mod local_event_trait {
|
||||
use super::*;
|
||||
#[allow(unused_imports)]
|
||||
use $crate::prelude::*;
|
||||
|
||||
pub trait EventableCtx<WL: WidgetLike<$state, Tag>, Tag> {
|
||||
fn on<E: EventLike>(
|
||||
self,
|
||||
event: E,
|
||||
f: impl for<'a> WidgetEventFn<$state, <E::Event as Event>::Data<'a>, WL::Widget>,
|
||||
) -> impl WidgetIdFn<$state, WL::Widget>;
|
||||
}
|
||||
impl<WL: WidgetLike<$state, Tag>, Tag> EventableCtx<WL, Tag> for WL {
|
||||
fn on<E: EventLike>(
|
||||
self,
|
||||
event: E,
|
||||
f: impl for<'a> WidgetEventFn<Client, <E::Event as Event>::Data<'a>, WL::Widget>,
|
||||
) -> impl WidgetIdFn<Client, WL::Widget> {
|
||||
eventable::Eventable::on(self, event, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
use local_event_trait::*;
|
||||
};
|
||||
}
|
||||
pub use event_state;
|
||||
Reference in New Issue
Block a user