Skip to content

Commit 310a6da

Browse files
committed
new event system in place
1 parent 9e61607 commit 310a6da

File tree

28 files changed

+297
-169
lines changed

28 files changed

+297
-169
lines changed

anathema-backend/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::time::Duration;
33

44
use anathema_geometry::{Pos, Size};
55
use anathema_value_resolver::{AttributeStorage, Scope};
6-
use anathema_widgets::components::events::Event;
6+
use anathema_widgets::components::events::ComponentEvent;
77
use anathema_widgets::error::Result;
88
use anathema_widgets::layout::{Constraints, LayoutCtx, LayoutFilter, PositionFilter, Viewport};
99
use anathema_widgets::paint::PaintFilter;
@@ -14,7 +14,7 @@ pub mod tui;
1414
pub trait Backend {
1515
fn size(&self) -> Size;
1616

17-
fn next_event(&mut self, timeout: Duration) -> Option<Event>;
17+
fn next_event(&mut self, timeout: Duration) -> Option<ComponentEvent>;
1818

1919
fn resize(&mut self, new_size: Size, glyph_map: &mut GlyphMap);
2020

anathema-backend/src/tui/events.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use std::time::Duration;
22

3-
use anathema_widgets::components::events::{Event, KeyCode, KeyEvent, KeyState, MouseButton, MouseEvent, MouseState};
3+
use anathema_widgets::components::events::{
4+
ComponentEvent, KeyCode, KeyEvent, KeyState, MouseButton, MouseEvent, MouseState,
5+
};
46
use crossterm::event::{Event as CTEvent, KeyEventKind, read};
57
pub use crossterm::event::{
68
KeyCode as CTKeyCode, KeyEvent as CTKeyEvent, KeyEventState, KeyModifiers, MouseButton as CTMouseButton,
@@ -14,18 +16,18 @@ impl Events {
1416
/// Poll events given a duration.
1517
/// If no event is available within the duration
1618
/// the function will return `None`.
17-
pub fn poll(&self, timeout: Duration) -> Option<Event> {
19+
pub fn poll(&self, timeout: Duration) -> Option<ComponentEvent> {
1820
match crossterm::event::poll(timeout).ok()? {
1921
true => {
2022
let event = read().map(Into::into).ok()?;
2123

2224
let event = match event {
23-
CTEvent::Paste(_) => Event::Noop,
24-
CTEvent::FocusGained => Event::Focus,
25-
CTEvent::FocusLost => Event::Blur,
26-
CTEvent::Key(key_ev) => Event::Key(key_code_to_key_code(key_ev)),
27-
CTEvent::Mouse(mouse_ev) => Event::Mouse(mouse_to_mouse(mouse_ev)),
28-
CTEvent::Resize(width, height) => Event::Resize((width, height).into()),
25+
CTEvent::Paste(_) => ComponentEvent::Noop,
26+
CTEvent::FocusGained => ComponentEvent::Focus,
27+
CTEvent::FocusLost => ComponentEvent::Blur,
28+
CTEvent::Key(key_ev) => ComponentEvent::Key(key_code_to_key_code(key_ev)),
29+
CTEvent::Mouse(mouse_ev) => ComponentEvent::Mouse(mouse_to_mouse(mouse_ev)),
30+
CTEvent::Resize(width, height) => ComponentEvent::Resize((width, height).into()),
2931
};
3032

3133
Some(event)

anathema-backend/src/tui/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::time::Duration;
1010

1111
use anathema_geometry::{LocalPos, Pos, Size};
1212
use anathema_value_resolver::AttributeStorage;
13-
use anathema_widgets::components::events::Event;
13+
use anathema_widgets::components::events::ComponentEvent;
1414
pub use anathema_widgets::{Attributes, Style};
1515
use anathema_widgets::{GlyphMap, PaintChildren, WidgetRenderer};
1616
use crossterm::cursor::{RestorePosition, SavePosition};
@@ -153,7 +153,7 @@ impl Backend for TuiBackend {
153153
self.screen.size()
154154
}
155155

156-
fn next_event(&mut self, timeout: Duration) -> Option<Event> {
156+
fn next_event(&mut self, timeout: Duration) -> Option<ComponentEvent> {
157157
self.events.poll(timeout)
158158
}
159159

anathema-default-widgets/src/testing.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use anathema_templates::blueprints::Blueprint;
66
use anathema_templates::{Document, Globals, ToSourceKind};
77
use anathema_value_resolver::{AttributeStorage, Attributes, Scope};
88
use anathema_widgets::components::ComponentRegistry;
9-
use anathema_widgets::components::events::Event;
9+
use anathema_widgets::components::events::ComponentEvent;
1010
use anathema_widgets::layout::{Constraints, LayoutCtx, Viewport};
1111
use anathema_widgets::paint::{Glyph, paint};
1212
use anathema_widgets::query::{Children, Elements};
@@ -37,7 +37,7 @@ impl Backend for TestBackend {
3737
self.surface.size
3838
}
3939

40-
fn next_event(&mut self, _timeout: std::time::Duration) -> Option<Event> {
40+
fn next_event(&mut self, _timeout: std::time::Duration) -> Option<ComponentEvent> {
4141
None
4242
}
4343

anathema-runtime/src/builder.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use anathema_default_widgets::register_default_widgets;
44
use anathema_geometry::Size;
55
use anathema_templates::{Document, ToSourceKind};
66
use anathema_widgets::components::deferred::DeferredComponents;
7-
use anathema_widgets::components::events::Event;
7+
use anathema_widgets::components::events::ComponentEvent;
88
use anathema_widgets::components::{Component, ComponentId, ComponentRegistry, Emitter, ViewMessage};
99
use anathema_widgets::tabindex::TabIndex;
1010
use anathema_widgets::{Factory, Widget};
@@ -86,7 +86,6 @@ impl<G: GlobalEventHandler> Builder<G> {
8686
component: C,
8787
state: C::State,
8888
) -> Result<ComponentId<C::Message>> {
89-
let ident = ident.into();
9089
let id = self.document.add_component(ident, template.to_source_kind())?.into();
9190
self.component_registry.add_component(id, component, state);
9291
Ok(id.into())
@@ -106,7 +105,6 @@ impl<G: GlobalEventHandler> Builder<G> {
106105
{
107106
let component = C::default();
108107
let state = C::State::default();
109-
let ident = ident.into();
110108
let id = self.document.add_component(ident, template.to_source_kind())?.into();
111109
self.component_registry.add_component(id, component, state);
112110
Ok(id.into())
@@ -126,15 +124,14 @@ impl<G: GlobalEventHandler> Builder<G> {
126124
FS: 'static + FnMut() -> C::State,
127125
C: Component + 'static,
128126
{
129-
let ident = ident.into();
130127
let id = self.document.add_component(ident, template.to_source_kind())?.into();
131128
self.component_registry.add_prototype(id, proto, state);
132129
Ok(())
133130
}
134131

135132
pub fn with_global_event_handler<Eh>(self, global_event_handler: Eh) -> Builder<Eh>
136133
where
137-
Eh: Fn(Event, &mut TabIndex<'_, '_>, &mut DeferredComponents) -> Option<Event>,
134+
Eh: Fn(ComponentEvent, &mut TabIndex<'_, '_>, &mut DeferredComponents) -> Option<ComponentEvent>,
138135
{
139136
Builder {
140137
factory: self.factory,
@@ -185,7 +182,7 @@ impl<G: GlobalEventHandler> Builder<G> {
185182
Ok(_) => continue,
186183
Err(Error::Stop) => break Ok(()),
187184
Err(Error::Template(_error)) => todo!(),
188-
Err(Error::Widget(_error)) => {}
185+
Err(Error::Widget(err)) => panic!("this should not panic in the future: {err}"),
189186
Err(e) => break Err(e),
190187
},
191188
}

anathema-runtime/src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub enum Error {
1111
Notify(notify::Error),
1212
Widget(anathema_widgets::error::Error),
1313
Stop,
14+
InvalidComponentName,
1415
}
1516

1617
impl Display for Error {
@@ -20,6 +21,7 @@ impl Display for Error {
2021
Error::Stop => write!(f, "stopping"),
2122
Error::Notify(err) => write!(f, "{err}"),
2223
Error::Widget(err) => write!(f, "{err}"),
24+
Error::InvalidComponentName => write!(f, "no such component"),
2325
}
2426
}
2527
}

anathema-runtime/src/events.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
use anathema_widgets::components::deferred::DeferredComponents;
2-
use anathema_widgets::components::events::{Event, KeyCode, KeyEvent};
2+
use anathema_widgets::components::events::{ComponentEvent, KeyCode, KeyEvent};
33
use anathema_widgets::tabindex::TabIndex;
44

55
pub trait GlobalEventHandler {
66
fn handle(
77
&self,
8-
event: Event,
8+
event: ComponentEvent,
99
tabindex: &mut TabIndex<'_, '_>,
1010
components: &mut DeferredComponents,
11-
) -> Option<Event>;
11+
) -> Option<ComponentEvent>;
1212
}
1313

1414
impl GlobalEventHandler for () {
15-
fn handle(&self, event: Event, tabindex: &mut TabIndex<'_, '_>, _: &mut DeferredComponents) -> Option<Event> {
16-
if let Event::Key(KeyEvent {
15+
fn handle(
16+
&self,
17+
event: ComponentEvent,
18+
tabindex: &mut TabIndex<'_, '_>,
19+
_: &mut DeferredComponents,
20+
) -> Option<ComponentEvent> {
21+
if let ComponentEvent::Key(KeyEvent {
1722
code: KeyCode::Tab,
1823
ctrl: false,
1924
..
@@ -23,7 +28,7 @@ impl GlobalEventHandler for () {
2328
return None;
2429
}
2530

26-
if let Event::Key(KeyEvent {
31+
if let ComponentEvent::Key(KeyEvent {
2732
code: KeyCode::BackTab, ..
2833
}) = event
2934
{
@@ -32,22 +37,22 @@ impl GlobalEventHandler for () {
3237
}
3338

3439
if event.is_ctrl_c() {
35-
return Some(Event::Stop);
40+
return Some(ComponentEvent::Stop);
3641
}
3742
Some(event)
3843
}
3944
}
4045

4146
impl<T> GlobalEventHandler for T
4247
where
43-
T: Fn(Event, &mut TabIndex<'_, '_>, &mut DeferredComponents) -> Option<Event>,
48+
T: Fn(ComponentEvent, &mut TabIndex<'_, '_>, &mut DeferredComponents) -> Option<ComponentEvent>,
4449
{
4550
fn handle(
4651
&self,
47-
event: Event,
52+
event: ComponentEvent,
4853
tabindex: &mut TabIndex<'_, '_>,
4954
components: &mut DeferredComponents,
50-
) -> Option<Event> {
55+
) -> Option<ComponentEvent> {
5156
self(event, tabindex, components)
5257
}
5358
}

anathema-runtime/src/runtime/mod.rs

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use anathema_templates::blueprints::Blueprint;
99
use anathema_templates::{Document, Globals};
1010
use anathema_value_resolver::{AttributeStorage, Scope};
1111
use anathema_widgets::components::deferred::{CommandKind, DeferredComponents};
12-
use anathema_widgets::components::events::Event;
12+
use anathema_widgets::components::events::ComponentEvent;
1313
use anathema_widgets::components::{
1414
AnyComponentContext, AssociatedEvents, ComponentKind, ComponentRegistry, Emitter, ViewMessage,
1515
};
@@ -230,7 +230,7 @@ pub struct Frame<'rt, 'bp, G> {
230230
}
231231

232232
impl<'rt, 'bp, G: GlobalEventHandler> Frame<'rt, 'bp, G> {
233-
pub fn handle_global_event(&mut self, event: Event) -> Option<Event> {
233+
pub fn handle_global_event(&mut self, event: ComponentEvent) -> Option<ComponentEvent> {
234234
let mut changed = false;
235235
let mut tabindex = TabIndex::new(&mut self.tabindex, self.tree.view_mut(), &mut changed);
236236

@@ -257,21 +257,21 @@ impl<'rt, 'bp, G: GlobalEventHandler> Frame<'rt, 'bp, G> {
257257
event
258258
}
259259

260-
pub fn event(&mut self, event: Event) {
260+
pub fn event(&mut self, event: ComponentEvent) {
261261
#[cfg(feature = "profile")]
262262
puffin::profile_function!();
263263

264264
let Some(event) = self.handle_global_event(event) else { return };
265-
if let Event::Stop = event {
265+
if let ComponentEvent::Stop = event {
266266
self.stop = true;
267267
return;
268268
}
269269

270270
match event {
271-
Event::Noop => return,
272-
Event::Stop => todo!(),
271+
ComponentEvent::Noop => return,
272+
ComponentEvent::Stop => todo!(),
273273
// Component specific event
274-
Event::Blur | Event::Focus | Event::Key(_) => {
274+
ComponentEvent::Blur | ComponentEvent::Focus | ComponentEvent::Key(_) => {
275275
let Some(Index {
276276
widget_id, state_id, ..
277277
}) = self.tabindex
@@ -280,13 +280,13 @@ impl<'rt, 'bp, G: GlobalEventHandler> Frame<'rt, 'bp, G> {
280280
};
281281
self.send_event_to_component(event, widget_id, state_id);
282282
}
283-
Event::Mouse(_) | Event::Resize(_) => {
283+
ComponentEvent::Mouse(_) | ComponentEvent::Resize(_) => {
284284
for i in 0..self.layout_ctx.components.len() {
285285
let Some((widget_id, state_id)) = self.layout_ctx.components.get(i) else { continue };
286286
self.send_event_to_component(event, widget_id, state_id);
287287
}
288288
}
289-
Event::Tick(_) => panic!("this event should never be sent to the runtime"),
289+
ComponentEvent::Tick(_) => panic!("this event should never be sent to the runtime"),
290290
}
291291
}
292292

@@ -376,7 +376,7 @@ impl<'rt, 'bp, G: GlobalEventHandler> Frame<'rt, 'bp, G> {
376376

377377
fn poll_events<B: Backend>(&mut self, remaining: Duration, fps_now: Instant, backend: &mut B) {
378378
while let Some(event) = backend.next_event(remaining) {
379-
if let Event::Resize(size) = event {
379+
if let ComponentEvent::Resize(size) = event {
380380
self.layout_ctx.viewport.resize(size);
381381
self.needs_layout = true;
382382
backend.resize(size, self.layout_ctx.glyph_map);
@@ -434,25 +434,36 @@ impl<'rt, 'bp, G: GlobalEventHandler> Frame<'rt, 'bp, G> {
434434
#[cfg(feature = "profile")]
435435
puffin::profile_function!();
436436

437-
while let Some(event) = self.assoc_events.next() {
438-
let Some((widget_id, state_id)) = self.layout_ctx.components.get_by_widget_id(event.parent.into()) else {
439-
return;
440-
};
437+
while let Some(assoc_event) = self.assoc_events.next() {
438+
let mut parent = assoc_event.parent;
439+
let external_ident = self.document.strings.get_ref_unchecked(assoc_event.external());
440+
let internal_ident = self.document.strings.get_ref_unchecked(assoc_event.internal());
441+
let sender = self.document.strings.get_ref_unchecked(assoc_event.sender);
442+
let mut event = assoc_event.to_event(internal_ident, external_ident, sender);
443+
444+
loop {
445+
let Some((widget_id, state_id)) = self.layout_ctx.components.get_by_widget_id(parent.into()) else {
446+
return;
447+
};
448+
449+
let stop_propagation = self
450+
.with_component(widget_id, state_id, |comp, children, ctx| {
451+
let next_parent = ctx.parent();
452+
comp.dyn_component.any_component_event(children, ctx, &mut event);
441453

442-
panic!(
443-
"this is going to be reworked. this was working while SharedState didn't have a lifetime, it does now so... figure it out"
444-
);
445-
// let Some(remote_state) = self.layout_ctx.states.get(event.state) else { return };
446-
// let Some(remote_state) = remote_state.shared_state() else { return };
447-
// self.with_component(widget_id, state_id, |comp, children, ctx| {
448-
// // TODO:
449-
// // Create a new event type
450-
// // if the event is stopped then return from drain_assoc_events
451-
452-
// let event_ident = self.document.strings.get_ref_unchecked(event.external);
453-
// comp.dyn_component
454-
// .any_receive(children, ctx, event_ident, &*remote_state);
455-
// });
454+
parent = match next_parent {
455+
Some(p) => p,
456+
None => return true,
457+
};
458+
459+
event.should_stop_propagation()
460+
})
461+
.unwrap_or(true);
462+
463+
if stop_propagation {
464+
break;
465+
}
466+
}
456467
}
457468
}
458469

@@ -521,7 +532,7 @@ impl<'rt, 'bp, G: GlobalEventHandler> Frame<'rt, 'bp, G> {
521532
Ok(())
522533
}
523534

524-
fn send_event_to_component(&mut self, event: Event, widget_id: WidgetId, state_id: StateId) {
535+
fn send_event_to_component(&mut self, event: ComponentEvent, widget_id: WidgetId, state_id: StateId) {
525536
self.with_component(widget_id, state_id, |comp, elements, ctx| {
526537
comp.dyn_component.any_event(elements, ctx, event);
527538
});
@@ -537,6 +548,7 @@ impl<'rt, 'bp, G: GlobalEventHandler> Frame<'rt, 'bp, G> {
537548
let WidgetKind::Component(component) = &mut container.kind else {
538549
panic!("this is always a component")
539550
};
551+
540552
let Some(state) = self.layout_ctx.states.get_mut(state_id) else {
541553
panic!("a component always has a state")
542554
};
@@ -548,6 +560,7 @@ impl<'rt, 'bp, G: GlobalEventHandler> Frame<'rt, 'bp, G> {
548560

549561
let ctx = AnyComponentContext::new(
550562
component.parent.map(Into::into),
563+
component.name_id,
551564
state_id,
552565
component.assoc_functions,
553566
self.assoc_events,
@@ -570,7 +583,7 @@ impl<'rt, 'bp, G: GlobalEventHandler> Frame<'rt, 'bp, G> {
570583

571584
for i in 0..self.layout_ctx.components.len() {
572585
let Some((widget_id, state_id)) = self.layout_ctx.components.get_ticking(i) else { continue };
573-
let event = Event::Tick(dt);
586+
let event = ComponentEvent::Tick(dt);
574587
self.send_event_to_component(event, widget_id, state_id);
575588
}
576589
}

anathema-state/src/states.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::any::Any;
22
use std::fmt::Debug;
33

4-
use anathema_store::slab::{Slab, SlabIndex};
4+
use anathema_store::slab::{Slab, SlabIndex, Ticket};
55

66
use crate::{Color, Hex, PendingValue, Type, Value};
77

0 commit comments

Comments
 (0)