diff --git a/core/src/event/ctx.rs b/core/src/event/ctx.rs index cf0005e..a16cfd9 100644 --- a/core/src/event/ctx.rs +++ b/core/src/event/ctx.rs @@ -2,13 +2,13 @@ use crate::{HasEvents, HasUi, Widget, WidgetRef}; pub struct EventCtx<'a, Rsc: HasEvents, Data> { pub state: &'a mut Rsc::State, - pub data: &'a mut Data, + pub data: Data, } pub struct EventIdCtx<'a, Rsc: HasEvents, Data, W: ?Sized> { pub widget: WidgetRef, pub state: &'a mut Rsc::State, - pub data: &'a mut Data, + pub data: Data, } impl EventIdCtx<'_, Rsc, Data, W> { diff --git a/core/src/event/manager.rs b/core/src/event/manager.rs index 1b08bc6..5876eeb 100644 --- a/core/src/event/manager.rs +++ b/core/src/event/manager.rs @@ -28,7 +28,7 @@ impl EventManager { &mut self, id: WidgetRef, event: E, - f: impl for<'a> WidgetEventFn::Data<'a>, W>, + f: impl WidgetEventFn::Data, W>, ) { self.get_type::().register(id, event, f); self.widget_to_types @@ -74,7 +74,7 @@ pub trait EventManagerLike { fn undraw(&mut self, data: &ActiveData); } -type EventData = (E, Rc EventFn::Data<'a>>>); +type EventData = (E, Rc::Data>>); pub struct TypeEventManager { // TODO: reduce visiblity!! pub active: HashMap>, @@ -116,18 +116,20 @@ impl TypeEventManager { &mut self, widget: WidgetRef, event: impl EventLike, - f: impl for<'a> WidgetEventFn, W>, + f: impl WidgetEventFn, ) { let event = event.into_event(); self.map.entry(widget.id()).or_default().push(( event, Rc::new(move |ctx, rsc| { - let mut test = EventIdCtx { - widget, - state: ctx.state, - data: ctx.data, - }; - f(&mut test, rsc); + f( + EventIdCtx { + widget, + state: ctx.state, + data: ctx.data, + }, + rsc, + ); }), )); } @@ -135,15 +137,15 @@ impl TypeEventManager { pub fn run_fn<'a>( &mut self, id: impl IdLike, - ) -> impl for<'b> FnOnce(EventCtx<'_, Rsc, E::Data<'b>>, &mut Rsc) + 'a { + ) -> impl FnOnce(EventCtx<'_, Rsc, E::Data>, &mut Rsc) + 'a { let fs = self.map.get(&id.id()).cloned().unwrap_or_default(); move |ctx, rsc| { for (e, f) in fs { - if e.should_run(ctx.data) { + if let Some(data) = e.should_run(&ctx.data) { f( - &mut EventCtx { + EventCtx { state: ctx.state, - data: ctx.data, + data, }, rsc, ) diff --git a/core/src/event/mod.rs b/core/src/event/mod.rs index 1481eb2..4010969 100644 --- a/core/src/event/mod.rs +++ b/core/src/event/mod.rs @@ -7,11 +7,11 @@ pub use manager::*; pub use rsc::*; pub trait Event: Sized + 'static + Clone { - type Data<'a> = (); + type Data: Clone = (); type State: Default = (); #[allow(unused_variables)] - fn should_run(&self, data: &mut Self::Data<'_>) -> bool { - true + fn should_run(&self, data: &Self::Data) -> Option { + Some(data.clone()) } } @@ -28,17 +28,17 @@ impl EventLike for E { } } -pub trait EventFn: Fn(&mut EventCtx, &mut Rsc) + 'static {} -impl, &mut Rsc) + 'static, Data> EventFn +pub trait EventFn: Fn(EventCtx, &mut Rsc) + 'static {} +impl, &mut Rsc) + 'static, Data> EventFn for F { } pub trait WidgetEventFn: - Fn(&mut EventIdCtx, &mut Rsc) + 'static + Fn(EventIdCtx, &mut Rsc) + 'static { } -impl, &mut Rsc) + 'static, Data, W: ?Sized> +impl, &mut Rsc) + 'static, Data, W: ?Sized> WidgetEventFn for F { } diff --git a/core/src/event/rsc.rs b/core/src/event/rsc.rs index 706cb8f..0ef2ba8 100644 --- a/core/src/event/rsc.rs +++ b/core/src/event/rsc.rs @@ -14,7 +14,7 @@ pub trait HasEvents: Sized + HasUi + HasState { &mut self, id: WidgetRef, event: E, - f: impl for<'a> WidgetEventFn::Data<'a>, W>, + f: impl WidgetEventFn::Data, W>, ) { self.events_mut().register(id, event, f); } @@ -24,7 +24,7 @@ pub trait RunEvents: HasEvents { fn run_event( &mut self, id: impl IdLike, - data: &mut ::Data<'_>, + data: ::Data, state: &mut Self::State, ) { let f = self.events_mut().get_type::().run_fn(id); diff --git a/core/src/widget/handle.rs b/core/src/widget/handle.rs index 9ea1302..3de2b73 100644 --- a/core/src/widget/handle.rs +++ b/core/src/widget/handle.rs @@ -171,3 +171,4 @@ fn null_ptr() -> *const W { } unsafe impl Send for WidgetRef {} +unsafe impl Sync for WidgetRef {} diff --git a/examples/tabs/main.rs b/examples/tabs/main.rs index 6ee99fc..6bb1e37 100644 --- a/examples/tabs/main.rs +++ b/examples/tabs/main.rs @@ -2,7 +2,8 @@ use cosmic_text::Family; use std::{cell::RefCell, rc::Rc}; use winit::event::WindowEvent; -iris::state_prelude!(DefaultRsc); +use iris::prelude::*; +type ClientRsc = DefaultRsc; fn main() { DefaultApp::::run(); @@ -119,6 +120,7 @@ impl DefaultAppState for Client { texts(rsc).push(msg_box); }) .add(rsc); + let text_edit_scroll = ( msg_area.height(rest(1)), ( @@ -126,8 +128,8 @@ impl DefaultAppState for Client { ( add_text.width(rest(1)), Rect::new(Color::GREEN) - .on(CursorSense::click(), move |ctx, rsc| { - rsc.run_event::(add_text, &mut (), ctx.state); + .on(CursorSense::click(), move |ctx, rsc: &mut ClientRsc| { + rsc.run_event::(add_text, (), ctx.state); }) .sized((40, 40)), ) diff --git a/examples/task.rs b/examples/task.rs index 7860e50..4503ead 100644 --- a/examples/task.rs +++ b/examples/task.rs @@ -1,7 +1,6 @@ +use iris::prelude::*; use std::time::Duration; -iris::state_prelude!(DefaultRsc); - fn main() { DefaultApp::::run(); } @@ -14,17 +13,15 @@ struct State { impl DefaultAppState for State { fn new(ui_state: DefaultUiState, rsc: &mut DefaultRsc, _: Proxy) -> Self { let rect = rect(Color::RED).add(rsc); - rect.on(CursorSense::click(), move |_, rsc| { - rsc.tasks.spawn(async move |ctx| { - tokio::time::sleep(Duration::from_secs(1)).await; - ctx.update(move |_, rsc| { - let rect = rect(rsc); - if rect.color == Color::RED { - rect.color = Color::GREEN; - } else { - rect.color = Color::RED; - } - }); + rect.task_on(CursorSense::click(), async move |mut ctx| { + tokio::time::sleep(Duration::from_secs(1)).await; + ctx.task.update(move |_, rsc| { + let rect = rect(rsc); + if rect.color == Color::RED { + rect.color = Color::GREEN; + } else { + rect.color = Color::RED; + } }); }) .set_root(rsc); diff --git a/src/default/mod.rs b/src/default/mod.rs index 1e9819a..9c56660 100644 --- a/src/default/mod.rs +++ b/src/default/mod.rs @@ -127,6 +127,12 @@ impl HasEvents for DefaultRsc { } } +impl HasTasks for DefaultRsc { + fn tasks_mut(&mut self) -> &mut Tasks { + &mut self.tasks + } +} + pub struct DefaultApp { rsc: DefaultRsc, state: State, @@ -169,7 +175,7 @@ impl AppState for DefaultApp { if input_changed { let window_size = ui_state.window_size(); self.rsc - .run_sensors(&mut self.state, &cursor_state, window_size); + .run_sensors(&mut self.state, cursor_state, window_size); } let ui = &mut self.rsc.ui; let ui_state = self.state.default_state_mut(); @@ -200,13 +206,13 @@ impl AppState for DefaultApp { ui_state.window.set_ime_allowed(false); } TextInputResult::Submit => { - self.rsc.run_event::(sel, &mut (), &mut self.state); + self.rsc.run_event::(sel, (), &mut self.state); } TextInputResult::Paste => { if let Ok(t) = ui_state.clipboard.get_text() { text.insert(&t); } - self.rsc.run_event::(sel, &mut (), &mut self.state); + self.rsc.run_event::(sel, (), &mut self.state); } TextInputResult::Copy(text) => { if let Err(err) = ui_state.clipboard.set_text(text) { @@ -214,7 +220,7 @@ impl AppState for DefaultApp { } } TextInputResult::Used => { - self.rsc.run_event::(sel, &mut (), &mut self.state); + self.rsc.run_event::(sel, (), &mut self.state); } TextInputResult::Unused => {} } diff --git a/src/default/sense.rs b/src/default/sense.rs index 871cf48..db88abd 100644 --- a/src/default/sense.rs +++ b/src/default/sense.rs @@ -26,14 +26,15 @@ pub enum CursorSense { pub struct CursorSenses(Vec); impl Event for CursorSenses { - type Data<'a> = CursorData<'a>; + type Data = CursorData; type State = SensorState; - fn should_run(&self, data: &mut Self::Data<'_>) -> bool { - if let Some(sense) = should_run(self, data.cursor, data.hover) { + fn should_run(&self, data: &Self::Data) -> Option { + if let Some(sense) = should_run(self, &data.cursor, data.hover) { + let mut data = data.clone(); data.sense = sense; - true + Some(data) } else { - false + None } } } @@ -127,23 +128,24 @@ pub struct SensorState { pub hover: ActivationState, } -pub struct CursorData<'a> { +#[derive(Clone)] +pub struct CursorData { /// where this widget was hit pub pos: Vec2, pub size: Vec2, pub scroll_delta: Vec2, pub hover: ActivationState, - pub cursor: &'a CursorState, + pub cursor: CursorState, /// the first sense that triggered this pub sense: CursorSense, } pub trait SensorUi { - fn run_sensors(&mut self, state: &mut Rsc::State, cursor: &CursorState, window_size: Vec2); + fn run_sensors(&mut self, state: &mut Rsc::State, cursor: CursorState, window_size: Vec2); } impl SensorUi for Rsc { - fn run_sensors(&mut self, state: &mut Rsc::State, cursor: &CursorState, window_size: Vec2) { + fn run_sensors(&mut self, state: &mut Rsc::State, cursor: CursorState, window_size: Vec2) { let layers = std::mem::take(&mut self.ui_mut().layers); let mut active = std::mem::take(&mut self.events_mut().get_type::().active); for layer in layers.indices().rev() { @@ -158,7 +160,9 @@ impl SensorUi for Rsc { } sensed = true; - let mut data = CursorData { + let cursor = cursor.clone(); + + let data = CursorData { pos: cursor.pos - region.top_left, size: region.bot_right - region.top_left, scroll_delta: cursor.scroll_delta, @@ -168,7 +172,7 @@ impl SensorUi for Rsc { // might wanna set up Event to have a prepare stage sense: CursorSense::Hovering, }; - self.run_event::(*id, &mut data, state); + self.run_event::(*id, data, state); } if sensed { break; diff --git a/src/default/task.rs b/src/default/task.rs index 51f6a66..36b55c1 100644 --- a/src/default/task.rs +++ b/src/default/task.rs @@ -62,17 +62,14 @@ impl Tasks { ) } - pub fn spawn AsyncFnOnce(&'a mut TaskCtx) + 'static + std::marker::Send>( - &mut self, - task: F, - ) where - for<'a> ,)>>::CallOnceFuture: Send, + pub fn spawn) + 'static + std::marker::Send>(&mut self, task: F) + where + F::CallOnceFuture: Send, { let send = self.msg_send.clone(); let window = self.window.clone(); let _ = self.start.send(Box::pin(async move { - let mut ctx = TaskCtx::new(send); - task(&mut ctx).await; + task(TaskCtx::new(send)).await; window.request_redraw(); })); } diff --git a/src/event.rs b/src/event.rs index f8960ea..5cd0691 100644 --- a/src/event.rs +++ b/src/event.rs @@ -1,54 +1,60 @@ use iris_core::*; use iris_macro::*; +use std::sync::Arc; use crate::default::{TaskCtx, Tasks}; -pub mod eventable { - use super::*; - widget_trait! { - pub trait Eventable; - fn on( - self, - event: E, - f: impl for<'a> WidgetEventFn::Data<'a>, WL::Widget>, - ) -> impl WidgetIdFn { - move |rsc| { - let id = self.add(rsc); - rsc.register_event(id, event.into_event(), move |ctx, rsc| { - f(&mut EventIdCtx { +pub trait Eventable: WidgetLike { + fn on( + self, + event: E, + f: impl WidgetEventFn::Data, Self::Widget>, + ) -> impl WidgetIdFn { + move |rsc| { + let id = self.add(rsc); + rsc.register_event(id, event.into_event(), move |ctx, rsc| { + f( + EventIdCtx { widget: id, state: ctx.state, data: ctx.data, - }, rsc); - }); - id - } + }, + rsc, + ); + }); + id } } +} +impl, Rsc: HasEvents, Tag> Eventable for WL {} - // widget_trait! { - // pub trait TaskEventable; - // fn task_on( - // self, - // event: E, - // f: impl for<'a> AsyncWidgetEventFn::Data<'a>, WL::Widget>, - // ) -> impl WidgetIdFn { - // move |rsc| { - // let id = self.add(rsc); - // rsc.register_event(id, event.into_event(), move |ctx, rsc| { - // rsc.tasks_mut().spawn(async move |task| { - // f(&mut AsyncEventIdCtx { - // widget: id, - // state: ctx.state, - // data: ctx.data, - // task, - // }, rsc).await; - // }); - // }); - // id - // } - // } - // } +widget_trait! { + pub trait TaskEventable; + fn task_on::Data, WL::Widget>>( + self, + event: E, + f: F, + ) -> impl WidgetIdFn + where ::Data: Send, + for<'a> F::CallRefFuture<'a>: Send, + { + let f = Arc::new(f); + move |rsc| { + let id = self.add(rsc); + rsc.register_event(id, event.into_event(), move |ctx, rsc| { + let data = ctx.data; + let f = f.clone(); + rsc.tasks_mut().spawn(async move |task| { + f(AsyncEventIdCtx { + widget: id, + data, + task, + }).await; + }); + }); + id + } + } } pub trait HasTasks: Sized + HasState + HasEvents { @@ -56,21 +62,20 @@ pub trait HasTasks: Sized + HasState + HasEvents { } pub trait AsyncWidgetEventFn: - AsyncFn(&mut AsyncEventIdCtx, &mut Rsc) + 'static + AsyncFn(AsyncEventIdCtx) + Send + Sync + 'static { } impl< Rsc: HasEvents, - F: AsyncFn(&mut AsyncEventIdCtx, &mut Rsc) + 'static, + F: AsyncFn(AsyncEventIdCtx) + Send + Sync + 'static, Data, W: ?Sized, > AsyncWidgetEventFn for F { } -pub struct AsyncEventIdCtx<'a, Rsc: HasEvents, Data, W: ?Sized> { +pub struct AsyncEventIdCtx { pub widget: WidgetRef, - pub state: &'a mut Rsc::State, - pub data: &'a mut Data, - pub task: &'a mut TaskCtx, + pub data: Data, + pub task: TaskCtx, } diff --git a/src/lib.rs b/src/lib.rs index 81f1a3e..fa54bba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,25 +8,11 @@ pub mod default; pub mod event; -pub mod typed; pub mod widget; pub use iris_core as core; pub use iris_macro as macros; -#[macro_export] -macro_rules! state_prelude { - ($vis:vis $state:ty) => { - iris::event_state!($vis $state); - $vis use iris::{ - default::*, - core::{len_fns::*, util::Vec2, *}, - macros::*, - widget::*, - }; - }; -} - pub mod prelude { use super::*; pub use default::*; @@ -36,5 +22,5 @@ pub mod prelude { pub use widget::*; pub use iris_core::util::Vec2; - pub use typed::*; + pub use len_fns::*; } diff --git a/src/typed.rs b/src/typed.rs deleted file mode 100644 index d22d8fb..0000000 --- a/src/typed.rs +++ /dev/null @@ -1,37 +0,0 @@ -#[macro_export] -macro_rules! event_state { - ($vis:vis $rsc:ty) => { - mod local_event_trait { - use super::*; - #[allow(unused_imports)] - use $crate::prelude::*; - pub trait EventableCtx, Tag> { - fn on( - self, - event: E, - f: impl for<'a> WidgetEventFn< - $rsc, - ::Data<'a>, - WL::Widget - >, - ) -> impl WidgetIdFn<$rsc, WL::Widget>; - } - impl, Tag> EventableCtx for WL { - fn on( - self, - event: E, - f: impl for<'a> WidgetEventFn< - $rsc, - ::Data<'a>, - WL::Widget - >, - ) -> impl WidgetIdFn<$rsc, WL::Widget> { - eventable::Eventable::on(self, event, f) - } - } - } - $vis type EventManager = $crate::prelude::EventManager<<$rsc as HasState>::State>; - $vis use local_event_trait::*; - }; -} -pub use event_state; diff --git a/src/widget/trait_fns.rs b/src/widget/trait_fns.rs index 594cc98..b526d40 100644 --- a/src/widget/trait_fns.rs +++ b/src/widget/trait_fns.rs @@ -84,7 +84,6 @@ widget_trait! { } fn scrollable(self) -> impl WidgetIdFn where Rsc: HasEvents { - use eventable::Eventable; move |state| { Scroll::new(self.add_strong(state), Axis::Y) .on(CursorSense::Scroll, |ctx, rsc| { @@ -132,9 +131,9 @@ widget_trait! { } } -pub trait CoreWidgetArr, Tag> { - fn span(self, dir: Dir) -> SpanBuilder; - fn stack(self) -> StackBuilder; +pub trait CoreWidgetArr, Tag> { + fn span(self, dir: Dir) -> SpanBuilder; + fn stack(self) -> StackBuilder; } impl, Tag>