macro goodness
This commit is contained in:
@@ -19,6 +19,7 @@ mod orientation;
|
|||||||
mod painter;
|
mod painter;
|
||||||
mod primitive;
|
mod primitive;
|
||||||
mod render;
|
mod render;
|
||||||
|
mod state;
|
||||||
mod ui;
|
mod ui;
|
||||||
mod widget;
|
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();
|
App::<State>::run();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(HasUi, HasUiState)]
|
#[derive(DefaultUiState)]
|
||||||
struct State {
|
struct State {
|
||||||
ui: Ui<Self>,
|
ui: Ui<Self>,
|
||||||
ui_state: UiState<Self>,
|
ui_state: UiState<Self>,
|
||||||
|
|||||||
@@ -145,9 +145,16 @@ pub fn derive_global_state(input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
#[proc_macro_derive(HasUi)]
|
#[proc_macro_derive(HasUi)]
|
||||||
pub fn derive_has_ui(input: TokenStream) -> TokenStream {
|
pub fn derive_has_ui(input: TokenStream) -> TokenStream {
|
||||||
let input = parse_macro_input!(input as ItemStruct);
|
has_ui(&parse_macro_input!(input))
|
||||||
let name = input.ident;
|
}
|
||||||
let Some(field) = input.fields.iter().find(|f| f.ty == parse_quote!(Ui<Self>)) else {
|
|
||||||
|
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")
|
return Error::new(name.span(), "could not find a Ui<Self> field for HasUi")
|
||||||
.into_compile_error()
|
.into_compile_error()
|
||||||
.into();
|
.into();
|
||||||
@@ -155,11 +162,11 @@ pub fn derive_has_ui(input: TokenStream) -> TokenStream {
|
|||||||
let field = &field.ident;
|
let field = &field.ident;
|
||||||
quote! {
|
quote! {
|
||||||
impl HasUi for #name {
|
impl HasUi for #name {
|
||||||
fn ui_ref(&self) -> &Ui<Self> {
|
fn ui_ref(&self) -> &iris::iris_core::Ui<Self> {
|
||||||
&self.#field
|
&self.#field
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui(&mut self) -> &mut Ui<Self> {
|
fn ui(&mut self) -> &mut iris::iris_core::Ui<Self> {
|
||||||
&mut self.#field
|
&mut self.#field
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,14 +174,15 @@ pub fn derive_has_ui(input: TokenStream) -> TokenStream {
|
|||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(HasUiState)]
|
#[proc_macro_derive(DefaultUiState)]
|
||||||
pub fn derive_has_ui_state(input: TokenStream) -> TokenStream {
|
pub fn derive_default_ui_state(input: TokenStream) -> TokenStream {
|
||||||
let input = parse_macro_input!(input as ItemStruct);
|
let input = parse_macro_input!(input as ItemStruct);
|
||||||
|
let mut output = has_ui(&input);
|
||||||
let name = input.ident;
|
let name = input.ident;
|
||||||
let Some(field) = input
|
let Some(field) = input
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
.find(|f| f.ty == parse_quote!(UiState<Self>))
|
.find(|f| f.ty == parse_quote!(UiState<Self>) || f.ty == parse_quote!(UiState))
|
||||||
else {
|
else {
|
||||||
return Error::new(
|
return Error::new(
|
||||||
name.span(),
|
name.span(),
|
||||||
@@ -184,12 +192,15 @@ pub fn derive_has_ui_state(input: TokenStream) -> TokenStream {
|
|||||||
.into();
|
.into();
|
||||||
};
|
};
|
||||||
let field = &field.ident;
|
let field = &field.ident;
|
||||||
quote! {
|
output.extend::<TokenStream>(
|
||||||
impl HasUiState for #name {
|
quote! {
|
||||||
fn ui_state(&mut self) -> &mut UiState<Self> {
|
impl HasUiState for #name {
|
||||||
&mut self.#field
|
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 cosmic_text::Family;
|
||||||
use iris::prelude::*;
|
use std::{cell::RefCell, rc::Rc};
|
||||||
use len_fns::*;
|
|
||||||
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::WindowAttributes};
|
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::WindowAttributes};
|
||||||
|
|
||||||
|
iris::state_prelude!(Client);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::<Client>::run();
|
App::<Client>::run();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(HasUi, HasUiState)]
|
#[derive(DefaultUiState)]
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
ui: Ui<Self>,
|
ui: Ui,
|
||||||
ui_state: UiState<Self>,
|
ui_state: UiState,
|
||||||
info: WidgetRef<Self, Text<Self>>,
|
info: WidgetRef<Text>,
|
||||||
}
|
}
|
||||||
|
|
||||||
event_ctx!(Client);
|
|
||||||
|
|
||||||
impl DefaultAppState for Client {
|
impl DefaultAppState for Client {
|
||||||
fn new(event_loop: &ActiveEventLoop, _proxy: Proxy<Self::Event>) -> Self {
|
fn new(event_loop: &ActiveEventLoop, _proxy: Proxy<Self::Event>) -> Self {
|
||||||
let mut ui = Ui::new();
|
let mut ui = Ui::new();
|
||||||
@@ -153,7 +150,7 @@ impl DefaultAppState for Client {
|
|||||||
let main = WidgetPtr::new().handles(ui);
|
let main = WidgetPtr::new().handles(ui);
|
||||||
|
|
||||||
let vals = Rc::new(RefCell::new((0, Vec::new())));
|
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 vec = &mut vals.borrow_mut().1;
|
||||||
let i = vec.len();
|
let i = vec.len();
|
||||||
if vec.is_empty() {
|
if vec.is_empty() {
|
||||||
|
|||||||
@@ -52,7 +52,10 @@ pub trait HasUiState: Sized + 'static + HasUi {
|
|||||||
fn ui_state(&mut self) -> &mut UiState<Self>;
|
fn ui_state(&mut self) -> &mut UiState<Self>;
|
||||||
fn ui_with_ui_state(&mut self) -> (&mut Ui<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
|
// 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(associated_type_defaults)]
|
||||||
#![feature(unsize)]
|
#![feature(unsize)]
|
||||||
|
|
||||||
mod default;
|
pub mod default;
|
||||||
mod event;
|
pub mod event;
|
||||||
mod widget;
|
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 {
|
pub mod prelude {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -17,4 +37,5 @@ pub mod prelude {
|
|||||||
pub use widget::*;
|
pub use widget::*;
|
||||||
|
|
||||||
pub use iris_core::util::Vec2;
|
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